Initial commit: app +
VPS deploy pipeline
This commit is contained in:
commit
9fd1839ce9
4 changed files with 101 additions and 0 deletions
24
deploy/Caddyfile
Normal file
24
deploy/Caddyfile
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# /etc/caddy/Caddyfile on the VPS.
|
||||
# Replace thermograph.example.com with your real hostname. Its A/AAAA record
|
||||
# must already point at this VPS — Caddy provisions a Let's Encrypt cert on
|
||||
# first request and auto-renews. Nothing else to do for TLS.
|
||||
|
||||
thermograph.example.com {
|
||||
encode zstd gzip
|
||||
|
||||
# Reverse-proxy to the loopback uvicorn (see thermograph.service).
|
||||
reverse_proxy 127.0.0.1:8137
|
||||
|
||||
log {
|
||||
output file /var/log/caddy/thermograph.log
|
||||
}
|
||||
}
|
||||
|
||||
# If you keep THERMOGRAPH_BASE=/thermograph instead of serving at the root,
|
||||
# use this block instead of the one above:
|
||||
#
|
||||
# thermograph.example.com {
|
||||
# encode zstd gzip
|
||||
# reverse_proxy /thermograph/* 127.0.0.1:8137
|
||||
# redir / /thermograph/
|
||||
# }
|
||||
40
deploy/deploy.sh
Executable file
40
deploy/deploy.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/env bash
|
||||
# Pull the latest code and restart Thermograph. Run on the VPS — the GitHub
|
||||
# Actions workflow invokes this over SSH, and you can run it by hand too.
|
||||
#
|
||||
# ssh deploy@vps '/opt/thermograph/deploy/deploy.sh'
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="${APP_DIR:-/opt/thermograph}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
cd "$APP_DIR"
|
||||
|
||||
echo "==> Fetching $BRANCH"
|
||||
git fetch --prune origin "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
|
||||
echo "==> Installing dependencies"
|
||||
if [ ! -d .venv ]; then
|
||||
python3 -m venv .venv
|
||||
fi
|
||||
.venv/bin/pip install --upgrade pip -q
|
||||
.venv/bin/pip install -r backend/requirements.txt -q
|
||||
|
||||
echo "==> Restarting service"
|
||||
sudo systemctl restart thermograph
|
||||
|
||||
echo "==> Health check"
|
||||
PORT="$(sed -n 's/^PORT=//p' /etc/thermograph.env)"; PORT="${PORT:-8137}"
|
||||
BASE="$(sed -n 's/^THERMOGRAPH_BASE=//p' /etc/thermograph.env)"; BASE="${BASE:-/}"
|
||||
# Normalize: no double slash, allow root.
|
||||
url="http://127.0.0.1:${PORT}${BASE%/}/"
|
||||
for i in $(seq 1 15); do
|
||||
if curl -fsS -o /dev/null "$url"; then
|
||||
echo "==> OK: $url is serving"
|
||||
exit 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "!! Health check failed for $url" >&2
|
||||
sudo systemctl status thermograph --no-pager -l || true
|
||||
exit 1
|
||||
10
deploy/thermograph.env.example
Normal file
10
deploy/thermograph.env.example
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Copy to /etc/thermograph.env on the VPS and edit.
|
||||
# Read by the systemd unit (EnvironmentFile).
|
||||
|
||||
# Port uvicorn binds on loopback. Caddy proxies to this. Keep 8137 unless it clashes.
|
||||
PORT=8137
|
||||
|
||||
# Base path the app is served under.
|
||||
# / -> app at the domain root (recommended on a dedicated domain)
|
||||
# /thermograph -> app under a sub-path (if sharing the host with other apps)
|
||||
THERMOGRAPH_BASE=/
|
||||
27
deploy/thermograph.service
Normal file
27
deploy/thermograph.service
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
[Unit]
|
||||
Description=Thermograph (FastAPI/uvicorn)
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
User=deploy
|
||||
Group=deploy
|
||||
# The repo checkout. uvicorn is run from backend/ so `app:app` resolves.
|
||||
WorkingDirectory=/opt/thermograph/backend
|
||||
# THERMOGRAPH_BASE, PORT, etc. See deploy/thermograph.env.example.
|
||||
EnvironmentFile=/etc/thermograph.env
|
||||
# Bind loopback only — Caddy terminates TLS and reverse-proxies to us.
|
||||
ExecStart=/opt/thermograph/.venv/bin/uvicorn app:app --host 127.0.0.1 --port ${PORT}
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
# Hardening
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
# The parquet cache must stay writable across deploys.
|
||||
ReadWritePaths=/opt/thermograph/data /opt/thermograph/logs
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Loading…
Reference in a new issue