Bundle to VPS — end-to-end walkthrough¶
This guide walks through the canonical path from a scaffolded VibeWarden
project to a running stack on a VPS. It replaces the removed
vibew deploy command (see ADR-086).
The whole flow is three commands once the project is built:
Everything after that — restarts, log inspection, updates — is done with
standard docker compose commands against the copied bundle directory.
Prerequisites¶
On your workstation:
- A scaffolded VibeWarden project (
vibew initrun at least once). - A built app image (
vibew buildrun at least once whenapp.buildis set; skip if you pull from a registry viaapp.image). scpandsshinPATH— the bundle uses whatever transport you configure in~/.ssh/config.
On the VPS:
- A Linux host reachable over SSH.
- Docker Engine 20.10+ and the Docker Compose v2 plugin installed and runnable by the SSH user.
- The user's home directory writable (the bundle lands under
~/bundle/).
1. Build the deployment artifact¶
This writes a self-contained tree under .vibewarden/bundle/:
.vibewarden/bundle/
docker-compose.yml # image: pinned, never build:
vibewarden.yaml # merged base + production override, strict-validated
sample.env # regenerated every run — commit this
.env # first-run only; --overwrite to replace
deploy.sh # reference script, mode 0o750
image.tar # omit with --skip-image for registry-pull flows
README.md # per-bundle 3-paragraph cheat sheet
kratos/ # anything the generator produces (auth, credentials…)
.credentials # stable across re-runs
Flags you may want:
| Flag | Purpose |
|---|---|
--output <dir> |
Override the default .vibewarden/bundle/. |
--overwrite |
Replace an existing .env in the output dir. First run writes it; subsequent runs preserve the user's edits unless --overwrite is set. |
--skip-image |
Do not package image.tar. Useful when app.image points at a registry the VPS can pull from. |
--image <tag> |
Override the packaged image tag. Defaults to <project>-app:latest. |
The command never opens an SSH connection, never calls docker on a remote
host, and never touches files outside --output. Rerunning it with the
same inputs produces byte-identical output (deterministic).
2. Copy the bundle to the VPS¶
Use rsync instead if you prefer delta transfers on redeploy:
Both leave the tree at ~/bundle/ on the remote. No other layout is
supported by the reference deploy.sh.
3. Start the stack on the VPS¶
deploy.sh is a ten-line reference script generated by vibew bundle.
Inspect it before first use — it runs docker compose up -d and (when
image.tar is present) docker load -i image.tar beforehand. You are
free to replace it with your own orchestration (systemd unit, Ansible
play, Kubernetes manifest) — the bundle is just files.
Day-two operations¶
Once the bundle is on the VPS, all subsequent operations use standard
docker compose:
ssh user@host 'cd ~/bundle && docker compose ps' # status
ssh user@host 'cd ~/bundle && docker compose logs --tail=100 -f' # logs
ssh user@host 'cd ~/bundle && docker compose restart vibewarden' # restart
ssh user@host 'cd ~/bundle && docker compose pull && docker compose up -d' # update
Redeploys are vibew bundle → rsync → ssh ... docker compose up -d.
The bundle is deterministic so the redeploy diff is limited to what you
actually changed (config, image tag, overlay).
Troubleshooting¶
-
Image not loading on the VPS. Check that the host architecture matches the image's target arch.
docker inspect --format='{{.Architecture}}' <image>on both sides.vibew bundledoes not auto-detect cross-arch mismatches; rebuild withdocker buildx build --platform linux/amd64if needed. -
TLS certificates.
vibew bundleemits whatever TLS config the mergedvibewarden.yamlspecifies. Let's Encrypt flows run on first container start. Verify withssh user@host 'cd ~/bundle && docker compose logs vibewarden | grep -i acme'. -
Strict config validation failures before any files are written.
vibew bundlecallsconfig.LoadStrict, so unknown keys abort the command before the bundle directory is touched. -
Health check failures on the VPS.
curl -k https://localhost:$PORT/_vibewarden/healthover SSH is the canonical probe. The sidecar's owndocker compose logs vibewardenusually pinpoints the failing plugin.