▍ humdrum codex / custard
license AGPL-3.0
4.2 KB raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env bash
#
# deploy.sh — build custard for linux/amd64 and deploy it behind Caddy + systemd.
# Reads deploy/deploy.env (copy from deploy.env.example). Idempotent; re-run to
# update. Generates the Caddyfile + systemd unit from your settings — nothing to
# hand-edit on the server.
#
set -euo pipefail
cd "$(dirname "$0")/.."

ENV_FILE="deploy/deploy.env"
if [ ! -f "$ENV_FILE" ]; then
	echo "missing $ENV_FILE — copy deploy/deploy.env.example to it and fill in your values" >&2
	exit 1
fi
set -a; . "$ENV_FILE"; set +a
: "${REMOTE:?set REMOTE in deploy.env}"
: "${DOMAIN:?set DOMAIN in deploy.env}"
: "${RUN_USER:?set RUN_USER in deploy.env}"
: "${REPOS_PATH:?set REPOS_PATH in deploy.env}"
SOFT_SERVE_DB="${SOFT_SERVE_DB:-}"
SOFT_SERVE_BACKEND="${SOFT_SERVE_BACKEND:-}"
WEBHOOK_SECRET="${WEBHOOK_SECRET:-}"
TAP_REPO="${TAP_REPO:-homebrew-tap}"
DL_PATH="/var/lib/custard/dl"

echo "==> building static linux/amd64 binary"
command -v templ >/dev/null 2>&1 && templ generate
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /tmp/custard-linux ./cmd/custard

echo "==> rendering Caddyfile + unit for $DOMAIN"
gitblock=""
if [ -n "$SOFT_SERVE_BACKEND" ]; then
	gitblock="  handle_path /git/* {
    reverse_proxy $SOFT_SERVE_BACKEND
  }
"
fi
cat > /tmp/custard.Caddyfile <<EOF
# Generated by custard deploy.sh — do not edit by hand.
${DOMAIN} {
  encode gzip zstd
${gitblock}  handle_path /dl/* {
    root * /var/lib/custard/dl
    file_server browse
  }
  reverse_proxy 127.0.0.1:8080
}
EOF

dbflag=""
[ -n "$SOFT_SERVE_DB" ] && dbflag=" --soft-serve-db ${SOFT_SERVE_DB}"
cat > /tmp/custard.service <<EOF
[Unit]
Description=custard — web code forge
After=network-online.target
Wants=network-online.target

[Service]
User=${RUN_USER}
Group=${RUN_USER}
EnvironmentFile=-/etc/custard.env
ExecStart=/usr/local/bin/custard --repos ${REPOS_PATH} --addr 127.0.0.1:8080 --base-url https://${DOMAIN} --soft-serve-http https://${DOMAIN}/git --tap-repo ${TAP_REPO} --dl-path ${DL_PATH}${dbflag}
Restart=on-failure
RestartSec=2
NoNewPrivileges=true
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
ReadOnlyPaths=${REPOS_PATH}
# custard writes only the tap repo (formula commits) and the download dir.
ReadWritePaths=${REPOS_PATH}/${TAP_REPO}.git ${DL_PATH}

[Install]
WantedBy=multi-user.target
EOF

echo "==> uploading to $REMOTE"
scp -q /tmp/custard-linux "$REMOTE:/usr/local/bin/custard.new"
scp -q /tmp/custard.service "$REMOTE:/etc/systemd/system/custard.service"
scp -q /tmp/custard.Caddyfile "$REMOTE:/tmp/custard.Caddyfile"

# Webhook secret → root-only env file (not process args). Empty file if unset.
if [ -n "$WEBHOOK_SECRET" ]; then
	printf 'WEBHOOK_SECRET=%s\n' "$WEBHOOK_SECRET" > /tmp/custard.env
else
	: > /tmp/custard.env
fi
scp -q /tmp/custard.env "$REMOTE:/tmp/custard.env"
# Download dir owned by the run user (custard writes), world-readable (Caddy serves).
ssh "$REMOTE" "install -d -o ${RUN_USER} -g ${RUN_USER} -m 755 ${DL_PATH} && install -m 600 /tmp/custard.env /etc/custard.env && rm -f /tmp/custard.env"

echo "==> installing on remote"
ssh "$REMOTE" 'bash -seu' <<'REMOTE_EOF'
if ! command -v caddy >/dev/null 2>&1; then
  echo "installing caddy..."
  apt-get install -y -q debian-keyring debian-archive-keyring apt-transport-https curl >/dev/null 2>&1
  curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
  curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' > /etc/apt/sources.list.d/caddy-stable.list
  apt-get update -q >/dev/null 2>&1 && apt-get install -y -q caddy >/dev/null 2>&1
fi
install -d -o caddy -g caddy /etc/caddy
mv /tmp/custard.Caddyfile /etc/caddy/Caddyfile
mv /usr/local/bin/custard.new /usr/local/bin/custard
chmod +x /usr/local/bin/custard
systemctl daemon-reload
systemctl enable --now custard >/dev/null 2>&1 || true
systemctl restart custard
caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile >/dev/null && { systemctl reload caddy || systemctl restart caddy; }
sleep 1
echo "  custard: $(systemctl is-active custard)   caddy: $(systemctl is-active caddy)"
curl -s -o /dev/null -w '  local probe -> %{http_code}\n' http://127.0.0.1:8080/ || true
REMOTE_EOF

echo "==> done → https://${DOMAIN}"