profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
docker-compose.vps.yml 2,723 bytes
1 # roundtable.rasmusj.com, the shared-host variant of docker-compose.yml.
2 #
3 # The VPS already runs one Caddy for every site on it, so this file leaves TLS
4 # and the domain out entirely: nothing is published to the host and the proxy
5 # reaches the app by container name over the external `web` network. The domain
6 # lives in /opt/caddy/Caddyfile alone.
7 #
8 # Postgres stays off `web`. Every other project on the box shares that network,
9 # and a database has no business being reachable from any of them.
10 #
11 # Deploy with ./deploy.sh, which builds this on the server.
12
13 # Named explicitly because every project on this host is deployed into a
14 # directory called `app`, and Compose would otherwise derive the same project
15 # name for all of them and treat the neighbours' containers as orphans.
16 name: roundtable
17
18 services:
19 db:
20 image: postgres:16-alpine
21 container_name: roundtable-db
22 restart: unless-stopped
23 environment:
24 POSTGRES_USER: roundtable
25 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
26 POSTGRES_DB: roundtable
27 volumes:
28 - roundtable-pgdata:/var/lib/postgresql/data
29 networks:
30 - internal
31 healthcheck:
32 test: ['CMD-SHELL', 'pg_isready -U roundtable -d roundtable']
33 interval: 5s
34 timeout: 5s
35 retries: 12
36 logging:
37 driver: json-file
38 options:
39 max-size: '10m'
40 max-file: '3'
41
42 app:
43 build:
44 context: .
45 image: roundtable:vps
46 container_name: roundtable
47 restart: unless-stopped
48 depends_on:
49 db:
50 condition: service_healthy
51 environment:
52 DATABASE_URL: postgresql://roundtable:${POSTGRES_PASSWORD}@db:5432/roundtable?schema=public
53 ENCRYPTION_KEY: ${ENCRYPTION_KEY:?set ENCRYPTION_KEY in .env}
54 AUTH_TRUST_HOST: 'true'
55 OPENROUTER_APP_URL: ${OPENROUTER_APP_URL:-https://roundtable.rasmusj.com}
56 OPENROUTER_APP_TITLE: ${OPENROUTER_APP_TITLE:-Roundtable}
57 # Inference is always paid by the visitor's own OpenRouter key, so the
58 # public site costs nothing to run. /demo replays seeded debates and needs
59 # no key at all.
60 MOCK_LLM: ${MOCK_LLM:-0}
61 RATE_LIMIT_DEBATES_PER_HOUR: ${RATE_LIMIT_DEBATES_PER_HOUR:-10}
62 PORT: '3000'
63 networks:
64 - web
65 - internal
66 expose:
67 - '3000'
68 healthcheck:
69 test: ['CMD', 'node', '-e', "fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
70 interval: 30s
71 timeout: 5s
72 start_period: 40s
73 retries: 3
74 logging:
75 driver: json-file
76 options:
77 max-size: '10m'
78 max-file: '3'
79
80 volumes:
81 roundtable-pgdata:
82
83 networks:
84 web:
85 external: true
86 internal:
87