Files
podman/infra/README.md
T
2026-06-28 02:54:29 +00:00

4.1 KiB

infra

Deploy targets for PodMan on DigitalOcean.

  • Dockerfile — builds the backend runtime image from the monorepo root
  • app.yaml — DigitalOcean App Platform spec: static site, API service, agent worker
  • systemd/ — local droplet service/timer units for the API, agent worker, public healthcheck, and Hermes watchdog

Full deploy spec and env var reference in docs/digitalocean.md.

Local development

pnpm --filter @podman/backend dev:server
pnpm --filter @podman/backend dev:agent
pnpm --filter @podman/frontend dev

Local container

docker build -f infra/Dockerfile -t podman-backend .
docker run --env-file backend/.env -e PODMAN_PROCESS=server -p 8787:8787 podman-backend
docker run --env-file backend/.env -e PODMAN_PROCESS=agent podman-backend

The automated check uses Docker by default, matching pnpm build:container:

pnpm build:container
pnpm verify:containers

Set VERIFY_CONTAINER_RUNTIME=podman to run the same verifier against a Podman image store.

Local production services

On the demo droplet, serve the API and worker with systemd instead of tmux:

sudo install -m 0644 infra/systemd/podman-platform-api.service /etc/systemd/system/
sudo install -m 0644 infra/systemd/podman-platform-agent.service /etc/systemd/system/
sudo install -m 0644 infra/systemd/podman-hermes-*.service infra/systemd/podman-hermes-*.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now podman-platform-api podman-platform-agent podman-hermes-watchdog.timer podman-hermes-sync-deploy.timer
sudo systemctl status podman-platform-api podman-platform-agent podman-hermes-watchdog.timer podman-hermes-sync-deploy.timer

The services expect:

  • built backend artifacts in backend/dist
  • runtime env in backend/.env
  • Caddy proxying /api/* to 127.0.0.1:8787

Useful checks:

curl http://127.0.0.1:8787/health
journalctl -u podman-platform-api -u podman-platform-agent -f
journalctl -u podman-hermes-watchdog -f

DigitalOcean deploy

doctl apps create --spec infra/app.yaml

Set secret env vars (LiveKit, Gemini, GitHub, MongoDB) in the DO dashboard after app creation. Run pnpm deploy:doctor:strict with the same environment loaded before treating the deployment as production-ready.

Droplet/systemd fallback

The infra/systemd/ units run the compiled API and LiveKit/Gemini agent from /root/podman and load /root/podman/backend/.env, matching the current droplet layout. pnpm deploy:doctor also falls back to that file when root .env is absent. Set FRONTEND_URL when the static frontend is served from a different public origin than VITE_BACKEND_URL.

The matching Caddy config is in infra/Caddyfile; it serves /var/www/podman, proxies /api/* and /health to localhost:8787, and proxies the optional local LiveKit host.

sudo cp infra/systemd/podman-platform-*.service /etc/systemd/system/
sudo cp infra/systemd/podman-hermes-watchdog.* /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now podman-platform-api podman-platform-agent podman-hermes-watchdog.timer
systemctl status podman-platform-api podman-platform-agent podman-hermes-watchdog.timer

Hermes operations layer

Hermes is the operations copilot for the droplet. The durable layer is:

  • podman-hermes-watchdog.timer runs pnpm hermes:watchdog every five minutes.
  • podman-hermes-sync-deploy.timer polls origin/main every two minutes and deploys clean fast-forward changes.
  • podman-public-healthcheck.timer keeps the fast public URL restart loop.
  • /var/log/podman/hermes-watchdog-latest.json records the latest watchdog report.
  • .git/hooks/pre-push, installed by pnpm hermes:install, gates major pushes with typecheck, lint, and a non-remediating watchdog check.

Install or refresh all local ops wiring:

pnpm hermes:install

Manual one-shot checks:

pnpm hermes:watchdog
pnpm hermes:watchdog:strict
pnpm hermes:sync-deploy

Fallback (demo safety)

If DO deploy is flaky on stage, run the API and agent locally. In dev, the PWA defaults to http://localhost:8787; in production it falls back to same-origin.