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
```