Installation & Setup Linux Install

OpenClaw on NixOS: Reproducible AI Agent Setup Explained

NixOS is the only Linux distribution where your entire system — including OpenClaw — can be declared in code, version-controlled, and rolled back in seconds. Here's the exact derivation pattern that makes it work reliably.

TC
T. Chen
AI Systems Engineer
Feb 16, 2025 16 min read Linux Install
Updated Feb 2025
Key Takeaways
OpenClaw is not in nixpkgs — you need a custom mkDerivation that wraps the npm package using nodejs_20.
Nix flakes pin nixpkgs exactly, giving you reproducible builds across every machine in your fleet.
Declare OpenClaw as a systemd.services entry in configuration.nix for automatic startup and restart-on-failure.
Never hardcode tokens in configuration.nix — use sops-nix or agenix for encrypted secret management.
Rollback is trivial: nixos-rebuild switch --rollback undoes the last generation in seconds.

Most Linux users install OpenClaw once and hope nothing breaks. NixOS users declare it, version-control it, and rebuild the exact same setup on any machine in 90 seconds flat. The tradeoff is real — you need to write a derivation. But that investment pays back every single time you need to reproduce your setup, migrate to new hardware, or roll back a bad update.

Why NixOS Makes Sense for OpenClaw

OpenClaw runs as a persistent gateway daemon. It needs a stable Node.js runtime, a gateway.yaml config, and environment variables for LLM API keys. On traditional distros, you manage these by hand. On NixOS, every one of these dependencies is declared in code.

The practical benefits are significant. When you upgrade NixOS, your OpenClaw setup upgrades with it — and if something breaks, nixos-rebuild switch --rollback brings back the previous working state. No manual package pinning, no version conflicts, no "works on my machine" surprises.

As of early 2025, OpenClaw is not available in nixpkgs. This means you write a derivation yourself. It's less than 30 lines of Nix code — and once written, it works forever.

ℹ️
NixOS Knowledge Assumed
This guide assumes you have a working NixOS installation with flakes enabled. If you're new to NixOS, read the official NixOS manual chapter on flakes before proceeding.

Writing the OpenClaw Derivation

The simplest approach fetches OpenClaw from npm and wraps it in a Nix derivation. Create a file called openclaw.nix in your config directory:

{ lib, stdenv, nodejs_20, fetchurl }:

let
  nodeEnv = nodejs_20;
in stdenv.mkDerivation rec {
  pname = "openclaw";
  version = "1.0.0";

  src = fetchurl {
    url = "https://registry.npmjs.org/openclaw/-/openclaw-${version}.tgz";
    sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
  };

  buildInputs = [ nodeEnv ];

  buildPhase = ''
    mkdir -p $out/lib/node_modules/openclaw
    cp -r . $out/lib/node_modules/openclaw
    cd $out/lib/node_modules/openclaw
    ${nodeEnv}/bin/npm install --production --ignore-scripts
  '';

  installPhase = ''
    mkdir -p $out/bin
    cat > $out/bin/openclaw << 'EOF'
#!/usr/bin/env bash
exec ${nodeEnv}/bin/node ${out}/lib/node_modules/openclaw/bin/openclaw.js "$@"
EOF
    chmod +x $out/bin/openclaw
  '';

  meta = with lib; {
    description = "OpenClaw AI agent gateway";
    license = licenses.mit;
    platforms = platforms.linux;
  };
}

Replace the sha256 placeholder with the actual hash. To get it, run nix-prefetch-url --unpack https://registry.npmjs.org/openclaw/-/openclaw-1.0.0.tgz and paste the result.

⚠️
Hash Must Be Exact
If the sha256 hash is wrong, the Nix build will fail with a hash mismatch error. Always use nix-prefetch-url to generate the correct hash — never guess or leave the placeholder value.

Flake Setup

A flake ties everything together and pins nixpkgs to an exact commit. Your flake.nix:

{
  description = "NixOS system with OpenClaw";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, ... }:
  let
    system = "x86_64-linux";
    pkgs = import nixpkgs { inherit system; };
    openclaw = pkgs.callPackage ./openclaw.nix {};
  in {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      inherit system;
      modules = [
        ./configuration.nix
        {
          environment.systemPackages = [ openclaw ];
        }
      ];
    };
  };
}

Run nixos-rebuild switch --flake .#myhost from your config directory. Nix will build the derivation, install the binary, and apply your configuration.

Declaring the Systemd Service

Add this block to your configuration.nix to run OpenClaw as a persistent system service:

systemd.services.openclaw = {
  description = "OpenClaw AI Agent Gateway";
  after = [ "network.target" ];
  wantedBy = [ "multi-user.target" ];

  environment = {
    OPENCLAW_GATEWAY_TOKEN = "your-token-here";  # use sops-nix in production
    NODE_ENV = "production";
  };

  serviceConfig = {
    Type = "simple";
    User = "openclaw";
    Group = "openclaw";
    WorkingDirectory = "/var/lib/openclaw";
    ExecStart = "${openclaw}/bin/openclaw gateway start";
    Restart = "on-failure";
    RestartSec = "5s";
    StateDirectory = "openclaw";
  };
};

users.users.openclaw = {
  isSystemUser = true;
  group = "openclaw";
  home = "/var/lib/openclaw";
};

users.groups.openclaw = {};

After rebuilding, verify the service: systemctl status openclaw. You should see active (running). Logs go to the journal: journalctl -u openclaw -f.

Home-Manager Option

If you prefer OpenClaw scoped to a single user rather than system-wide, home-manager is the cleaner path. Add to your home-manager config:

home.packages = [ openclaw ];

systemd.user.services.openclaw = {
  Unit = {
    Description = "OpenClaw AI Agent Gateway";
    After = "network.target";
  };

  Service = {
    ExecStart = "${openclaw}/bin/openclaw gateway start";
    Restart = "on-failure";
    Environment = "NODE_ENV=production";
  };

  Install = {
    WantedBy = [ "default.target" ];
  };
};

Enable and start it: systemctl --user enable openclaw && systemctl --user start openclaw. This approach is ideal for multi-user NixOS machines where each user runs their own OpenClaw instance with separate gateway configurations.

💡
Home-Manager Autostart
Add systemd.user.startServices = "sd-switch" to your home-manager config. This starts and stops user services automatically when you run home-manager switch, eliminating the manual systemctl step.

Managing Secrets Declaratively

Hardcoding OPENCLAW_GATEWAY_TOKEN directly in configuration.nix is a security mistake — the value ends up in the world-readable Nix store at /nix/store. Use sops-nix instead.

Install sops-nix as a flake input, create an encrypted secrets file with your token, and reference it in your service config:

sops.secrets.openclaw_token = {
  sopsFile = ./secrets/openclaw.yaml;
};

systemd.services.openclaw.environment = {
  OPENCLAW_GATEWAY_TOKEN_FILE = config.sops.secrets.openclaw_token.path;
};

The secret file is decrypted at runtime using your machine's SSH host key. The plaintext value never appears in the Nix store. This is the production-grade approach — anything else creates a secrets leak.

Common Mistakes on NixOS

  • Wrong sha256 hash — always regenerate with nix-prefetch-url after version bumps, never copy-paste from other derivations
  • Forgetting StateDirectory — without it, /var/lib/openclaw won't exist and OpenClaw can't write its config files
  • Using nix-env instead of flakes — nix-env installs are not tracked in configuration.nix and break reproducibility
  • Hardcoded secrets in configuration.nix — these land in the Nix store under /nix/store and are world-readable by all system users
  • Missing network.target ordering — OpenClaw needs network access at startup; without after = [ "network.target" ] the service may start before networking is ready

Frequently Asked Questions

Can I install OpenClaw on NixOS using nix-env?

OpenClaw is not in nixpkgs yet, so nix-env won't find it directly. Use a custom derivation that fetches the npm package or wraps the nodejs runtime. Flakes are the cleanest approach — pin nixpkgs, write a mkDerivation, and add it to your system packages.

How do I run OpenClaw as a NixOS systemd service?

Define a systemd.services.openclaw block in your NixOS configuration. Set User, WorkingDirectory, ExecStart to the openclaw binary from your derivation, and Restart to on-failure. Run nixos-rebuild switch and systemctl status openclaw to verify the service is active.

Does OpenClaw work with home-manager on NixOS?

Yes. Add a home.packages entry for your openclaw derivation and a systemd.user.services.openclaw block in home-manager config. This keeps OpenClaw scoped to your user rather than system-wide — useful for multi-user NixOS machines.

How do I store OpenClaw environment variables declaratively in NixOS?

Use environment.systemPackages for the binary and systemd.services.openclaw.environment for runtime vars like OPENCLAW_GATEWAY_TOKEN. For secrets, use sops-nix or agenix to encrypt values in your Nix config — never hardcode tokens in configuration.nix.

What Node.js version does OpenClaw need on NixOS?

OpenClaw requires Node.js 18 or newer. In your NixOS derivation, specify nodejs_20 from nixpkgs as the runtime. Pin nixpkgs to a stable channel that includes Node.js 20 LTS — nixos-23.11 or newer all include it.

How do I update OpenClaw on NixOS without breaking reproducibility?

Update the version string and sha256 hash in your derivation, then run nixos-rebuild switch. The old version stays in the Nix store until you run nix-collect-garbage. This gives you trivial rollback — just point your flake input back to the previous revision.

TC
T. Chen
AI Systems Engineer
T. Chen has deployed OpenClaw across NixOS, Alpine, and container environments for production AI agent workloads. Specializes in reproducible infrastructure and declarative system configuration for distributed AI pipelines.
Stay Current
New OpenClaw guides every week — straight to your inbox.