Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 117 additions & 5 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
url = "github:papercomputeco/stereosd";
inputs.nixpkgs.follows = "nixpkgs";
};

nix-openclaw = {
url = "github:openclaw/nix-openclaw";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = inputs@{ flake-parts, ... }:
Expand Down Expand Up @@ -72,6 +77,11 @@
features = [ ./mixtapes/full/base.nix ];
};

openclaw-mixtape = stereos-lib.mkMixtape {
name = "openclaw-mixtape";
features = [ ./mixtapes/openclaw/base.nix ];
};

# -- Dev configurations (SSH key injection) --------------------------
opencode-mixtape-dev = stereos-lib.mkMixtape {
name = "opencode-mixtape";
Expand All @@ -96,6 +106,12 @@
features = [ ./mixtapes/full/base.nix ];
extraModules = [ ./profiles/dev.nix ];
};

openclaw-mixtape-dev = stereos-lib.mkMixtape {
name = "openclaw-mixtape";
features = [ ./mixtapes/openclaw/base.nix ];
extraModules = [ ./profiles/dev.nix ];
};
};
};
};
Expand Down
12 changes: 8 additions & 4 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Build a complete NixOS system configuration ("mixtape") from:
# - The shared stereOS module tree (modules/)
# - A profile (profiles/base.nix)
# - External flake modules (agentd, stereosd) + overlays
# - External flake modules (agentd, stereosd, nix-openclaw) + overlays
# - Mixtape-specific feature modules
#
# For dev builds, include profiles/dev.nix via extraModules to get
Expand All @@ -28,16 +28,20 @@
inputs.nixpkgs.lib.nixosSystem {
inherit system;
modules = [
# External flake NixOS modules -- provide services.agentd and
# services.stereosd options + baseline systemd units.
# External flake NixOS modules -- provide services.agentd,
# services.stereosd, and services.openclaw-gateway options +
# baseline systemd units.
inputs.agentd.nixosModules.default
inputs.stereosd.nixosModules.default
inputs.nix-openclaw.nixosModules.openclaw-gateway

# Apply overlays so pkgs.agentd and pkgs.stereosd are available.
# Apply overlays so pkgs.agentd, pkgs.stereosd, and
# pkgs.openclaw-gateway are available.
({ ... }: {
nixpkgs.overlays = [
inputs.agentd.overlays.default
inputs.stereosd.overlays.default
inputs.nix-openclaw.overlays.default
];
})

Expand Down
1 change: 1 addition & 0 deletions mixtapes/full/base.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
../opencode/base.nix
../claude-code/base.nix
../gemini-cli/base.nix
../openclaw/base.nix
];
}
39 changes: 39 additions & 0 deletions mixtapes/openclaw/base.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# mixtapes/openclaw/base.nix
#
# OpenClaw mixtape — self-hosted, open-source personal AI assistant.
#
# OpenClaw routes messages from 15+ chat platforms through a local Gateway
# to any LLM backend, executing real-world tasks autonomously. The entire
# runtime is a single long-lived Node.js process (the Gateway) listening on
# ws://127.0.0.1:18789 by default.
#
# Package: from github:openclaw/nix-openclaw flake (overlay: pkgs.openclaw-gateway)
# Binary: openclaw (Gateway daemon + CLI)
# Service: openclaw-gateway.service (systemd, runs as dedicated 'openclaw' user)
#
# Required environment variables at runtime:
# ANTHROPIC_API_KEY or OPENAI_API_KEY (depending on configured provider)
# Plus channel tokens as needed (TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, etc.)
#
# Secrets are injected at boot by stereosd into /run/stereos/secrets/ and
# loaded via the systemd EnvironmentFile mechanism.

{ config, lib, pkgs, ... }:

{
imports = [
./service.nix
];

# Add the openclaw CLI to the agent's restricted PATH so the agent can
# interact with the running Gateway over WebSocket.
stereos.agent.extraPackages = [ pkgs.openclaw-gateway ];

# Also make it available system-wide (for admin use / debugging)
environment.systemPackages = [ pkgs.openclaw-gateway ];

# Disable auto-update and self-mutation flows — Nix manages the package.
# When this is set, openclaw skips update checks and shows Nix-specific
# remediation messages in the Control UI.
environment.variables.OPENCLAW_NIX_MODE = "1";
}
71 changes: 71 additions & 0 deletions mixtapes/openclaw/service.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# mixtapes/openclaw/service.nix
#
# OpenClaw Gateway systemd service for stereOS.
#
# Runs the Gateway daemon as a dedicated 'openclaw' system user with state
# in /var/lib/openclaw. The agent user interacts with the Gateway over its
# WebSocket API (ws://127.0.0.1:18789) or via the `openclaw` CLI.
#
# This module uses the NixOS service options from the nix-openclaw flake
# (services.openclaw-gateway.*) which handles:
# - System user/group creation
# - State directory tmpfiles rules
# - Config file generation from Nix attrsets
# - systemd service definition with logging
#
# Secret injection:
# API keys and channel tokens are injected at boot by stereosd into
# /run/stereos/secrets/. The service loads them via EnvironmentFile.
# Example secrets file (/run/stereos/secrets/openclaw.env):
# ANTHROPIC_API_KEY=sk-ant-...
# TELEGRAM_BOT_TOKEN=123456:ABC-...
# OPENCLAW_GATEWAY_TOKEN=<gateway-auth-token>

{ config, lib, pkgs, ... }:

{
services.openclaw-gateway = {
enable = true;
port = 18789;

user = "openclaw";
group = "openclaw";
stateDir = "/var/lib/openclaw";

# Gateway configuration — generates /etc/openclaw/openclaw.json
config = {
gateway = {
mode = "local";
bind = "loopback";
};

# Memory uses SQLite with FTS5 + sqlite-vec for search.
# Embedding model auto-selects: local GGUF -> OpenAI -> Gemini -> BM25.
# No additional config needed — defaults are sensible.
};

# Load secrets from stereosd-injected environment file.
# The leading '-' tells systemd to silently skip if the file is absent
# (e.g. during first boot before stereosd has injected secrets).
environmentFiles = [
"-/run/stereos/secrets/openclaw.env"
];

# Extra packages available to the Gateway process at runtime
servicePath = with pkgs; [
git
curl
];
};

# -- Service ordering: start after stereosd has injected secrets -----------
systemd.services.openclaw-gateway = {
after = [ "stereosd.service" ];
wants = [ "stereosd.service" ];
};

# -- Firewall: Gateway is loopback-only, no ports to open -----------------
# The WebSocket endpoint (127.0.0.1:18789) is only reachable from within
# the VM. If remote access is needed in the future, a reverse proxy
# (Caddy/nginx) with TLS should front the Gateway.
}