Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

docker-compose.standalone.yml

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

docker-compose.standalone.ymlBlame124 lines · 2 contributors
f635e2fClaude1# Standalone single-box deploy: Gluecron + Postgres(pgvector) + Caddy(auto-HTTPS)
2# plus self-healing (autoheal), log rotation, daily backups, and fast auto-deploy.
95e33b0Claude3#
4# For a DEDICATED VPS where Gluecron owns ports 80/443 (no co-tenant). One
5# command brings up the whole stack with automatic Let's Encrypt certs:
6#
7# docker compose -f docker-compose.standalone.yml up -d --build
8#
9# Variables come from a local .env (POSTGRES_PASSWORD, optional ANTHROPIC_API_KEY)
f635e2fClaude10# — see scripts/standalone-deploy.sh which generates it and installs the backup
11# + auto-deploy systemd timers. The Caddyfile already serves gluecron.com + www.
12
13x-logging: &default-logging
14 driver: json-file
15 options:
16 max-size: "10m"
17 max-file: "3"
18
95e33b0Claude19services:
20 postgres:
21 # pgvector image is required: migration 0057 does CREATE EXTENSION vector.
22 image: pgvector/pgvector:pg16
23 environment:
24 POSTGRES_USER: gluecron
25 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
26 POSTGRES_DB: gluecron
27 volumes:
28 - pgdata:/var/lib/postgresql/data
29 restart: unless-stopped
f635e2fClaude30 logging: *default-logging
95e33b0Claude31 healthcheck:
32 test: ["CMD-SHELL", "pg_isready -U gluecron -d gluecron"]
33 interval: 10s
34 timeout: 5s
35 retries: 6
36
37 gluecron:
38 build: .
95d0b72ccantynz-alt39 # Pass the ENTIRE .env into the container. Previously only a hardcoded
40 # allowlist below reached the app, so any env-gated feature whose var
41 # wasn't hand-added here was silently dead even when set in .env —
42 # SERVER_TARGETS_KEY (deploy targets), WORKFLOW_SECRETS_KEY (workflow
43 # secrets), the VAPRON_* deploy vars, etc. env_file fixes the whole
44 # class: set a documented var in .env and it just works. The explicit
45 # `environment:` block below still wins for the literals it pins
46 # (PORT, NODE_ENV, GIT_REPOS_PATH, APP_BASE_URL, SSH_PORT) and stays as
47 # documentation of the load-bearing ones.
48 env_file:
49 - .env
95e33b0Claude50 environment:
09d5f39Claude51 - DATABASE_URL=${DATABASE_URL:-}
95e33b0Claude52 - GIT_REPOS_PATH=/data/repos
53 - PORT=3000
54 - NODE_ENV=production
55 - APP_BASE_URL=https://gluecron.com
56 - SSH_PORT=0
57 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
8102dd4ccantynz-alt58 # Build provenance. The image has no .git, so without these
59 # src/lib/build-info.ts falls through to "unknown" — which froze the
60 # footer at "unknown · unknown", made /api/version report a SHA that
61 # never changes (so the auto-update banner could never fire), and left
62 # the PWA service-worker cache key static across deploys.
63 # GIT_SHA is what build-info.ts reads; BUILD_SHA is what version.ts and
64 # pwa.ts read. Both are exported by scripts/self-deploy.sh.
65 - GIT_SHA=${GIT_SHA:-}
66 - GIT_BRANCH=${GIT_BRANCH:-main}
67 - BUILD_SHA=${BUILD_SHA:-}
56ea9a9Claude68 # "Sign in with Google" — values come from .env (gitignored). Wiring them
69 # here is what makes the env bootstrap reach the container and survive
70 # redeploys; a config saved at /admin/google-oauth (DB) still takes
71 # precedence over these.
72 - GOOGLE_OAUTH_CLIENT_ID=${GOOGLE_OAUTH_CLIENT_ID:-}
73 - GOOGLE_OAUTH_CLIENT_SECRET=${GOOGLE_OAUTH_CLIENT_SECRET:-}
74 - GOOGLE_OAUTH_AUTO_CREATE=${GOOGLE_OAUTH_AUTO_CREATE:-}
75 - GOOGLE_OAUTH_ALLOWED_DOMAINS=${GOOGLE_OAUTH_ALLOWED_DOMAINS:-}
95e33b0Claude76 expose:
77 - "3000"
78 volumes:
79 - git-repos:/data/repos
80 depends_on:
81 postgres:
82 condition: service_healthy
83 restart: unless-stopped
f635e2fClaude84 logging: *default-logging
95e33b0Claude85 healthcheck:
f635e2fClaude86 # Liveness — autoheal restarts the container if this fails repeatedly.
95e33b0Claude87 test: ["CMD", "wget", "-qO-", "http://localhost:3000/healthz"]
88 interval: 30s
89 timeout: 10s
90 retries: 3
f635e2fClaude91 start_period: 60s
95e33b0Claude92
93 caddy:
94 image: caddy:2-alpine
95 restart: unless-stopped
f635e2fClaude96 logging: *default-logging
95e33b0Claude97 ports:
98 - "80:80"
99 - "443:443"
100 volumes:
101 - ./Caddyfile:/etc/caddy/Caddyfile:ro
102 - caddy-data:/data
103 - caddy-config:/config
104 depends_on:
105 - gluecron
106
f635e2fClaude107 # Self-healing: watches every container that declares a healthcheck and
108 # restarts any that goes unhealthy (a hung process that didn't crash).
109 autoheal:
110 image: willfarrell/autoheal:latest
111 restart: unless-stopped
112 logging: *default-logging
113 environment:
114 - AUTOHEAL_CONTAINER_LABEL=all
115 - AUTOHEAL_INTERVAL=15
116 - AUTOHEAL_START_PERIOD=60
117 volumes:
118 - /var/run/docker.sock:/var/run/docker.sock
119
95e33b0Claude120volumes:
121 pgdata:
122 git-repos:
123 caddy-data:
124 caddy-config: