Skip to content

feat: add Gitea Docker deployment with automated user provisioning (#141)#148

Open
t0kubetsu wants to merge 3 commits into
mainfrom
feature/gitea-bootstrap
Open

feat: add Gitea Docker deployment with automated user provisioning (#141)#148
t0kubetsu wants to merge 3 commits into
mainfrom
feature/gitea-bootstrap

Conversation

@t0kubetsu
Copy link
Copy Markdown
Contributor

Summary

Closes #141. Delivers a standalone, provisioned Gitea deployment via Docker Compose. All users and SSH keys are declared in a single YAML manifest; a provisioner sidecar bootstraps them automatically on first run — no manual steps after make up.

Changes

Dockerfile (two-stage)

  • Stage 1 builder (golang:alpine) — installs yq + jq, copies and pre-validates provisioning scripts
  • Stage 2 runtime (gitea/gitea:latest, Alpine-based) — inherits the gitea CLI binary; copies tooling from builder; runs init.sh as entrypoint

compose.yml

  • dbpostgres:16-alpine with healthcheck (pg_isready)
  • giteagitea/gitea:latest with INSTALL_LOCK=true, DISABLE_REGISTRATION=true, HTTP + SSH ports, healthcheck on /api/v1/version
  • provisioner — built from the Dockerfile; depends_on: gitea: healthy; restart: "no" (one-shot)

provisioning/init.sh

  • Waits for Gitea HTTP (180 s timeout, exits 1 on expiry)
  • Creates admin + regular users via gitea admin user create CLI (direct DB, no HTTP auth needed)
  • Injects SSH keys via Gitea REST API; jq used to build JSON payload (prevents injection via crafted key strings)
  • Idempotent: stamp file at /data/gitea/.provisioned prevents double-provisioning

provisioning/users.yml — declarative manifest; add/remove entries to scale users

.env.example — all tunable vars documented with CHANGEME placeholders for secrets

Makefileup / down / build / rebuild / reprovision / logs-provisioner / term targets following existing project conventions

README.md — Quick Start, Build & Push, User Declaration, SSH Key Format, Env Vars table, Troubleshooting

.dockerignore — excludes .env, *.key, *.pem from build context

Files Changed

File Type
03_container_layer/docker/admin/gitea/Dockerfile Added
03_container_layer/docker/admin/gitea/compose.yml Added
03_container_layer/docker/admin/gitea/provisioning/init.sh Added
03_container_layer/docker/admin/gitea/provisioning/users.yml Added
03_container_layer/docker/admin/gitea/.env.example Added
03_container_layer/docker/admin/gitea/Makefile Added
03_container_layer/docker/admin/gitea/README.md Added
03_container_layer/docker/admin/gitea/.dockerignore Added

Design Notes

  • Base image: golang:alpine (builder) → gitea/gitea:latest (runtime). Ubuntu LTS was not used; the official Gitea Dockerfile uses Alpine/golang:alpine and this PR follows that convention.
  • Security review applied: jq --arg used for JSON construction (H-1 injection fix); .dockerignore added (M-4); wait loop has hard timeout (L-4); Postgres password placeholder strengthened; plaintext passwords in users.yml marked with CHANGE BEFORE DEPLOY banner.

Testing

cp .env.example .env        # set real secrets
make build-up               # builds provisioner, starts full stack
make logs-provisioner       # verify users + SSH keys provisioned
curl http://localhost:3000/api/v1/version   # Gitea health

Related Issues

Closes #141

t0kubetsu added 2 commits May 11, 2026 15:28
)

Two-stage Dockerfile (golang:alpine builder → gitea/gitea:latest runtime)
with a provisioner sidecar that bootstraps users and SSH keys on first run.

- Dockerfile: two-stage build; builder installs yq+jq, runtime inherits gitea CLI
- compose.yml: db (postgres:16-alpine) + gitea + provisioner with health-chain
- provisioning/users.yml: declarative admin/user/SSH-key manifest
- provisioning/init.sh: idempotent bootstrap via gitea CLI (users) + REST API (SSH keys)
- .env.example: all tunable vars documented with safe defaults
- Makefile: up/down/build/rebuild/reprovision/term targets
- README.md: quick-start, user declaration, SSH key format, env vars, troubleshooting
- .dockerignore: prevents .env and key files leaking into build context

Security: jq used for JSON construction to prevent SSH-key injection;
wait loop has 180 s timeout; plaintext passwords marked CHANGE BEFORE DEPLOY.
- Fix SSH port: use SSH_LISTEN_PORT=22 + SSH_PORT=${SSH_PORT:-2222} to advertise correct host port
- Fix silent errors: capture gitea CLI stderr, distinguish 'already exists' from real failures
- Fix yq: explicitly install mikefarah/yq v4.44.1 (apk yq may be kislyuk/yq)
- Fix postgres: require POSTGRES_PASSWORD to be set explicitly (no weak default)
- Add .PHONY declarations to Makefile
@t0kubetsu
Copy link
Copy Markdown
Contributor Author

Fix commit pushed

Addressed all critical and high findings from code review:

  • ✅ SSH port: SSH_LISTEN_PORT=22 + SSH_PORT advertises host port correctly
  • ✅ Silent errors: gitea CLI stderr captured with proper error handling
  • ✅ yq: explicitly installs mikefarah/yq v4.44.1 instead of relying on Alpine package
  • ✅ Postgres: requires POSTGRES_PASSWORD to be set explicitly
  • .PHONY added to Makefile

@hyde-repo hyde-repo added the track_axis-03 Student-facing infrastructure services label May 19, 2026
@hyde-repo hyde-repo self-assigned this May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tests-wave_03 track_axis-03 Student-facing infrastructure services

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Deploy a standalone Gitea instance (Dockerized, with users & SSH keys provisioned)

2 participants