Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

deploy-crontech.sh

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

deploy-crontech.shBlame184 lines · 1 contributor
7738c58Claude1#!/usr/bin/env bash
2# ============================================================================
3# Gluecron deploy to Crontech bare-metal
4# ============================================================================
5# Idempotent. Run as root on the Crontech box (45.76.171.37). Re-runnable.
6#
7# Usage:
8# bash scripts/deploy-crontech.sh
9#
10# Environment (prompted if not set):
11# DATABASE_URL Neon Postgres pooled connection string
12# SITE_ADMIN_USERNAME GitHub-style username for the bootstrap admin
13# (default: ccantynz-alt)
14# SITE_DOMAIN Public domain for HTTPS (default: gluecron.com)
15#
16# What it does:
17# 1. Installs Bun if missing
18# 2. bun install (frozen lockfile)
19# 3. Ensures /data/repos exists for bare git repos
20# 4. Writes /etc/gluecron.env (chmod 600)
21# 5. Runs DB migrations
22# 6. Writes /etc/systemd/system/gluecron.service + enables it
23# 7. Adds <domain> { reverse_proxy localhost:3000 } to Caddyfile + reloads
24# 8. Smoke-tests localhost:3000/healthz
25# ============================================================================
26
27set -euo pipefail
28
29REPO_DIR=${REPO_DIR:-/opt/gluecron}
30BARE_REPOS=${BARE_REPOS:-/data/repos}
5d82f61Claude31PORT=${PORT:-3010}
7738c58Claude32SITE_DOMAIN=${SITE_DOMAIN:-gluecron.com}
33SITE_ADMIN_USERNAME=${SITE_ADMIN_USERNAME:-ccantynz-alt}
34
35cd "$REPO_DIR" || {
36 echo "ERROR: $REPO_DIR doesn't exist. Clone the repo first:"
37 echo " git clone https://github.com/ccantynz-alt/Gluecron.com.git $REPO_DIR"
38 exit 1
39}
40
41echo "==> Pulling latest source"
42git pull --ff-only origin main
43
44# ---- DATABASE_URL prompt -------------------------------------------------
45if [ -z "${DATABASE_URL:-}" ]; then
46 if [ -f /etc/gluecron.env ] && grep -q '^DATABASE_URL=' /etc/gluecron.env; then
47 DATABASE_URL=$(grep '^DATABASE_URL=' /etc/gluecron.env | cut -d= -f2-)
48 echo "==> Reusing existing DATABASE_URL from /etc/gluecron.env"
49 else
50 echo
51 echo "Paste the Neon DATABASE_URL (postgresql://... ?sslmode=require ...):"
52 read -r DATABASE_URL
53 fi
54fi
55
56APP_BASE_URL=${APP_BASE_URL:-https://${SITE_DOMAIN}}
57
58# ---- Bun install ---------------------------------------------------------
59if ! command -v bun >/dev/null && [ ! -x "$HOME/.bun/bin/bun" ]; then
60 echo "==> Installing Bun"
61 curl -fsSL https://bun.sh/install | bash
62fi
63export PATH="$HOME/.bun/bin:$PATH"
64echo "==> bun: $(bun --version)"
65
66# ---- Dependencies --------------------------------------------------------
67echo "==> Installing project dependencies"
68bun install --frozen-lockfile
69
70# ---- Bare-repo dir -------------------------------------------------------
71mkdir -p "$BARE_REPOS"
72chmod 755 "$BARE_REPOS"
73
74# ---- Env file ------------------------------------------------------------
75echo "==> Writing /etc/gluecron.env"
76umask 077
77cat > /etc/gluecron.env <<EOF
78DATABASE_URL=${DATABASE_URL}
79APP_BASE_URL=${APP_BASE_URL}
80SITE_ADMIN_USERNAME=${SITE_ADMIN_USERNAME}
81GIT_REPOS_PATH=${BARE_REPOS}
82PORT=${PORT}
83DEMO_SEED_ON_BOOT=1
84EMAIL_PROVIDER=log
ad6af41Claude85EMAIL_FROM="gluecron <no-reply@${SITE_DOMAIN}>"
7738c58Claude86NODE_ENV=production
87EOF
88chmod 600 /etc/gluecron.env
89umask 022
90
91# ---- Migrations ----------------------------------------------------------
92echo "==> Running database migrations"
93set -a; source /etc/gluecron.env; set +a
94bun run src/db/migrate.ts || {
95 echo "WARNING: migration command failed — continuing (it may be idempotent already-applied)"
96}
97
98# ---- systemd unit --------------------------------------------------------
99BUN_BIN="$(command -v bun)"
100echo "==> Writing /etc/systemd/system/gluecron.service"
101cat > /etc/systemd/system/gluecron.service <<EOF
102[Unit]
103Description=Gluecron — AI-native code intelligence platform
104After=network-online.target
105Wants=network-online.target
106
107[Service]
108Type=simple
109User=root
110WorkingDirectory=${REPO_DIR}
111EnvironmentFile=/etc/gluecron.env
112ExecStart=${BUN_BIN} run src/index.ts
113Restart=always
114RestartSec=5
115StandardOutput=journal
116StandardError=journal
117SyslogIdentifier=gluecron
118LimitNOFILE=65536
119
120[Install]
121WantedBy=multi-user.target
122EOF
123
124echo "==> Reloading systemd + (re)starting gluecron"
125systemctl daemon-reload
126systemctl enable gluecron >/dev/null 2>&1 || true
127systemctl restart gluecron
128
129# ---- Caddy ----------------------------------------------------------------
130CADDYFILE="/etc/caddy/Caddyfile"
131if [ -f "$CADDYFILE" ]; then
132 if ! grep -q "^${SITE_DOMAIN} *{" "$CADDYFILE"; then
133 echo "==> Adding ${SITE_DOMAIN} to Caddyfile"
134 cat >> "$CADDYFILE" <<EOF
135
136${SITE_DOMAIN} {
137 reverse_proxy localhost:${PORT}
138}
139www.${SITE_DOMAIN} {
140 redir https://${SITE_DOMAIN}{uri} permanent
141}
142EOF
143 if command -v caddy >/dev/null; then
144 caddy validate --config "$CADDYFILE" --adapter caddyfile && systemctl reload caddy
145 else
146 systemctl reload caddy || systemctl restart caddy || true
147 fi
148 else
149 echo "==> ${SITE_DOMAIN} already in Caddyfile (skipping)"
150 fi
151else
152 echo "WARNING: $CADDYFILE not found — skipping Caddy config"
153 echo " You'll need to add a reverse_proxy to localhost:${PORT} manually"
154fi
155
156# ---- Smoke test ----------------------------------------------------------
157echo
158echo "==> Waiting for /healthz to respond (up to 30s)"
159for i in $(seq 1 10); do
160 if curl -sf "http://localhost:${PORT}/healthz" >/dev/null; then
161 echo "✓ gluecron is up at http://localhost:${PORT}"
162 echo
163 echo "============================================================"
164 echo "DONE. Next steps:"
165 echo " 1. DNS: ensure A record for ${SITE_DOMAIN} → this server's IP"
166 echo " 2. Visit: https://${SITE_DOMAIN}"
167 echo " 3. Register account '${SITE_ADMIN_USERNAME}' → instant site admin"
168 echo
169 echo "Useful commands:"
170 echo " systemctl status gluecron"
171 echo " journalctl -u gluecron -f"
172 echo " bash scripts/deploy-crontech.sh # re-deploy after git pull"
173 echo "============================================================"
174 exit 0
175 fi
176 sleep 3
177done
178
179echo
180echo "✗ gluecron did not respond on /healthz after 30s"
181echo "Diagnose with:"
182echo " systemctl status gluecron"
183echo " journalctl -u gluecron -n 100 --no-pager"
184exit 1