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

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
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

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)

1 participant