-
Notifications
You must be signed in to change notification settings - Fork 1
Data Volumes
Since v0.7.0, every persistent path lives under one host directory
(./vibe-coder-data/), making backup/migration a one-line tar.
v0.14.0 added a postgres/ subdirectory holding the PostgreSQL data files
(the persistence layer used to be SQLite under server/).
./vibe-coder-data/ container
───────────────── ─────────
├── workspace/ → /workspace (sources + APKs)
├── postgres/ → vibe-coder-postgres : /var/lib/postgresql/data (v0.14.0+, PG data dir)
├── server/ → /data (logs + build metadata)
├── dev-tools/
│ ├── android-sdk/ → /opt/android-sdk (3-4 GB)
│ ├── gradle/ → /home/vibe/.gradle (1-2 GB)
│ ├── npm-global/ → /home/vibe/.local (MCP `npm -g`)
│ ├── npm-cache/ → /home/vibe/.npm (npx cache)
│ ├── playwright/ → /home/vibe/.cache/ms-playwright (optional, ~300 MB)
│ ├── config/ → /home/vibe/.config (tool config)
│ ├── ssh/ → /home/vibe/.ssh (v1.2.0+ SSH key for git clone/push)
│ └── keystores/ → /home/vibe/keystores (v1.5.0+ Android signing keys ⚠️ back up!)
└── claude/ → /home/vibe/.claude (OAuth/API key/MCP registrations)
The server image itself (~600 MB) contains only the Ktor body + Claude CLI +
JDK + Node — every byte that took effort to download lives in your host
directory. vibe-coder-data/postgres/ is added in v0.14.0 (the database
now runs as a sidecar container).
vibe-coder-data/postgres/ is owned by the postgres user inside the
container (UID 70 in postgres:17-alpine). On the host the directory will
show as owned by UID 70 — that's expected and what PostgreSQL requires for
secure file permissions. You will need sudo on the host to read/copy
those files directly. tar as root or logical pg_dump (see Backup
below) bypass that.
Three options, from simplest to most surgical:
# Stop both containers so PG and server are quiescent.
docker compose stop
# One-line tar (sudo because of the postgres dir ownership)
sudo tar czf vibe-coder-data-$(date +%F).tar.gz vibe-coder-data/
sudo chown $(id -u):$(id -g) vibe-coder-data-$(date +%F).tar.gz
# Resume
docker compose startdocker exec vibe-coder-postgres pg_dump -U vibecoder -F c vibecoder > vibe-pg-$(date +%F).pgdump
# To restore on another machine after `docker compose up -d`:
docker exec -i vibe-coder-postgres pg_restore -U vibecoder -d vibecoder --clean --if-exists < vibe-pg-*.pgdumpLogical dump skips workspace files / Android SDK / MCP — combine with
tar czf workspace-$(date +%F).tar.gz vibe-coder-data/workspace/ to cover
the rest.
# /etc/cron.daily/vibe-coder-backup
#!/bin/sh
BAK=/srv/backup/vibe-coder
mkdir -p $BAK
docker exec vibe-coder-postgres pg_dump -U vibecoder -F c vibecoder > $BAK/pg-$(date +%F).pgdump
find $BAK -name 'pg-*.pgdump' -mtime +14 -delete# On the destination
mkdir -p ~/vibe-coder && cd ~/vibe-coder
curl -fsSL https://raw.githubusercontent.com/siamakerlab/vibe-coder-server/main/docker/compose.yml -o compose.yml
curl -fsSL https://raw.githubusercontent.com/siamakerlab/vibe-coder-server/main/docker/.env.example -o .env
# REQUIRED: set VIBECODER_DB_PASSWORD to the same value you used on the source
# (otherwise the restored postgres data dir won't authenticate).
${EDITOR:-nano} .env
# Drop the archive into place
scp source-host:~/vibe-coder/vibe-coder-data-*.tar.gz .
sudo tar xzf vibe-coder-data-*.tar.gz # sudo to preserve UID 70 inside postgres/
docker compose up -dPUID / PGID change is the gotcha for everything except the
PostgreSQL data dir. If id -u/-g on the destination differ from the
source, the entrypoint chowns top-level dirs but not deep contents. If you
see permission errors:
sudo chown -R $(id -u):$(id -g) vibe-coder-data/workspace vibe-coder-data/dev-tools vibe-coder-data/server vibe-coder-data/claude
# Leave vibe-coder-data/postgres/ alone — postgres needs UID 70 inside.Or update .env PUID/PGID to match the source host's values.
| Use case | Recommended free disk |
|---|---|
| First boot, no projects yet | ~5 GB (SDK 3-4 GB + image 600 MB + PG init ~50 MB + buffer) |
| Active project, ~10 builds done | ~10 GB |
| Heavy use with Playwright + several MCP-installed packages | ~15 GB |
| Production-leaning (artifact retention 20+ APKs each ~100 MB + long history) | ~20-30 GB |
The artifactKeepCount in server.yml (default 20) bounds APK growth.
PostgreSQL initial size is ~50 MB and grows mostly with future
conversation_turns table (Roadmap §F.☆ #1 — not yet implemented).
-
Docker container's own writable layer — ephemeral, recreated on
--force-recreate. If you put state here by accident (writing to a non-mounted path inside the container), it'll vanish. -
Image layers — pulled fresh on
docker compose pull. -
Host SSH agent — not forwarded. The container has its own SSH key at
/home/vibe/.ssh/id_ed25519, now persisted in./vibe-coder-data/dev-tools/ssh/(v1.2.0+). The entrypoint auto-generates the keypair on first boot and never overwrites it on subsequent boots, so the key survives image upgrades. View / copy / regenerate via Settings → SSH Key in the admin UI. See SSH-Key for details. -
v1.5.0+ Android keystores (
./vibe-coder-data/dev-tools/keystores/)⚠️ . Managed via Settings → Keystores — each Android package name maps to a 4-file set:<pkg>.keystore(release),<pkg>-debug.keystore(debug),<pkg>-keystore.properties(Gradle signing config), and optionally<pkg>-admob.properties(AdMob IDs). Losing the release key blocks Play Store updates for that package forever — back up this directory after every new keystore creation. The defaults form is pre-filled fromserver.yml'skeystore.defaultssection (CN / O / OU / country / city- default password + validity years), so once the operator fills those
out, every subsequent keystore only needs the package name. Builds load
the properties file via standard Gradle
Properties().load(FileInputStream( "/home/vibe/keystores/<pkg>-keystore.properties"))— see your Android project'sapp/build.gradle.kts.
Migrating from < v1.2.0? Your previous installs had no
.sshbind mount, so the key was stored in the container's writable layer and lost on--force-recreate. After upgrading to v1.2.0+ a fresh key is generated in the new bind mount on first boot — re-register the public key on your Git host. - default password + validity years), so once the operator fills those
out, every subsequent keystore only needs the package name. Builds load
the properties file via standard Gradle
docker compose down -v removes Docker named volumes. v0.7.0+ uses
bind mounts only (everything in ./vibe-coder-data/), so down -v is
safe in clean installations. But if you're mid-migration from a v0.6.x
install, you may still have orphaned named volumes — those would be
deleted. Use docker volume ls to check first.
sudo du -sh vibe-coder-data/*/
# →
# 1.2G vibe-coder-data/dev-tools
# 8.4G vibe-coder-data/workspace
# 120M vibe-coder-data/server
# 80M vibe-coder-data/postgres ← v0.14.0+
# 8.0K vibe-coder-data/claudeInside dev-tools/:
sudo du -sh vibe-coder-data/dev-tools/*/
# 3.7G android-sdk
# 1.8G gradle
# 420M npm-global
# 280M npm-cache
# 310M playwright
# 4.0K config