Specimen Report · Shell

cobalt-crucible

phiat/cobalt-crucible

Incus dev container setup for WSL2 — multi-language toolchain in one command

Stars
★ 1
Forks
⑂ 0
Language
Shell
Size
39 kB
Last Push
2mo ago
Forged
3mo ago
dev-containerdevtoolsincuslinuxmisewsl2
# cobalt-crucible Automated setup for Ubuntu 24.04 development containers using Incus on Ubuntu 24.04 running in WSL2. This provisions isolated, resource-limited Ubuntu 24.04 containers from your Ubuntu 24.04 WSL2 host. Each container includes a full polyglot dev environment (Node, Go, Rust, Erlang, Elixir, Python, Java, Clojure, Zig, Bun) managed by mise, plus Podman, Tailscale, Claude Code, OpenCode, and a configured zsh/tmux setup. **Use case**: Spin up clean, reproducible dev environments in seconds (after first build), snapshot them for reuse, and enforce resource limits (memory/CPU) per container. ## Setup ```bash # 1. Install Incus and add user to incus-admin group sudo add-apt-repository -y universe sudo apt update sudo apt install -y incus sudo incus admin init --auto sudo usermod -aG incus-admin $USER # 2. Clone repo if not already in it if [ ! -f setup.sh ]; then git clone https://github.com/phiat/cobalt-crucible.git cd cobalt-crucible fi # 3. Run remaining setup with incus-admin group active (using sg) # This uses 'sg' to run commands with the new group without requiring logout sg incus-admin -c ' # Fix lxcfs for WSL2 (recommended for proper resource reporting) sudo apt install -y lxcfs sudo mkdir -p /etc/systemd/system/lxcfs.service.d printf "[Unit]\nConditionVirtualization=\n" | sudo tee /etc/systemd/system/lxcfs.service.d/override.conf > /dev/null sudo systemctl daemon-reload sudo systemctl start lxcfs # Build container bash setup.sh my-dev ./provision.sh ' # 4. Activate the incus-admin group in your current shell (or logout/login) newgrp incus-admin ``` Then shell in: ```bash incus shell my-dev ``` Rename the container (optional): ```bash incus rename my-dev new-name ``` ## What Gets Installed `provision.sh` provisions the container with: - **System**: build-essential, curl, wget, git, htop, tmux, tree, openssh-server, net-tools, etc. - **Shell**: zsh + Oh My Zsh (agnoster theme), tmux (maroon/cyan theme, mouse on, status top) - **Languages** (via mise): Node.js, Go, Rust, Erlang, Elixir, Python, Java, Clojure, Zig, Bun - **CLI tools** (via mise): jq, bat, typst, lazydocker, yarn, ripgrep, fd, just - **Containers**: Podman - **Networking**: Tailscale - **Dev tools**: Claude Code, OpenCode, GitHub CLI (gh), fzf ## Snapshots After building, save the container as a reusable image so future containers launch in seconds: ```bash incus stop my-dev incus publish my-dev --alias cobalt-crucible-base incus start my-dev ``` ## Launching Containers **With Tailscale (recommended):** First, store your Tailscale auth key (generate at https://login.tailscale.com/admin/settings/keys): ```bash # Store auth key (choose one method) export TAILSCALE_AUTHKEY="tskey-auth-xxxxx" # OR echo "tskey-auth-xxxxx" > ~/.tailscale-authkey chmod 600 ~/.tailscale-authkey ``` Then launch with automatic Tailscale connection: ```bash bash launch-container.sh my-container-name ``` This launches the container, connects to Tailscale, and shows the IP for SSH access. **Without Tailscale:** ```bash incus launch cobalt-crucible-base <name> ``` Update the snapshot after making changes: ```bash incus stop <name> incus image delete cobalt-crucible-base incus publish <name> --alias cobalt-crucible-base incus start <name> ``` ## Resource Limits Defaults are set in `setup.sh` (8GB memory, 8 CPUs). Adjust per container: ```bash incus config set <name> limits.memory 4GB incus config set <name> limits.cpu 2 incus config set <name> limits.cpu.allowance 50% incus config device set <name> root size=20GB ``` Changes apply live — no restart needed. ## Common Commands ```bash incus shell <name> # shell into container incus list # list containers incus info <name> # resource usage incus config show <name> # full config incus rename <old> <new> # rename container incus restart <name> # restart incus stop <name> # stop incus delete <name> --force # delete incus image list # list local images ```
↗ GitHub