prompts / deploy-app-on-vps.md
edit FILL IN & copy this prompt →824 words

Prompt: deploy a containerised web app on an ird server at your hostname

Have an agent put a Docker Compose app on an ird VPS behind Caddy — TLS issued automatically, the hostname's A record set on your ird zone, secrets copied out of band — with a repeatable redeploy that keeps the proxy up, a snapshot before every risky upgrade, and the logs to prove it works.

Needs: ird access (MCP server or the ird CLI, logged in); an existing ird server with Docker and a non-root deploy user (from the vps-server prompt); a shell with ssh/scp; the app's compose file or image; a hostname on a zone hosted on ird DNS Costs: the server's hourly tier as before (credits_prices → recurring.vps-hourly); each snapshot per GB-hour while kept (recurring.image-hourly) Group: servers

Paste everything below the line into a fresh conversation. Fill in the FILL IN block first.


Task

Deploy the app below on SERVER so it answers at https://HOST, and leave me a redeploy procedure. No server is created or destroyed here; snapshots are taken only after I confirm.

FILL IN

SERVER:      app-1                        # name or id from vps_list — "none" = go to the vps-server prompt first
HOST:        app.example.ro               # hostname on a zone hosted on ird DNS
ZONE:        example.ro
APP_DIR:     ./                           # holds compose.yaml (and Dockerfile if building)
IMAGE:       ghcr.io/example/app:1.4.2    # image:tag, or "build" to build from APP_DIR on the server
APP_PORT:    8080                         # port the app container listens on
ENV_FILE:    ./.env.production            # secrets; copied to the server, never pasted anywhere
DEPLOY_USER: deploy                       # non-root user in the docker group
HEALTH:      /healthz                     # path returning 200 when the app is ready

Non-negotiable rules

  1. No server, no provisioning here. vps_list must show SERVER running. If it doesn't exist, stop and point me to the vps-server prompt — that's where price and creation are confirmed.
  2. Snapshot before anything destructive. Image upgrades and schema migrations get ird vps snapshot SERVER pre-<tag> first (bills per GB-hour, CLI-only); ask before taking it, delete it once the release is verified.
  3. Secrets stay out of band. ENV_FILE travels by scp, lands with mode 600, is referenced via env_file:, and is never quoted in chat, committed, or baked into the image.
  4. Whole record sets. dns_set_record replaces the entire RRset of that name+type; read dns_get_zone first and touch only HOST. Never call vps_destroy.
  5. Only Caddy is public. The app container publishes no host ports; Caddy takes 80/443. Check ufw status allows exactly those (plus 22).

Steps

A. Server. vps_list (CLI: ird vps show SERVER) → id, ipv4, state. ssh DEPLOY_USER@<ipv4> docker compose version must work; if Docker is missing, the vps-server prompt's hardening step installs it.

B. DNS. dns_list_zones includes ZONE. dns_get_zone(ZONE); then dns_set_record(domain=ZONE, name="HOST.", type="A", data={address: <ipv4>}) (CLI: ird dns set ZONE <short name> A <ipv4> — the CLI takes app, not the full HOST). Add an AAAA only if Caddy will actually answer on the server's ipv6 — a stale AAAA breaks certificate issuance. dig +short HOST = ipv4 before step D; Caddy can't get a certificate until the name resolves.

C. Files on the server in /srv/HOST/:

D. First deploy. docker compose pull (or build), docker compose up -d, docker compose ps (both healthy), docker compose logs caddy shows the certificate obtained, then curl -sS https://HOST/HEALTH returns 200 and curl -vI https://HOST shows a valid chain.

E. Redeploy. For each release: (1) if it migrates data, rule 2 — ird vps snapshot SERVER pre-<tag>, wait until ird vps snapshot images lists it available (ird vps activity: the create-image job succeeded); (2) change the tag in compose.yaml; (3) docker compose pull app && docker compose up -d --no-deps app. Caddy stays up throughout; the only gap is the seconds until the new app container passes its healthcheck. Rollback = put the previous tag back and repeat (3); a broken migration means restoring the snapshot (the vps-snapshot-restore prompt).

F. Verify. curl -sS https://HOST/HEALTH → 200; docker compose ps healthy; docker compose logs --tail=100 app clean; docker image prune -f for old layers; vps_list still running.

G. Cleanup. Once the release has run for the agreed time: ird vps snapshot images delete <image-id> for the pre-upgrade snapshot — it bills per GB-hour until removed. Confirm with ird vps snapshot images.

Deliverable

https://HOST, the server id and IP, the A record set, the compose and Caddyfile as deployed (secrets redacted), the health and certificate checks, the three-command redeploy, the rollback line, and the snapshot id still held (if any) with its monthly cost.

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/prompts.git