#!/bin/sh # Praxis — Proxmox LXC first-boot hookscript. # # Adapted from coreci/scripts/proxmox/firstboot-hook.sh. # Coreci fetches a pre-built Go binary + pct-pushes it; praxis installs # Docker inside the CT, clones the repo from Gitea, builds the image, # and starts the service via systemd (D-022, D-028, D-029). # # Referenced by lxc-config.sh via hookscript=local:snippets/praxis-firstboot.sh. # Proxmox invokes this script at CT lifecycle phases on the PVE HOST # (not inside the CT). The `post-start` phase does the work. # # G-101 FIX: GITEA_TOKEN is baked into this snippet by stage-snippet.sh # (the hookscript runs on the PVE host where lxc.environment is invisible). # The token is used to clone the private Gitea repo inside the CT. # # Proxmox passes: $1 = VMID, $2 = phase # Environment (baked in by stage-snippet.sh): # GITEA_TOKEN — bearer token for the private Gitea repo # PRAXIS_VERSION — git ref (default: main) # GITEA_HOST — Gitea hostname (default: git.cloudinit.dev) set -eu vmid="${1:-}" phase="${2:-}" log() { printf '[praxis-hook %s] %s\n' "$phase" "$*" >&2; } case "$phase" in post-start) : ;; *) exit 0 ;; esac log "VMID=${vmid} — first-boot praxis install (Docker-in-LXC)" VERSION="${PRAXIS_VERSION:-main}" GITEA_HOST="${GITEA_HOST:-git.cloudinit.dev}" GITEA_ORG="coreci" GITEA_REPO="praxis" CLONE_URL="https://${GITEA_TOKEN}@${GITEA_HOST}/${GITEA_ORG}/${GITEA_REPO}.git" # Idempotency: skip if praxis is already installed and running. # Check for the repo clone + active service (not a binary — praxis uses # docker compose, not a /usr/local/bin binary like coreci). if pct exec "$vmid" -- sh -c '[ -d /opt/praxis/.git ] && systemctl is-active --quiet praxis' 2>/dev/null; then log "praxis already installed and active — skipping" exit 0 fi # Step 1: Install Docker + docker-compose-v2 inside the CT (D-028). # Debian 12 standard template + nesting=1 supports Docker. log "installing Docker inside CT ${vmid}" pct exec "$vmid" -- sh -c ' set -e export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq docker.io docker-compose-v2 git curl systemctl enable --now docker ' # Step 2: Clone the praxis repo inside the CT (D-029). # Clone to /opt/praxis (persistent across container restarts). log "cloning praxis repo (ref=${VERSION}) into CT" pct exec "$vmid" -- sh -c " set -e mkdir -p /opt/praxis cd /opt/praxis git clone --depth 1 --branch '${VERSION}' '${CLONE_URL}' . 2>&1 || { # If the specific branch doesn't exist, fall back to main log 'falling back to main branch' git clone --depth 1 '${CLONE_URL}' . 2>&1 } " # Step 3: Write the env file from lxc.environment (passed via the CT's env). # The lxc.environment vars are available inside the CT's environment. # install-service.sh writes /etc/praxis/server.env from these. log "running install-service inside CT" pct exec "$vmid" -- sh -c ' set -e cd /opt/praxis sh scripts/install-service.sh ' log "praxis installed and started in CT ${vmid}" exit 0