AI spaces
An AI space is a DNF host with the ai-space profile, generally a
microVM guest. It hosts an assistant
OpenClaw 🡕 reserved for its members, with its own secrets
and its own data.
Create a space
Section titled “Create a space”-
Declare the host and its members
The host’s
usersare its members: DNF creates the Kanidm groupspace-<hôte>for them.etc/config.yaml - hostname: "ia-pro"zone: "lan:1.40"profile: "ai-space"features: ["microvm-guest:hyperviseur", "monitoring-node"]users: ["alice", "bob"]services:openclaw: {}monitoring-nodeplaces the space under the zone’s supervision: without it, neither a space failure nor an assistant shutdown triggers an alert.The owner is the member whose subscription runs the assistant: they receive validation requests and unsolicited messages (reminders, scheduled tasks). If the sole member, it is implicit. With multiple members, it is declared in
usr/machines/ia-pro/configuration.nix(the order ofusersis not preserved):{ darkone.service.openclaw.owner = "alice"; } -
Initialize the space
just space-init ia-pro: host key, secrets (see Isolated hosts) and, if the network has Matrix, the bot@ia-pro:<domaine>. Then commitusr/secrets/andvar/generated/spaces/. -
Deploy
The hypervisor, the zone gateway (vhost, DNS) and the HCS (Kanidm group):
just apply hyperviseur,gw,hcs. -
Connect the AI provider
Once per space, from the host (
just enter ia-pro), depending on the space’s model (darkone.service.openclaw.model):Model Subscription Connection anthropic/*(default:anthropic/claude-sonnet-5-5)Claude Pro/Max, via the claudeCLIsudo -u openclaw -H claude auth loginopenai/*ChatGPT Plus/Pro, via the codexpluginopenclaw models auth login --provider openaiThe host’s
openclawcommand automatically switches to the service user.openclaw models statuschecks the connection, which stays in/var/lib/openclaw, persistent.
Matrix
Section titled “Matrix”Members write to the bot @<hôte>:<domaine> in direct message, end-to-end
encrypted. The channel only exists if the network declares the matrix
service: without it, the space runs on its web interface alone.
| Element | Rule |
|---|---|
| Who is listened to | The space’s members (@<login>:<domaine>), DM only; other accounts are ignored |
| Rooms | Ignored: non-members would read the replies there |
| Sessions | One per member when there are several, otherwise a single one for all channels |
| Command validation | None by default (see Security); any request goes to the owner, via DM |
| Unsolicited messages | Sent to the owner, via DM |
| Encryption keys | In /var/lib/openclaw, persistent |
Agent tools
Section titled “Agent tools”MCP servers, skills and tools are declared once per space, in
usr/machines/<hôte>/configuration.nix. The assistant and each member
(Claude Code, Codex) receive the same ones.
{ pkgs, ... }:{ darkone.host.ai-space = { mcp.fetch = { command = "uvx"; args = [ "mcp-server-fetch" ]; }; mcp.github = { command = "github-mcp-server"; args = [ "stdio" ]; secretEnv = [ "GITHUB_PERSONAL_ACCESS_TOKEN" ]; }; mcp.docs.url = "https://mcp.example.com/mcp"; skills.rapport = ./skills/rapport; # dossier avec SKILL.md packages = [ pkgs.uv pkgs.pandoc pkgs.github-mcp-server ]; };
darkone.service.openclaw = { workspace."AGENTS.md" = ./AGENTS.md; projects.notes = "https://forge.example.com/alice/notes.git"; };}| Option | Role |
|---|---|
darkone.host.ai-space.mcp | MCP servers, local (command, args, env, secretEnv) or remote (url, headers) |
darkone.host.ai-space.skills | Skills by name: content of SKILL.md, file or directory |
darkone.host.ai-space.packages | Tools in the assistant’s PATH and for members |
darkone.host.ai-space.enableClaude, enableCodex | Claude Code and Codex, enabled by default |
darkone.service.openclaw.exec | Command policy (see Security) |
darkone.service.openclaw.identity | Assistant name, emoji and avatar (name, emoji, avatar): the configuration being read-only, the assistant cannot change them itself |
darkone.service.openclaw.workspace | Assistant workspace files (AGENTS.md, SOUL.md…) |
darkone.service.openclaw.projects | Git repositories cloned once into workspace/projects/<nom> |
darkone.service.openclaw.transcription | Local transcription of voice notes (whisper.cpp) |
Voice notes, Matrix or web, are transcribed on the space with whisper.cpp’s
small model (466 MB, on CPU), with no external service. The language is
detected per note; transcription.language = "fr" sets it.
Member accounts
Section titled “Member accounts”Each member has a Linux account on the space, trimmed down:
| Element | On the space |
|---|---|
| Home Manager profile | space-member (zsh, git, vim, tmux), instead of their own |
| Space tools | Claude Code and Codex, with the space’s MCP and skills (darkone.home.aiSpace) |
| Customizations | usr/users/<login>/space.nix (all their spaces), then usr/users/<login>/spaces/<hôte>.nix (this space), if they exist |
usr/users/<login>/default.nix | Ignored: reserved for their workstations |
| Rights | No group (no sudo), regardless of their profile |
Administration of the space goes through the nix account
(just enter <hôte>).
Each member connects their own subscriptions, once: claude (then /login)
and codex login --device-auth.
Access
Section titled “Access”| Element | Rule |
|---|---|
| Address | https://openclaw.<zone>.<domaine> |
| Login | Kanidm SSO, reserved to the space-<hôte> group |
| Device | Paired on first visit, with no administration or validation rights (owner only) |
| Administration | openclaw … on the host, from the nix account |
| Assistant port | Reachable from the zone gateway only |
Security
Section titled “Security”By default, the assistant runs its commands without validation, like
OpenClaw: the barrier is the space itself (microVM cut off from the LAN,
secrets specific to the space). Its service is additionally confined: it only
writes to /var/lib/openclaw and sees neither members’ directories nor
processes.
darkone.service.openclaw.exec chooses the policy:
| Value | Commands |
|---|---|
full (default) | All, without validation |
ask | Allowlist ones pass, the rest are submitted to the owner |
auto | A model examines those outside the allowlist and submits doubtful cases to the owner |
allowlist | Allowlist ones only |
deny | None |
The allowlist is filled on the host:
openclaw approvals allowlist add --agent main <chemin>.