diff --git a/deploy/.env.example b/deploy/.env.example index 3d6e06f..6e8210a 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -42,21 +42,31 @@ PROCESSGIT_UPDATER_REPO=Algomation-AI/ProcessGit PROCESSGIT_UPDATER_STUB=true # ============================================================================= -# ProcessGit app config (passed through to the main container) +# ProcessGit app config (consumed by the init-config bootstrap step) # ============================================================================= # -# Any Gitea/ProcessGit configuration env vars can go here. The main -# container receives this file via env_file, so every key=value pair -# becomes an env var inside the container. See: -# https://docs.gitea.com/installation/install-with-docker +# These are written into /data/gitea/conf/app.ini on first boot by the +# processgit-init-config service. They're effective only on the first +# `up -d` for a fresh volume; subsequent restarts read the existing +# app.ini and ignore these (idempotency). To change them after the +# first boot, edit /data/gitea/conf/app.ini inside the volume directly. # -# Some common ones: -# -# DOMAIN=processgit.example.com -# SSH_DOMAIN=processgit.example.com -# ROOT_URL=https://processgit.example.com/ -# APP_NAME=ProcessGit -# DISABLE_REGISTRATION=true +# Defaults work for `docker compose up -d` on localhost with the +# default port mapping (18080 → 3000, 12222 → 22). + +# Hostname/IP that operators will reach the instance at. Used in clone +# URLs and OAuth callbacks. +PROCESSGIT_DOMAIN=localhost + +# Full ROOT_URL including scheme and trailing slash. Match what your +# users will type in the browser. +PROCESSGIT_ROOT_URL=http://localhost:18080/ + +# External SSH port — must match the host side of the SSH port mapping +# in docker-compose.yml ("12222:22" → 12222). Affects displayed +# `git clone ssh://...` URLs only; the container always listens on 22 +# internally. +PROCESSGIT_SSH_PORT=12222 # ============================================================================= # Opting out of the self-update sidecar @@ -67,7 +77,7 @@ PROCESSGIT_UPDATER_STUB=true # blank above, and at `up` time list only the services you want: # # docker compose -f deploy/docker-compose.yml up -d \ -# processgit-init-perms processgit processgit-bootstrap +# processgit-init-perms processgit-init-config processgit processgit-bootstrap # # The main app starts identically — you just won't have in-product # self-updates. You can always opt back in later by setting the token diff --git a/deploy/bootstrap/init-config.sh b/deploy/bootstrap/init-config.sh new file mode 100755 index 0000000..c440656 --- /dev/null +++ b/deploy/bootstrap/init-config.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env sh +# Bootstrap Gitea's app.ini before the main container starts. +# +# Why: Gitea, when no app.ini is present, falls through to its interactive +# install wizard. The container then never satisfies the +# /api/v1/version healthcheck (which is not served in install mode), the +# compose orchestration declares it unhealthy, and the +# processgit-bootstrap step that waits on healthy is deadlocked. +# +# This script is the deterministic alternative to depending on the +# upstream gitea/gitea image's s6 startup conventions (which moved +# between s6-overlay v2 and v3 and broke our path-based override of +# /etc/s6/gitea/run, silently skipping the env-var-to-ini conversion +# the image would otherwise do). +# +# Idempotent: if app.ini already exists with INSTALL_LOCK = true, do +# nothing. So restarts and updates don't clobber the operator's tuned +# config or the secrets generated on first boot. + +set -eu + +CONF=/data/gitea/conf/app.ini + +if [ -f "$CONF" ] && grep -q '^INSTALL_LOCK *= *true' "$CONF"; then + echo "[init-config] $CONF exists and is locked; skipping" + exit 0 +fi + +echo "[init-config] generating $CONF" + +mkdir -p \ + /data/gitea/conf \ + /data/gitea/log \ + /data/gitea/attachments \ + /data/gitea/avatars \ + /data/gitea/repo-avatars \ + /data/gitea/sessions \ + /data/gitea/indexers \ + /data/git/repositories \ + /data/git/lfs + +# Generate per-deployment secrets using the bundled gitea binary. These +# are written into the file once and never regenerated — losing them +# would invalidate all existing sessions, signed cookies, and lfs JWT +# tokens, so the idempotent guard above protects them. +SECRET_KEY="$(/app/gitea/gitea generate secret SECRET_KEY)" +INTERNAL_TOKEN="$(/app/gitea/gitea generate secret INTERNAL_TOKEN)" +JWT_SECRET="$(/app/gitea/gitea generate secret JWT_SECRET)" +LFS_JWT_SECRET="$(/app/gitea/gitea generate secret LFS_JWT_SECRET)" + +# Operator-overridable values; defaults are sane for `docker compose up` +# on localhost with the published port mapping (18080:3000, 12222:22). +APP_NAME="${APP_NAME:-ProcessGit}" +DOMAIN="${PROCESSGIT_DOMAIN:-localhost}" +ROOT_URL="${PROCESSGIT_ROOT_URL:-http://localhost:18080/}" +SSH_PORT="${PROCESSGIT_SSH_PORT:-12222}" + +cat > "$CONF" <