Portable, containerized development environments for remote hosts. Each devbox is built once, pushed to GHCR, and then pulled ready to use on CPU or GPU machines.
-
Copy the example environment file and fill in host-specific values:
cp devboxes/physicsnemo/.env.example devboxes/physicsnemo/.env
-
Start the PhysicsNeMo devbox:
docker compose -f devboxes/physicsnemo/compose.yaml --env-file devboxes/physicsnemo/.env up -d
-
SSH into the container through Tailscale:
ssh xhou@<tailnet-ip>
The Tailscale sidecar owns networking. The dev container shares that network namespace and runs its own sshd. Do not add --ssh to Tailscale arguments because it would take over port 22 in the sidecar.
common/contains shared build-time and runtime scripts.devboxes/physicsnemo/is the GPU PhysicsNeMo image.docker-bake.hcldefines shared local and CI build targets.
The PhysicsNeMo compose file uses three mount styles:
devbox-home:/home/xhouis the recommended named home volume. Docker initializes a fresh named volume from image content on first run, so baked tools and home defaults survive container recreation.${DATA_DIR:-/mnt/fist}:/mnt/fist:rwis a host bind mount for datasets. It is not portable, but it fits hosts that always expose the same data directory.${CODE_DIR:-./workspace}:/home/xhou/workspaceis a host bind mount for working code.
Each host should keep its own .env; the compose file should stay unchanged.
Dotfiles are cloned at container startup, not image build time, because /home/xhou is mounted as a volume. The entrypoint runs before any SSH agent is forwarded, so cloning git@github.com:accordeonixte/dotfiles.git requires a key already present for xhou at boot.
The clone or pull is non-fatal. If it fails, the container still starts and logs a warning. Because the dotfiles repo is public, you can either provide an SSH key to xhou before startup or switch DOTFILES_REPO to:
https://github.com/accordeonixte/dotfiles.git
Only the headless packages are stowed at runtime: zsh, tmux, nvim, and htop.
The images install these tools at build time:
- Node.js 22 LTS
- Claude Code
- OpenAI Codex CLI
- opencode
They ship unauthenticated. Log in or set API keys inside the running container.
Create a new directory under devboxes/ with a Dockerfile that copies common/ and runs the shared setup scripts. You can start by copying an existing devbox:
cp -R devboxes/physicsnemo devboxes/myboxThen edit devboxes/mybox/Dockerfile, usually the FROM line, image-specific packages, and any compose settings. Shared setup comes from common/.
Build all targets with Docker Buildx Bake:
docker buildx bakeBuild one target:
docker buildx bake physicsnemoPushes to main that touch devboxes/**, common/**, the workflows, or docker-bake.hcl trigger image builds. The workflow discovers devboxes/*/, builds each Dockerfile with repository root as the context, and pushes images to:
ghcr.io/accordeonixte/devbox-<name>
Tags include latest and the short commit SHA.
All jobs run on a Linux x64 self-hosted GitHub Actions runner. Runner prerequisites:
- Docker
- Docker Buildx
- NVIDIA Container Toolkit when building GPU images
- Labels:
self-hosted,Linux, andX64 - Permission to push packages to
ghcr.io/accordeonixte
The reusable workflow at .github/workflows/reusable-build.yml accepts image, dockerfile, and optional context inputs for standalone devbox repositories.