From eec087ac506db2ddce33e76af23eba00d75d0e16 Mon Sep 17 00:00:00 2001 From: Grant Whitmer Date: Tue, 11 Aug 2026 14:44:13 -0400 Subject: [PATCH] G2: Gitea auto-install, own DB role, SSH deferred, Actions on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gitea was configured to connect as a 'gitea' DB user that never existed, so it sat unconfigured behind a working tunnel. It now gets its OWN role and database via a first-init script — I-1 says we never write Gitea's tables, and that is better as a permission than as a promise. Co-Authored-By: Claude Opus 5 --- deploy/postgres/01-gitea-role.sh | 14 ++++++++++++++ docker-compose.yml | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100755 deploy/postgres/01-gitea-role.sh diff --git a/deploy/postgres/01-gitea-role.sh b/deploy/postgres/01-gitea-role.sh new file mode 100755 index 0000000..3bbef86 --- /dev/null +++ b/deploy/postgres/01-gitea-role.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# Gitea gets its OWN role and database, not ours. +# +# I-1: Gitea is a component whose private state we never write to directly. That +# boundary is worth enforcing at the database, not just in prose — our plane +# holds schema `windgit` in `windygit`, and Gitea holds a database it alone can +# reach. A shared login would make "we never write Gitea's tables" a promise +# instead of a permission. +set -e +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-SQL + CREATE ROLE gitea LOGIN PASSWORD '${GITEA_DB_PASSWORD:?GITEA_DB_PASSWORD must be set}'; + CREATE DATABASE gitea OWNER gitea; + REVOKE ALL ON DATABASE gitea FROM PUBLIC; +SQL diff --git a/docker-compose.yml b/docker-compose.yml index 37b0697..7a93fa5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,7 +35,20 @@ services: GITEA__database__NAME: gitea GITEA__database__USER: gitea GITEA__database__PASSWD: ${GITEA_DB_PASSWORD:?set GITEA_DB_PASSWORD} + GITEA__database__SSL_MODE: disable GITEA__repository__DEFAULT_BRANCH: main + # Auto-install: no wizard, no half-configured box waiting on a human. + GITEA__security__INSTALL_LOCK: "true" + GITEA__security__SECRET_KEY: ${GITEA_SECRET_KEY:?set GITEA_SECRET_KEY} + GITEA__server__DOMAIN: ${GITEA_DOMAIN:-app.windygit.com} + # G6.2 — SSH access is deferred to R1. The tunnel does HTTPS cleanly and + # no v0 user needs SSH. Recorded as deferred, not forgotten. + GITEA__server__DISABLE_SSH: "true" + # G7.1 — CI on our own hardware. This is the whole verification payoff. + GITEA__actions__ENABLED: "true" + # D-9 vocabulary law reaches the product name itself. + GITEA__DEFAULT__APP_NAME: Windy Git + GITEA__DEFAULT__APP_SLOGAN: Your work, every version, and agents as citizens. GITEA__server__ROOT_URL: ${GITEA_ROOT_URL:-http://localhost:3000/} # G2.2 — OIDC only. No local password login, no self-registration. GITEA__service__DISABLE_REGISTRATION: "true" @@ -57,7 +70,10 @@ services: POSTGRES_USER: windygit POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD} POSTGRES_DB: windygit - volumes: ["./data/pg:/var/lib/postgresql/data"] + GITEA_DB_PASSWORD: ${GITEA_DB_PASSWORD:?set GITEA_DB_PASSWORD} + volumes: + - "./data/pg:/var/lib/postgresql/data" + - "./deploy/postgres:/docker-entrypoint-initdb.d:ro" healthcheck: test: ["CMD-SHELL", "pg_isready -U windygit"] interval: 5s