Commit95e33b0unknown_key
deploy: standalone dedicated-box stack (Gluecron + Postgres/pgvector + Caddy)
deploy: standalone dedicated-box stack (Gluecron + Postgres/pgvector + Caddy) One-command Docker Compose deploy for running Gluecron on its own VPS with automatic Let's Encrypt TLS, isolated from any co-tenant. Includes data restore from /root/gluecron.sql.gz so an existing DB can be migrated over. https://claude.ai/code/session_01QKaJBYpD6DGErWHrRVChkf
2 files changed+151−095e33b09473a79f8f306d77e9f287bc0f12e362c
2 changed files+151−0
Addeddocker-compose.standalone.yml+69−0View fileUnifiedSplit
@@ -0,0 +1,69 @@
1# Standalone single-box deploy: Gluecron + Postgres(pgvector) + Caddy(auto-HTTPS).
2#
3# For a DEDICATED VPS where Gluecron owns ports 80/443 (no co-tenant). One
4# command brings up the whole stack with automatic Let's Encrypt certs:
5#
6# docker compose -f docker-compose.standalone.yml up -d --build
7#
8# Variables come from a local .env (POSTGRES_PASSWORD, optional ANTHROPIC_API_KEY)
9# — see scripts/standalone-deploy.sh which generates it. The Caddyfile in the
10# repo already serves gluecron.com + www.gluecron.com -> gluecron:3000.
11services:
12 postgres:
13 # pgvector image is required: migration 0057 does CREATE EXTENSION vector.
14 image: pgvector/pgvector:pg16
15 environment:
16 POSTGRES_USER: gluecron
17 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
18 POSTGRES_DB: gluecron
19 volumes:
20 - pgdata:/var/lib/postgresql/data
21 restart: unless-stopped
22 healthcheck:
23 test: ["CMD-SHELL", "pg_isready -U gluecron -d gluecron"]
24 interval: 10s
25 timeout: 5s
26 retries: 6
27
28 gluecron:
29 build: .
30 environment:
31 - DATABASE_URL=postgres://gluecron:${POSTGRES_PASSWORD}@postgres:5432/gluecron
32 - GIT_REPOS_PATH=/data/repos
33 - PORT=3000
34 - NODE_ENV=production
35 - APP_BASE_URL=https://gluecron.com
36 - SSH_PORT=0
37 - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:-}
38 expose:
39 - "3000"
40 volumes:
41 - git-repos:/data/repos
42 depends_on:
43 postgres:
44 condition: service_healthy
45 restart: unless-stopped
46 healthcheck:
47 test: ["CMD", "wget", "-qO-", "http://localhost:3000/healthz"]
48 interval: 30s
49 timeout: 10s
50 retries: 3
51
52 caddy:
53 image: caddy:2-alpine
54 restart: unless-stopped
55 ports:
56 - "80:80"
57 - "443:443"
58 volumes:
59 - ./Caddyfile:/etc/caddy/Caddyfile:ro
60 - caddy-data:/data
61 - caddy-config:/config
62 depends_on:
63 - gluecron
64
65volumes:
66 pgdata:
67 git-repos:
68 caddy-data:
69 caddy-config:
Addedscripts/standalone-deploy.sh+82−0View fileUnifiedSplit
@@ -0,0 +1,82 @@
1
2#
3# Standalone single-box deploy for Gluecron on a DEDICATED VPS.
4# Brings up Gluecron + Postgres(pgvector) + Caddy(auto-HTTPS) with one command.
5#
6# Usage (as root on a fresh Ubuntu box):
7# curl -fsSL https://raw.githubusercontent.com/ccantynz-alt/Gluecron.com/claude/site-migration-vercel-XstpK/scripts/standalone-deploy.sh | bash
8# or, after cloning:
9# bash scripts/standalone-deploy.sh
10#
11# To migrate existing data: copy a dump to /root/gluecron.sql.gz BEFORE running
12# (e.g. `scp` it from the old box). The script restores it automatically.
13set -euo pipefail
14
15REPO_URL="https://github.com/ccantynz-alt/Gluecron.com.git"
16REPO_DIR="/opt/gluecron"
17COMPOSE="docker compose -f docker-compose.standalone.yml"
18
19echo "== Gluecron standalone deploy =="
20
21# 1. Docker
22if ! command -v docker >/dev/null 2>&1; then
23 echo "-- installing Docker"
24 curl -fsSL https://get.docker.com | sh
25fi
26
27# 2. Code
28if [ ! -d "$REPO_DIR/.git" ]; then
29 echo "-- cloning $REPO_URL"
30 git clone "$REPO_URL" "$REPO_DIR"
31fi
32cd "$REPO_DIR"
33git pull --ff-only 2>/dev/null || true
34
35# 3. Env (random Postgres password on first run)
36if [ ! -f .env ]; then
37 echo "POSTGRES_PASSWORD=$(openssl rand -hex 24)" > .env
38 echo "ANTHROPIC_API_KEY=" >> .env
39 echo "-- generated .env (random Postgres password; add ANTHROPIC_API_KEY later if you want AI features)"
40fi
41
42# 4. Firewall (best-effort; only ports we need)
43if command -v ufw >/dev/null 2>&1; then
44 ufw allow 22/tcp >/dev/null 2>&1 || true
45 ufw allow 80/tcp >/dev/null 2>&1 || true
46 ufw allow 443/tcp >/dev/null 2>&1 || true
47fi
48
49# 5. Database first
50echo "-- starting Postgres"
51$COMPOSE up -d postgres
52echo "-- waiting for Postgres to accept connections"
53until $COMPOSE exec -T postgres pg_isready -U gluecron -d gluecron >/dev/null 2>&1; do sleep 2; done
54
55# 6. Restore prior data if a dump is present
56if [ -f /root/gluecron.sql.gz ]; then
57 echo "-- restoring data from /root/gluecron.sql.gz"
58 gunzip -c /root/gluecron.sql.gz | $COMPOSE exec -T postgres psql -U gluecron -d gluecron >/dev/null
59elif [ -f /root/gluecron.sql ]; then
60 echo "-- restoring data from /root/gluecron.sql"
61 $COMPOSE exec -T postgres psql -U gluecron -d gluecron < /root/gluecron.sql >/dev/null
62else
63 echo "-- no dump found at /root/gluecron.sql(.gz); starting with a fresh database"
64fi
65
66# 7. App + Caddy
67echo "-- building and starting Gluecron + Caddy"
68$COMPOSE up -d --build
69
70# 8. Migrations (idempotent — safe whether restored or fresh)
71echo "-- applying migrations"
72sleep 5
73$COMPOSE exec -T gluecron bun run db:migrate || true
74
75echo
76echo "== status =="
77$COMPOSE ps
78echo
79echo "Done. Now point gluecron.com + www.gluecron.com DNS at THIS box's IP"
80echo "(Cloudflare, DNS-only / grey cloud). Caddy issues the cert automatically"
81echo "within ~1 minute of DNS resolving here. Verify with:"
82echo " curl -sI https://gluecron.com/healthz"
083