feat(infra): replace Pulumi ESC with SOPS in bootstrap + setup scripts
- bootstrap_supervisor.sh: remove esc CLI + PULUMI_ACCESS_TOKEN; install sops+age; check age keypair exists; decrypt .env.prod.sops → .env; checkout latest release tag; use uv sync --all-packages - setup_server.sh: add age keypair generation at /opt/materia/age-key.txt; install age binary; print public key with .sops.yaml instructions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,45 +1,74 @@
|
||||
#!/bin/bash
|
||||
# One-time server setup: create app user, /opt/beanflows, and GitLab deploy key.
|
||||
# Run as root on a fresh Hetzner server before bootstrapping the supervisor.
|
||||
# One-time server setup: create data directories, generate age keypair.
|
||||
# Run as root on a fresh Hetzner server before running bootstrap_supervisor.sh.
|
||||
#
|
||||
# Usage:
|
||||
# bash infra/setup_server.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
APP_USER="beanflows_service"
|
||||
APP_DIR="/opt/beanflows"
|
||||
KEY_PATH="/home/$APP_USER/.ssh/gitlab_deploy"
|
||||
REPO_DIR="/opt/materia"
|
||||
AGE_KEY_FILE="$REPO_DIR/age-key.txt"
|
||||
|
||||
# Create system user with a home dir (needed for .ssh) but no login shell
|
||||
if ! id "$APP_USER" &>/dev/null; then
|
||||
useradd --system --create-home --shell /usr/sbin/nologin "$APP_USER"
|
||||
echo "Created user: $APP_USER"
|
||||
else
|
||||
echo "User $APP_USER already exists, skipping"
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "ERROR: This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create app directory owned by app user
|
||||
mkdir -p "$APP_DIR"
|
||||
chown "$APP_USER:$APP_USER" "$APP_DIR"
|
||||
chmod 750 "$APP_DIR"
|
||||
echo "Created $APP_DIR (owner: $APP_USER)"
|
||||
# ── Create data directories ────────────────────────────────
|
||||
echo "--- Creating data directories ---"
|
||||
mkdir -p /data/materia/landing
|
||||
mkdir -p "$REPO_DIR"
|
||||
echo "Data dir: /data/materia"
|
||||
|
||||
# Generate deploy key if not already present
|
||||
if [ ! -f "$KEY_PATH" ]; then
|
||||
mkdir -p "/home/$APP_USER/.ssh"
|
||||
ssh-keygen -t ed25519 -f "$KEY_PATH" -N "" -C "beanflows-server"
|
||||
chown -R "$APP_USER:$APP_USER" "/home/$APP_USER/.ssh"
|
||||
chmod 700 "/home/$APP_USER/.ssh"
|
||||
chmod 600 "$KEY_PATH"
|
||||
chmod 644 "$KEY_PATH.pub"
|
||||
echo "Generated deploy key: $KEY_PATH"
|
||||
else
|
||||
echo "Deploy key already exists, skipping"
|
||||
# ── Install age ────────────────────────────────────────────
|
||||
echo "--- Installing age ---"
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH_AGE="amd64" ;;
|
||||
aarch64) ARCH_AGE="arm64" ;;
|
||||
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
if ! command -v age-keygen &>/dev/null; then
|
||||
AGE_VERSION="v1.3.1"
|
||||
curl -fsSL "https://dl.filippo.io/age/${AGE_VERSION}?for=linux/${ARCH_AGE}" -o /tmp/age.tar.gz
|
||||
tar -xzf /tmp/age.tar.gz -C /usr/local/bin --strip-components=1 age/age age/age-keygen
|
||||
chmod +x /usr/local/bin/age /usr/local/bin/age-keygen
|
||||
rm /tmp/age.tar.gz
|
||||
echo "age installed to /usr/local/bin"
|
||||
fi
|
||||
|
||||
# ── Generate age keypair ───────────────────────────────────
|
||||
echo "--- Setting up age keypair ---"
|
||||
if [ -f "$AGE_KEY_FILE" ]; then
|
||||
echo "Keypair already exists at $AGE_KEY_FILE — skipping generation"
|
||||
else
|
||||
age-keygen -o "$AGE_KEY_FILE" 2>/dev/null
|
||||
chmod 600 "$AGE_KEY_FILE"
|
||||
echo "Generated: $AGE_KEY_FILE"
|
||||
fi
|
||||
|
||||
AGE_PUB=$(grep "public key:" "$AGE_KEY_FILE" | awk '{print $NF}')
|
||||
|
||||
echo ""
|
||||
echo "=== Add this deploy key to GitLab ==="
|
||||
echo "GitLab → repo → Settings → Repository → Deploy Keys (read-only)"
|
||||
echo "=================================================================="
|
||||
echo " Server age public key:"
|
||||
echo ""
|
||||
cat "$KEY_PATH.pub"
|
||||
echo " $AGE_PUB"
|
||||
echo ""
|
||||
echo " Add this key to .sops.yaml on your workstation:"
|
||||
echo ""
|
||||
echo " creation_rules:"
|
||||
echo " - path_regex: \\.env\\.(dev|prod)\\.sops\$"
|
||||
echo " age: >-"
|
||||
echo " <dev-key>"
|
||||
echo " + $AGE_PUB"
|
||||
echo ""
|
||||
echo " Then re-encrypt the prod secrets file:"
|
||||
echo " sops updatekeys .env.prod.sops"
|
||||
echo " git add .sops.yaml .env.prod.sops && git commit -m 'chore: add server age key'"
|
||||
echo " git push"
|
||||
echo ""
|
||||
echo " Then run infra/bootstrap_supervisor.sh to complete setup."
|
||||
echo "=================================================================="
|
||||
|
||||
Reference in New Issue
Block a user