diff --git a/common/sandboxed-workspace/base.nix b/common/sandboxed-workspace/base.nix index 548ed27..10be233 100644 --- a/common/sandboxed-workspace/base.nix +++ b/common/sandboxed-workspace/base.nix @@ -11,6 +11,17 @@ { config, lib, pkgs, ... }: +let + claudeConfigFile = pkgs.writeText "claude-config.json" (builtins.toJSON { + hasCompletedOnboarding = true; + theme = "dark"; + projects = { + "/home/googlebot/workspace" = { + hasTrustDialogAccepted = true; + }; + }; + }); +in { imports = [ ../shell.nix @@ -112,6 +123,22 @@ # Enable fish shell programs.fish.enable = true; + # Initialize Claude Code config on first boot (skips onboarding, trusts workspace) + systemd.services.claude-config-init = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = "googlebot"; + Group = "users"; + }; + script = '' + if [ ! -f /home/googlebot/claude-config/.claude.json ]; then + cp ${claudeConfigFile} /home/googlebot/claude-config/.claude.json + fi + ''; + }; + # Home Manager configuration home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; diff --git a/common/sandboxed-workspace/container.nix b/common/sandboxed-workspace/container.nix index 642fcfc..21c9eb5 100644 --- a/common/sandboxed-workspace/container.nix +++ b/common/sandboxed-workspace/container.nix @@ -47,16 +47,10 @@ in hostPath = "/home/googlebot/sandboxed/${name}/ssh-host-keys"; isReadOnly = false; }; - # Per-workspace claude config for isolated session data "/home/googlebot/claude-config" = { hostPath = "/home/googlebot/sandboxed/${name}/claude-config"; 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, ... }: { diff --git a/common/sandboxed-workspace/default.nix b/common/sandboxed-workspace/default.nix index 1bc77df..6937a86 100644 --- a/common/sandboxed-workspace/default.nix +++ b/common/sandboxed-workspace/default.nix @@ -122,45 +122,13 @@ in cfg.workspaces); # Automatically generate SSH host keys and directories for all workspaces - systemd.services = lib.mkMerge [ - # Create credentials-only directory for VMs (symlinks to actual credentials) - { - claude-credentials-dir = { - description = "Setup Claude credentials directory for VM workspaces"; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - User = "googlebot"; - Group = "users"; - }; - script = '' - mkdir -p /home/googlebot/.claude-credentials - # Copy credentials file (not symlink - virtiofs can't follow host symlinks) - if [ -f /home/googlebot/.claude/.credentials.json ]; then - cp /home/googlebot/.claude/.credentials.json /home/googlebot/.claude-credentials/.credentials.json - chmod 600 /home/googlebot/.claude-credentials/.credentials.json - fi - ''; - }; - } - # Per-workspace setup services - (lib.mapAttrs' + systemd.services = lib.mapAttrs' (name: ws: let serviceName = if ws.type == "vm" then "microvm@${name}" else if ws.type == "incus" then "incus-workspace-${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}"; @@ -188,23 +156,9 @@ in 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 - '' + lib.optionalString (ws.type == "incus") '' - # Copy credentials for incus (can't use bind mount for files inside another mount) - if [ -f /home/googlebot/.claude/.credentials.json ]; then - cp /home/googlebot/.claude/.credentials.json /home/googlebot/sandboxed/${name}/claude-config/.credentials.json - chown googlebot:users /home/googlebot/sandboxed/${name}/claude-config/.credentials.json - chmod 600 /home/googlebot/sandboxed/${name}/claude-config/.credentials.json - fi ''; } ) - cfg.workspaces) - ]; + cfg.workspaces; }; } diff --git a/common/sandboxed-workspace/incus.nix b/common/sandboxed-workspace/incus.nix index 55bc57a..17565b2 100644 --- a/common/sandboxed-workspace/incus.nix +++ b/common/sandboxed-workspace/incus.nix @@ -31,6 +31,12 @@ let boot.isContainer = true; networking.useHostResolvConf = false; nixpkgs.config.allowUnfree = true; + + environment.systemPackages = [ + (lib.hiPrio (pkgs.writeShellScriptBin "claude" '' + exec ${pkgs.claude-code}/bin/claude --dangerously-skip-permissions "$@" + '')) + ]; }) ]; }; diff --git a/common/sandboxed-workspace/vm.nix b/common/sandboxed-workspace/vm.nix index 4ca3073..cf2ac27 100644 --- a/common/sandboxed-workspace/vm.nix +++ b/common/sandboxed-workspace/vm.nix @@ -58,20 +58,11 @@ let networkInterface = { Type = "ether"; }; }) { - # Copy credentials from host mount to per-workspace config - systemd.services.claude-credentials = { - description = "Copy Claude credentials from host"; - wantedBy = [ "multi-user.target" ]; - before = [ "multi-user.target" ]; - serviceConfig.Type = "oneshot"; - script = '' - if [ -f /home/googlebot/.claude-credentials/.credentials.json ]; then - install -m 600 -o googlebot -g users \ - /home/googlebot/.claude-credentials/.credentials.json \ - /home/googlebot/claude-config/.credentials.json - fi - ''; - }; + environment.systemPackages = [ + (lib.hiPrio (pkgs.writeShellScriptBin "claude" '' + exec ${pkgs.claude-code}/bin/claude --dangerously-skip-permissions "$@" + '')) + ]; # MicroVM specific configuration microvm = { @@ -116,14 +107,6 @@ let source = "/home/googlebot/sandboxed/${name}/claude-config"; mountPoint = "/home/googlebot/claude-config"; } - { - # Credentials-only directory (read-only) - # This directory should contain only .credentials.json - proto = "virtiofs"; - tag = "claude-credentials"; - source = "/home/googlebot/.claude-credentials"; - mountPoint = "/home/googlebot/.claude-credentials"; - } ]; # Writeable overlay for /nix/store