Configure Claude Code for sandboxed workspaces
- Add credentials bind mount in container.nix - Create claude-credentials-dir service to copy credentials for VMs - Generate .claude.json with onboarding skipped and workspace trusted - Add allowUnfree to container config
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
{ config, lib, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
# Container-specific configuration for sandboxed workspaces using systemd-nspawn
|
# Container-specific configuration for sandboxed workspaces using systemd-nspawn
|
||||||
# This module is imported by default.nix for workspaces with type = "container"
|
# This module is imported by default.nix for workspaces with type = "container"
|
||||||
@@ -47,10 +47,16 @@ in
|
|||||||
hostPath = "/home/googlebot/sandboxed/${name}/ssh-host-keys";
|
hostPath = "/home/googlebot/sandboxed/${name}/ssh-host-keys";
|
||||||
isReadOnly = false;
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
|
# Per-workspace claude config for isolated session data
|
||||||
"/home/googlebot/claude-config" = {
|
"/home/googlebot/claude-config" = {
|
||||||
hostPath = "/home/googlebot/sandboxed/${name}/claude-config";
|
hostPath = "/home/googlebot/sandboxed/${name}/claude-config";
|
||||||
isReadOnly = false;
|
isReadOnly = false;
|
||||||
};
|
};
|
||||||
|
# Share credentials from host (read-only)
|
||||||
|
"/home/googlebot/claude-config/.credentials.json" = {
|
||||||
|
hostPath = "/home/googlebot/.claude/.credentials.json";
|
||||||
|
isReadOnly = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = { config, lib, pkgs, ... }: {
|
config = { config, lib, pkgs, ... }: {
|
||||||
@@ -65,6 +71,8 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
networking.useHostResolvConf = false;
|
networking.useHostResolvConf = false;
|
||||||
|
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
containerWorkspaces;
|
containerWorkspaces;
|
||||||
|
|||||||
@@ -118,40 +118,79 @@ in
|
|||||||
cfg.workspaces);
|
cfg.workspaces);
|
||||||
|
|
||||||
# Automatically generate SSH host keys and directories for all workspaces
|
# Automatically generate SSH host keys and directories for all workspaces
|
||||||
systemd.services = lib.mapAttrs'
|
systemd.services = lib.mkMerge [
|
||||||
(name: ws:
|
# Create credentials-only directory for VMs (symlinks to actual credentials)
|
||||||
let
|
{
|
||||||
serviceName = if ws.type == "vm" then "microvm@${name}" else "container@${name}";
|
claude-credentials-dir = {
|
||||||
in
|
description = "Setup Claude credentials directory for VM workspaces";
|
||||||
lib.nameValuePair "workspace-${name}-setup" {
|
|
||||||
description = "Setup directories and SSH keys for workspace ${name}";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
before = [ "${serviceName}.service" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
|
User = "googlebot";
|
||||||
|
Group = "users";
|
||||||
};
|
};
|
||||||
|
|
||||||
script = ''
|
script = ''
|
||||||
# Create directories if they don't exist
|
mkdir -p /home/googlebot/.claude-credentials
|
||||||
mkdir -p /home/googlebot/sandboxed/${name}/workspace
|
# Copy credentials file (not symlink - virtiofs can't follow host symlinks)
|
||||||
mkdir -p /home/googlebot/sandboxed/${name}/ssh-host-keys
|
if [ -f /home/googlebot/.claude/.credentials.json ]; then
|
||||||
mkdir -p /home/googlebot/sandboxed/${name}/claude-config
|
cp /home/googlebot/.claude/.credentials.json /home/googlebot/.claude-credentials/.credentials.json
|
||||||
|
chmod 600 /home/googlebot/.claude-credentials/.credentials.json
|
||||||
# Fix ownership
|
|
||||||
chown -R googlebot:users /home/googlebot/sandboxed/${name}
|
|
||||||
|
|
||||||
# Generate SSH host key if it doesn't exist
|
|
||||||
if [ ! -f /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key ]; then
|
|
||||||
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" \
|
|
||||||
-f /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key
|
|
||||||
chown googlebot:users /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key*
|
|
||||||
echo "Generated SSH host key for workspace ${name}"
|
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
}
|
};
|
||||||
)
|
}
|
||||||
cfg.workspaces;
|
# Per-workspace setup services
|
||||||
|
(lib.mapAttrs'
|
||||||
|
(name: ws:
|
||||||
|
let
|
||||||
|
serviceName = if ws.type == "vm" then "microvm@${name}" else "container@${name}";
|
||||||
|
claudeConfig = builtins.toJSON {
|
||||||
|
hasCompletedOnboarding = true;
|
||||||
|
theme = "dark";
|
||||||
|
projects = {
|
||||||
|
"/home/googlebot/workspace" = {
|
||||||
|
hasTrustDialogAccepted = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
lib.nameValuePair "workspace-${name}-setup" {
|
||||||
|
description = "Setup directories and SSH keys for workspace ${name}";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "${serviceName}.service" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
# Create directories if they don't exist
|
||||||
|
mkdir -p /home/googlebot/sandboxed/${name}/workspace
|
||||||
|
mkdir -p /home/googlebot/sandboxed/${name}/ssh-host-keys
|
||||||
|
mkdir -p /home/googlebot/sandboxed/${name}/claude-config
|
||||||
|
|
||||||
|
# Fix ownership
|
||||||
|
chown -R googlebot:users /home/googlebot/sandboxed/${name}
|
||||||
|
|
||||||
|
# Generate SSH host key if it doesn't exist
|
||||||
|
if [ ! -f /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key ]; then
|
||||||
|
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" \
|
||||||
|
-f /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key
|
||||||
|
chown googlebot:users /home/googlebot/sandboxed/${name}/ssh-host-keys/ssh_host_ed25519_key*
|
||||||
|
echo "Generated SSH host key for workspace ${name}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create claude-code config to skip onboarding and trust ~/workspace
|
||||||
|
if [ ! -f /home/googlebot/sandboxed/${name}/claude-config/.claude.json ]; then
|
||||||
|
echo '${claudeConfig}' > /home/googlebot/sandboxed/${name}/claude-config/.claude.json
|
||||||
|
chown googlebot:users /home/googlebot/sandboxed/${name}/claude-config/.claude.json
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cfg.workspaces)
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user