Files
Panama/server/containers/LashAddict/compose.yml
T
Gabriel Brown f33da41cc6 Panama learns what a server is: from a root login to running containers
A machine's role is now the interview's first question and the one answer
Panama records. Servers get the same shell minus the screen: core packages,
nvm, Bun, Claude Code and Codex (desktops get Codex too), linger, rootless
ports from 80, firewalld, the nginx-bridge network, and a nightly image
updater that replaced watchtower for cause.

server/containers/ carries junior's 23 compose services -- secrets moved to
per-machine .env files that never enter this public repo, every transformed
compose proven to render byte-identical to what is live. 'panama server'
enables, disables and relinks them; nothing here restarts a running service.
'boot --server' walks a fresh VPS from its root login to a normal install.

Five new contracts pin the secrets rule, the catalog's shape, panama-server's
behavior, the role plumbing, and the dotfile classification.

Claude-Session: https://claude.ai/code/session_01NU5JGiN3JfzqrLQB6wmJ1E
2026-08-25 23:11:49 -04:00

77 lines
3.0 KiB
YAML

networks:
nginx-bridge:
external: true
services:
lashaddict-next:
image: git.gbrown.org/gib/${NEXT_CONTAINER_NAME}:latest
container_name: ${NEXT_CONTAINER_NAME}
hostname: ${NEXT_CONTAINER_NAME}
domainname: ${NEXT_DOMAIN}
networks:
- ${NETWORK:-nginx-bridge}
environment:
- NODE_ENV=${NODE_ENV}
- SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN}
- NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL:-http://localhost:${NEXT_PORT:-3000}}
- NEXT_PUBLIC_CONVEX_URL=${NEXT_PUBLIC_CONVEX_URL:-http://${BACKEND_CONTAINER_NAME:-lashaddict-backend}:${BACKEND_PORT:-3210}}
- NEXT_PUBLIC_PLAUSIBLE_URL=${NEXT_PUBLIC_PLAUSIBLE_URL:-https://plausible.gbrown.org}
- NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN}
- NEXT_PUBLIC_SENTRY_URL=${NEXT_PUBLIC_SENTRY_URL}
- NEXT_PUBLIC_SENTRY_ORG=${NEXT_PUBLIC_SENTRY_ORG:-sentry}
- NEXT_PUBLIC_SENTRY_PROJECT_NAME=${NEXT_PUBLIC_SENTRY_PROJECT_NAME}
- PAYLOAD_SECRET=${PAYLOAD_SECRET}
- PAYLOAD_DB_URL=${PAYLOAD_DB_URL}
depends_on:
- lashaddict-backend
tty: true
stdin_open: true
restart: unless-stopped
lashaddict-backend:
image: ghcr.io/get-convex/convex-backend:${BACKEND_TAG:-latest}
container_name: ${BACKEND_CONTAINER_NAME:-lashaddict-backend}
hostname: ${BACKEND_CONTAINER_NAME:-lashaddict-backend}
domainname: ${BACKEND_DOMAIN:-lashaddict.gbrown.org}
networks:
- ${NETWORK:-nginx-bridge}
volumes:
- ./volumes/convex:/convex/data:z
labels:
- com.centurylinklabs.watchtower.enable=true
environment:
- INSTANCE_NAME=${INSTANCE_NAME}
- INSTANCE_SECRET=${INSTANCE_SECRET}
- CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://${BACKEND_CONTAINER_NAME:-stpeteit-backend}:${BACKEND_PORT:-3210}}
- CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://${BACKEND_CONTAINER_NAME:-stpeteit-backend}:${SITE_PROXY_PORT:-3211}}
- DISABLE_BEACON=${DISABLE_BEACON:-true}
- REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:-true}
- DO_NOT_REQUIRE_SSL=${DO_NOT_REQUIRE_SSL:-false}
- POSTGRES_URL=${POSTGRES_URL}
stdin_open: true
tty: true
restart: unless-stopped
healthcheck:
test: curl -f http://localhost:3210/version
interval: 5s
start_period: 10s
stop_grace_period: 10s
stop_signal: SIGINT
lashaddict-dashboard:
image: ghcr.io/get-convex/convex-dashboard:${DASHBOARD_TAG:-latest}
container_name: ${DASHBOARD_CONTAINER_NAME:-lashaddict-dashboard}
hostname: ${DASHBOARD_CONTAINER_NAME:-lashaddict-dashboard}
domainname: ${DASHBOARD_DOMAIN:-dashboard.${BACKEND_DOMAIN:-lashaddict.gbrown.org}}
networks:
- ${NETWORK:-nginx-bridge}
labels:
- com.centurylinklabs.watchtower.enable=true
environment:
- NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://${BACKEND_CONTAINER_NAME:-lashaddict-backend}:${PORT:-3210}}
depends_on:
lashaddict-backend:
condition: service_healthy
stdin_open: true
tty: true
restart: unless-stopped
stop_grace_period: 10s
stop_signal: SIGINT