commit bf99afd3b55a01b9a130d4fb8a76bc9a3eb901e5 Author: Deeman Date: Fri Feb 27 15:30:41 2026 +0100 chore: initial repo structure with recovery setup script setup.sh recovers docker-compose files from running containers via uvx docker-autocompose, creates infra_service system user, and deploys to /opt/server-infra/. Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cef73e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +.env.* +!.env.example diff --git a/setup.sh b/setup.sh new file mode 100644 index 0000000..96c4a7c --- /dev/null +++ b/setup.sh @@ -0,0 +1,174 @@ +#!/bin/bash +# Server shared-infra setup: recover compose files, create service user, deploy. +# Run as root on the server. +# +# Usage: +# sudo bash setup.sh +# +# What it does: +# 1. Recovers docker-compose.yml files from running containers via uvx docker-autocompose +# 2. Creates infra_service system user (docker group, nologin) +# 3. Creates /opt/server-infra/{umami,reverse-proxy}/ and deploys compose files +# 4. Copies recovered files back into this repo directory (ready to commit) +# +# Padelnomics containers are recovered to /tmp/padelnomics-compose-recovered.yml only. +# They belong in the padelnomics repo, not here. + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +SERVICE_USER="infra_service" +DEPLOY_DIR="/opt/server-infra" + +[ "$(id -u)" = "0" ] || { echo "ERROR: Run as root: sudo bash setup.sh"; exit 1; } + +log() { echo "$(date '+%H:%M:%S') ==> $*"; } +warn() { echo "$(date '+%H:%M:%S') ==> WARNING: $*" >&2; } + +# ── Preflight checks ─────────────────────────────────────────────────────────── + +command -v docker >/dev/null 2>&1 || { echo "ERROR: docker not found"; exit 1; } + +# Find uvx: prefer the installing user's local bin, fall back to PATH +UVX="" +for candidate in /home/Deeman/.local/bin/uvx /usr/local/bin/uvx "$(command -v uvx 2>/dev/null || true)"; do + if [ -n "${candidate}" ] && [ -x "${candidate}" ]; then + UVX="${candidate}" + break + fi +done +[ -n "${UVX}" ] || { echo "ERROR: uvx not found — install uv first: curl -LsSf https://astral.sh/uv/install.sh | sh"; exit 1; } + +log "Using uvx at ${UVX}" + +# ── Helper: recover one compose project ─────────────────────────────────────── +# Usage: recover_project [ ...] +recover_project() { + local outfile="$1" + shift + local containers=("$@") + + # Check at least one container from the list is running + local running=0 + for c in "${containers[@]}"; do + if docker inspect "${c}" >/dev/null 2>&1; then + running=1 + break + fi + done + + if [ "${running}" = "0" ]; then + warn "None of [${containers[*]}] are running — skipping recovery." + return 0 + fi + + log "Recovering compose file for: ${containers[*]}" + "${UVX}" docker-autocompose "${containers[@]}" > "${outfile}" + log "Saved to ${outfile}" +} + +# ── Recover compose files ────────────────────────────────────────────────────── + +log "Recovering compose files from running containers..." +mkdir -p /tmp/server-infra-recovery + +recover_project \ + /tmp/server-infra-recovery/umami.yml \ + umami-umami-1 umami-db-1 + +recover_project \ + /tmp/server-infra-recovery/reverse-proxy.yml \ + reverse_proxy-app-1 + +recover_project \ + /tmp/padelnomics-compose-recovered.yml \ + padelnomics-blue-worker-1 \ + padelnomics-blue-scheduler-1 \ + padelnomics-blue-app-1 \ + padelnomics-litestream-1 \ + padelnomics-router-1 + +# ── Copy recovered files into this repo ─────────────────────────────────────── + +log "Copying recovered files into repo (${SCRIPT_DIR})..." + +for pair in \ + "/tmp/server-infra-recovery/umami.yml:${SCRIPT_DIR}/umami/docker-compose.yml" \ + "/tmp/server-infra-recovery/reverse-proxy.yml:${SCRIPT_DIR}/reverse-proxy/docker-compose.yml"; do + src="${pair%%:*}" + dst="${pair##*:}" + if [ -f "${src}" ]; then + mkdir -p "$(dirname "${dst}")" + cp "${src}" "${dst}" + log " ${dst}" + fi +done + +# ── Service account ──────────────────────────────────────────────────────────── + +log "Creating service user ${SERVICE_USER}..." +if ! id "${SERVICE_USER}" >/dev/null 2>&1; then + useradd --system --create-home --shell /usr/sbin/nologin "${SERVICE_USER}" + log " User created." +else + log " User already exists — skipping." +fi +usermod -aG docker "${SERVICE_USER}" + +# ── Deploy directory ─────────────────────────────────────────────────────────── + +log "Creating deploy directory ${DEPLOY_DIR}..." +mkdir -p "${DEPLOY_DIR}/umami" "${DEPLOY_DIR}/reverse-proxy" + +for pair in \ + "/tmp/server-infra-recovery/umami.yml:${DEPLOY_DIR}/umami/docker-compose.yml" \ + "/tmp/server-infra-recovery/reverse-proxy.yml:${DEPLOY_DIR}/reverse-proxy/docker-compose.yml"; do + src="${pair%%:*}" + dst="${pair##*:}" + if [ -f "${src}" ]; then + cp "${src}" "${dst}" + fi +done + +chown -R "${SERVICE_USER}:${SERVICE_USER}" "${DEPLOY_DIR}" +log " Ownership set to ${SERVICE_USER}." + +# ── Summary ──────────────────────────────────────────────────────────────────── + +echo "" +echo "==================================================================" +echo "" +echo " Recovery complete. Files recovered:" +echo "" +[ -f "${DEPLOY_DIR}/umami/docker-compose.yml" ] && echo " umami → ${DEPLOY_DIR}/umami/docker-compose.yml" +[ -f "${DEPLOY_DIR}/reverse-proxy/docker-compose.yml" ] && echo " reverse-proxy → ${DEPLOY_DIR}/reverse-proxy/docker-compose.yml" +echo "" +if [ -f "/tmp/padelnomics-compose-recovered.yml" ]; then + echo " Padelnomics (NOT in repo — save to padelnomics repo):" + echo " /tmp/padelnomics-compose-recovered.yml" + echo "" +fi +echo " Service user: ${SERVICE_USER} (docker group)" +echo " Deploy dir: ${DEPLOY_DIR}/" +echo "" +echo "==================================================================" +echo "" +echo " Next steps:" +echo "" +echo " 1. Inspect recovered files and fix up any gaps (env vars, volumes):" +echo " docker compose -f ${DEPLOY_DIR}/umami/docker-compose.yml config" +echo " docker compose -f ${DEPLOY_DIR}/reverse-proxy/docker-compose.yml config" +echo "" +echo " 2. Commit recovered files to git:" +echo " cd ${SCRIPT_DIR}" +echo " git add umami/docker-compose.yml reverse-proxy/docker-compose.yml" +echo " git commit -m 'chore: recover compose files from running containers'" +echo "" +echo " 3. Move padelnomics compose to the padelnomics repo:" +echo " /tmp/padelnomics-compose-recovered.yml" +echo "" +echo " 4. To restart a service if containers go down:" +echo " sudo -u ${SERVICE_USER} docker compose -f ${DEPLOY_DIR}/umami/docker-compose.yml up -d" +echo "" +echo "==================================================================" +echo ""