diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..a5d7ea3 --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Temporary hostname for the deadline-driven Gitea deployment. +# It resolves to the existing Droplet but does not meet the Student Pack +# domain-offer rubric item. Replace it if the team later claims a domain. +GITEA_DOMAIN=git.137-184-97-250.nip.io diff --git a/Caddyfile.example b/Caddyfile.example new file mode 100644 index 0000000..1d90609 --- /dev/null +++ b/Caddyfile.example @@ -0,0 +1,14 @@ +# Current Caddy routes on the shared Droplet, recorded 2026-09-29. +# Replace the temporary nip.io names if the team later claims its own domain. + +137-184-97-250.nip.io { + reverse_proxy color-buttons-site:3000 +} + +http://137.184.97.250 { + redir https://137-184-97-250.nip.io{uri} permanent +} + +git.137-184-97-250.nip.io { + reverse_proxy gitea:3000 +} diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..bf2bb1f --- /dev/null +++ b/compose.yaml @@ -0,0 +1,22 @@ +services: + gitea: + image: docker.gitea.com/gitea:1.27.3 + restart: unless-stopped + environment: + GITEA__database__DB_TYPE: sqlite3 + GITEA__server__DOMAIN: ${GITEA_DOMAIN:?Set GITEA_DOMAIN in .env} + GITEA__server__ROOT_URL: https://${GITEA_DOMAIN:?Set GITEA_DOMAIN in .env}/ + GITEA__server__DISABLE_SSH: "true" + GITEA__service__DISABLE_REGISTRATION: "true" + volumes: + - gitea_data:/data + networks: + - color-net + # No host ports: Caddy reaches gitea:3000 on the private Docker network. + +volumes: + gitea_data: + +networks: + color-net: + external: true diff --git a/docs/gitea-operations.md b/docs/gitea-operations.md new file mode 100644 index 0000000..fbfb69d --- /dev/null +++ b/docs/gitea-operations.md @@ -0,0 +1,101 @@ +# Stevens SmartPark Gitea operations + +Status: deployed and checked on 2026-09-29. This document describes the Gitea +work hub, not a deployed SmartPark parking application. The earlier Two Buttons +site remains on the same Droplet as a separate exercise. + +## Service and architecture + +- Public work hub: https://git.137-184-97-250.nip.io/ +- Product repository: https://git.137-184-97-250.nip.io/stevens-smartpark/smartpark-app +- Host: one DigitalOcean Ubuntu 22.04 Droplet, 1 vCPU, 1 GiB RAM, 25 GiB disk. +- Gitea image: `docker.gitea.com/gitea:1.27.3`, configured with Docker Compose. +- Caddy is the public reverse proxy. The Cloud Firewall admits TCP 443 and TCP + 80 for HTTPS and HTTP-to-HTTPS redirect. SSH/TCP 22 is restricted to the + approved administrator IPv4 source. Gitea publishes no host port. +- Caddy terminates TLS and forwards privately to `gitea:3000` on Docker network + `color-net`. Gitea uses SQLite at `/data/gitea/gitea.db`; its `/data` directory + is backed by the named volume `gitea-foundation_gitea_data`. +- The `caddy_data` and `caddy_config` named volumes persist Caddy certificate + and configuration state. The live Caddyfile is mounted read-only from the + Droplet's `/root/color-buttons-app/Caddyfile`. +- The current `nip.io` hostname is a temporary address. It is **not** the + required GitHub Student Developer Pack domain offer; that requirement remains + outstanding for the team manual. + +## Start and inspect + +Sign in to the Droplet with the administrator's SSH key. Do not share the key, +passwords, tokens, or the Gitea database in the repository or report. + +```bash +cd /root/gitea-foundation +docker compose config --quiet +docker compose up -d +docker compose ps +docker logs --tail 50 gitea-foundation-gitea-1 +``` + +The expected Gitea container status is `Up`; its port listing should contain +only internal `22/tcp` and `3000/tcp`, without a host address mapping. Git over +SSH is disabled; HTTPS is the intended public access path. Check the public +repository URL in a browser and verify that the certificate is trusted. + +## Restart and troubleshoot + +```bash +cd /root/gitea-foundation +docker compose restart gitea +docker compose ps +docker logs --tail 100 gitea-foundation-gitea-1 +docker exec color-buttons-caddy wget -S -O /dev/null http://gitea:3000/ +docker exec color-buttons-caddy caddy validate --config /etc/caddy/Caddyfile +``` + +If the private `wget` check fails, inspect the Gitea logs, container status, +and `color-net` membership. If private access works but public HTTPS fails, +inspect Caddy's status and logs, its Caddyfile, the DNS lookup, and the Cloud +Firewall rules. Validate the Caddyfile before reloading it. Preserve the named +volumes when replacing containers; do not use `docker compose down -v` for a +routine restart or persistence test. + +## Verification performed + +On 2026-09-29, the team recorded the SmartPark repository and first issue, +recreated only the Gitea container with +`docker compose up -d --force-recreate gitea`, and verified that the same +repository and issue remained available over valid HTTPS afterward. This +demonstrates container-replacement persistence, **not** backup or restore. + +After moving public TCP 80 from the old app container to Caddy, independent +external checks confirmed that both Gitea and the Two Buttons site redirect +HTTP to trusted HTTPS pages. Gitea's backend TCP 3000, database TCP 5432, and +remote Docker management TCP 2375/2376 were unreachable from the test source. +The DigitalOcean Cloud Firewall was then attached to the correct Droplet; +screenshots show its inbound rules and Droplet assignment. After attachment, +the approved administrator completed a fresh SSH login, public HTTP redirected +to working HTTPS, and external checks found TCP 3000 and 5432 unreachable. +An unapproved-source SSH denial was not retested after attachment. Record the +test sources and times in the manual. + +The Gitea certificate was issued by Let's Encrypt for the temporary hostname +and was valid through 2026-12-28 UTC when checked. Caddy manages renewal and +its `/data` state persists. A separate staging-CA hostname successfully +completed an ACME issuance dry run on 2026-09-29; it returned HTTP 200 with a +matching staging certificate. The staging route was then removed and both +live HTTPS sites were rechecked. This proves the ACME challenge and issuance +path works; it does not claim an observed renewal of the live certificate. + +## Recovery and records + +A container replacement leaves the data volume in place but cannot recover +deleted or corrupt volume contents. On 2026-09-29, the operator briefly stopped +Gitea and archived the entire named data volume, including SQLite, application +configuration, and Git repositories. Gitea restarted normally. The archive was +restored into a separate volume and Gitea instance bound only to Droplet +localhost. The restored test repository and issue returned HTTP 200; the issue +retained its unique marker, and the restored Git endpoint returned the expected +commit. Original and restored browser screenshots were recorded. The backup +archive contains secrets and remains root-only on the Droplet; do not publish +it. Maintain dated, sanitized evidence in the team manual and update this page +after infrastructure changes. \ No newline at end of file