--- name: create-workspace description: > Creates a new sandboxed workspace (isolated dev environment) by adding NixOS configuration for a VM, container, or Incus instance. Use when the user wants to create, set up, or add a new sandboxed workspace. --- # Create Sandboxed Workspace Creates an isolated development environment backed by a VM (microvm.nix), container (systemd-nspawn), or Incus instance. This produces: 1. A workspace config file at `machines//workspaces/.nix` 2. A registration entry in `machines//default.nix` ## Step 1: Parse Arguments Extract the workspace name and backend type from `$ARGUMENTS`. If either is missing, ask the user. - **Name**: lowercase alphanumeric with hyphens (e.g., `my-project`) - **Type**: one of `vm`, `container`, or `incus` ## Step 2: Detect Machine Run `hostname` to get the current machine name. Verify that `machines//default.nix` exists. If the machine directory doesn't exist, stop and tell the user this machine isn't managed by this flake. ## Step 3: Allocate IP Address Read `machines//default.nix` to find existing `sandboxed-workspace.workspaces` entries and their IPs. All IPs are in the `192.168.83.0/24` subnet. Use these ranges by convention: | Type | IP Range | |------|----------| | vm | 192.168.83.10 - .49 | | container | 192.168.83.50 - .89 | | incus | 192.168.83.90 - .129 | Pick the next available IP in the appropriate range. If no workspaces exist yet for that type, use the first IP in the range. ## Step 4: Create Workspace Config File Create `machines//workspaces/.nix`. Use this template: ```nix { config, lib, pkgs, ... }: { environment.systemPackages = with pkgs; [ # Add packages here ]; } ``` Ask the user if they want any packages pre-installed. Create the `workspaces/` directory if it doesn't exist. **Important:** After creating the file, run `git add` on it immediately. Nix flakes only see files tracked by git, so new files must be staged before `nix build` will work. ## Step 5: Register Workspace Edit `machines//default.nix` to add the workspace entry inside the `sandboxed-workspace` block. The entry should look like: ```nix workspaces. = { type = ""; config = ./workspaces/.nix; ip = ""; }; ``` **If `sandboxed-workspace` block doesn't exist yet**, add the full block: ```nix sandboxed-workspace = { enable = true; workspaces. = { type = ""; config = ./workspaces/.nix; ip = ""; }; }; ``` The machine also needs `networking.sandbox.upstreamInterface` set. Check if it exists; if not, ask the user for their primary network interface name (they can find it with `ip route show default`). Do **not** set `hostKey` — it gets auto-generated on first boot and can be added later. ## Step 6: Verify Build Run a build to check for configuration errors: ``` nix build .#nixosConfigurations..config.system.build.toplevel --no-link ``` If the build fails, fix the configuration and retry. ## Step 7: Deploy Tell the user to deploy by running: ``` doas nixos-rebuild switch --flake . ``` **Never run this command yourself** — it requires privileges. ## Step 8: Post-Deploy Info Tell the user to deploy and then start the workspace so the host key gets generated. Provide these instructions: **Deploy:** ``` doas nixos-rebuild switch --flake . ``` **Starting the workspace:** ``` doas systemctl start ``` Where `` is: - VM: `microvm@` - Container: `container@` - Incus: `incus-workspace-` Or use the auto-generated shell alias: `workspace__start` **Connecting:** ``` ssh googlebot@workspace- ``` Or use the alias: `workspace_` **Never run deploy or start commands yourself** — they require privileges. ## Step 9: Add Host Key After the user has deployed and started the workspace, add the SSH host key to the workspace config. Do NOT skip this step — always wait for the user to confirm they've started the workspace, then proceed. 1. Read the host key from `~/sandboxed//ssh-host-keys/ssh_host_ed25519_key.pub` 2. Add `hostKey = "";` to the workspace entry in `machines//default.nix` 3. Run the build again to verify 4. Tell the user to redeploy with `doas nixos-rebuild switch --flake .` ## Backend Reference | | VM | Container | Incus | |---|---|---|---| | Isolation | Full kernel (cloud-hypervisor) | Shared kernel (systemd-nspawn) | Unprivileged container | | Overhead | Higher (separate kernel) | Lower (bind mounts) | Medium | | Filesystem | virtiofs shares | Bind mounts | Incus-managed | | Use case | Untrusted code, kernel-level isolation | Fast dev environments | Better security than nspawn |