Remote dev environment

Set up a shared dev environment on a clean public VPS with Let's Encrypt. Developers edit over VS Code Remote-SSH; containers, builds and Vite HMR run on the server. Full command reference: gon server:dev.

Before you start

  • A fresh VPS (Ubuntu LTS). Don't reuse a server already running server:setup — ports 80/443 must be free for Traefik.
  • A domain you control, pointing at the VPS (e.g. demo.example.com).
  • A classic GitHub PAT with read:packages (for image pulls).
  • Your local SSH pubkey (~/.ssh/id_ed25519.pub) — seeded into the dev user automatically.
  1. Create the project locally and verify it runs:

    gon create-project demo --preset=minimal
    cd demo
    gon up
  2. Provision a VPS and confirm SSH works (key-based, no password):

    ssh root@37.235.105.189 'echo ok'
  3. Point DNS at the VPS — the apex plus the vite. and mail. subdomains:

    A demo.example.com 37.235.105.189
    A vite.demo.example.com 37.235.105.189
    A mail.demo.example.com 37.235.105.189

    All three must resolve before the next steps (ACME checks them). Verify:

    dig +short demo.example.com vite.demo.example.com mail.demo.example.com
  4. Push the project to GitHub (server:dev:add-project clones from there):

    git init && git add -A && git commit -m "feat: initial commit"
    gh repo create rozklad/demo --private --source=. --push
  5. Bootstrap the VPS as a dev environment:

    gon server:dev:setup 37.235.105.189 \
    --alias=dev-vps1 \
    --email=ssl@example.com \
    --ghcr-token=ghp_xxxxx

    Installs Docker, raises inotify limits, creates the shared dev user, starts Traefik+ACME on 80/443, installs gon-cli on the box. Idempotent.

  6. Deploy the project onto the VPS:

    gon server:dev:add-project demo \
    --host=dev-vps1 \
    --repo=rozklad/demo \
    --domain=demo.example.com

    Clones the repo, writes the dev gon.json + .env, runs gon install + gon up.

  7. Verify:

    curl -I https://demo.example.com/api/v1/healthcheck # HTTP/2 200, valid TLS
    gon server:dev:info demo # URLs, SSH, DB creds, containers

Next: add the rest of the team. On a LAN box with no public internet, use a custom certificate instead.

Apply .env changes

gon up does not recreate running containers, so an edited .env stays invisible. Reload the stack instead:

gon server:dev:reload demo

Or, from inside the project over Remote-SSH, run gon reload — same effect (force-recreate + config:clear).

Database access from local TablePlus / DataGrip

MySQL has no public port — connect through an SSH tunnel (credentials from gon server:dev:info demo):

ssh -L 33060:127.0.0.1:3306 dev-vps1-dev -N
# Then in TablePlus: 127.0.0.1:33060

Adding a second project

One box can host several projects — each on its own subdomain and DB volume:

gon server:dev:add-project secondapp \
--host=dev-vps1 \
--repo=rozklad/secondapp \
--domain=second.example.com

Tearing down

gon server:dev:remove demo # Drop project + volumes (with confirmation)
gon server:dev:remove demo --keep-volumes # Preserve DB if you'll reinstall