diff --git a/.gitea/workflows/cd.yml b/.gitea/workflows/cd.yml index fc324c7..10f8e9e 100644 --- a/.gitea/workflows/cd.yml +++ b/.gitea/workflows/cd.yml @@ -11,7 +11,7 @@ on: env: IMAGE_BASE: gitea.101010.cloud/stwaidele/dorfteich - DEPLOY_HOST: 188.245.116.44 + DEPLOY_HOST: one.101010.cloud jobs: build-push: @@ -105,12 +105,9 @@ jobs: needs: smoke-test runs-on: ubuntu-latest # Toggle: set the repo/org Actions variable `RUN_INT_DEPLOY` to `false` - # (Gitea → Settings → Actions → Variables) to stop redeploying the Int stack - # while the runner host is resource-constrained; the Int stack can then stay - # `docker compose down`. Unset/anything-else keeps the normal promotion, so - # this defaults to the previous behaviour and re-enabling is a variable flip - # (no code change). Int is a preview stage; the CI quality gates are - # unaffected either way. + # (Gitea → Settings → Actions → Variables) to skip redeploying the Int + # stack (e.g. host maintenance); unset/anything-else runs the normal + # promotion. Int is a preview stage; CI quality gates are unaffected. if: ${{ vars.RUN_INT_DEPLOY != 'false' }} steps: - name: Log in to the Gitea registry diff --git a/deploy/compose/.env.example b/deploy/compose/.env.example index dceb9b0..4b49077 100644 --- a/deploy/compose/.env.example +++ b/deploy/compose/.env.example @@ -18,7 +18,7 @@ IMAGE_PREFIX=dorfteich TAG=latest # --- ports (localhost only; the host reverse proxy routes to these) --------- -# Suggested per stage on the shared VPS: test 8100/8101/8102, +# Suggested per stage on the shared host (ONE): test 8100/8101/8102, # int 8110/8111/8112, prod 8120/8121/8122 (web/api/collab). WEB_PORT=8100 API_PORT=8101 diff --git a/deploy/stages.md b/deploy/stages.md index 304d0cb..f699900 100644 --- a/deploy/stages.md +++ b/deploy/stages.md @@ -1,7 +1,9 @@ -# Stage provisioning on the VPS (188.245.116.44) +# Stage provisioning on the dedicated host ONE (one.101010.cloud) -Test and Int run as Compose stacks on the operator's VPS; DNS for -`*.dorfteich.cloud` already points there (deployment.md §Stages). Steps +Test and Int run as Compose stacks on the operator's dedicated Hetzner +server ONE (`one.101010.cloud`, 168.119.32.247) — the same host that runs +the Gitea instance and the CI runner; DNS for `*.dorfteich.cloud` already +points there (deployment.md §Stages). Steps marked **[root]** need host root access and are executed by the repo owner; everything else can be done by CI or a deploy user. @@ -54,7 +56,7 @@ FIXTURE_ADMIN_PASSWORD=… FIXTURE_USER_PASSWORD=… \ ``` (The stage db is not published; tunnel to the db container, e.g. -`ssh -L 15432::5432 root@188.245.116.44`.) +`ssh -L 15432::5432 root@one.101010.cloud`.) ## 2. Reverse proxy vhosts **[root]** @@ -83,24 +85,25 @@ Int: same block with `int.dorfteich.cloud` and ports 8110/8111/8112. ## 3. Gitea act_runner **[root]** -The CI/CD workflows (`.gitea/workflows/`) need one act_runner on the VPS +The CI/CD workflows (`.gitea/workflows/`) need one act_runner on the host with Docker access and the `ubuntu-latest` label: ```sh # 1. Download act_runner (https://gitea.com/gitea/act_runner/releases) # 2. Registration token: Gitea → Site/Repo Settings → Actions → Runners +# (or: docker exec -u git gitea_app gitea actions generate-runner-token) act_runner register \ --instance https://gitea.101010.cloud \ --token \ - --name vps-dorfteich \ - --labels ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-22.04 + --name one-dorfteich \ + --labels ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest # 3. Run as a systemd service (act_runner daemon), user in the docker group. ``` ## 4. Deploy user and SSH keys The CD workflow (issue #8) deploys via SSH: -`ssh deploy@188.245.116.44 'cd /home/DOCKER/dorfteich-test && docker compose pull && docker compose up -d'`. +`ssh deploy@one.101010.cloud 'cd /home/DOCKER/dorfteich-test && docker compose pull && docker compose up -d'`. - **[root]** Create a `deploy` user (or reuse an existing deployment user), member of the `docker` group, owning the stage directories. @@ -116,7 +119,7 @@ The pipeline pushes images to the Gitea container registry - Repository secret `REGISTRY_TOKEN`: a Gitea access token with `write:package` scope (owner `stwaidele` or a CI account). -- On the VPS, `docker login gitea.101010.cloud` for the `deploy` user +- On the host, `docker login gitea.101010.cloud` for the `deploy` user with a `read:package` token, so `compose pull` works. ## 6. Verification checklist @@ -133,5 +136,14 @@ The pipeline pushes images to the Gitea container registry - 2026-07-05: Test/Int stage directories, `.env` files, Caddy vhosts (TLS live), `deploy` user, act_runner (v0.6.1, systemd) and registry - login provisioned; Gitea Actions enabled instance-wide (`app.ini` on - BASEL, backup kept). First pipeline run = this commit. + login provisioned on the shared 4-GB VPS (188.245.116.44); Gitea + Actions enabled instance-wide (`app.ini` on BASEL, backup kept). + First pipeline run = this commit. +- 2026-07-11: **Everything moved to the dedicated host ONE** + (`one.101010.cloud`, 168.119.32.247) after Gitea itself relocated + there: stage volumes (`db-data`, `uploads`) and `.env` files copied + 1:1, compose files refreshed from the repo (now includes the `plugins` + volume from #71), Caddy vhosts recreated (prod block prepared but + commented out), act_runner `one-dorfteich` registered, old VPS runner + and stacks stopped (kept as rollback reserve). `DEPLOY_HOST` in + `cd.yml` and the `DEPLOY_HOST_KEY` secret updated accordingly. diff --git a/docs/architecture/adr/0014-gitea-actions-cicd.md b/docs/architecture/adr/0014-gitea-actions-cicd.md index 6e54066..85adcc4 100644 --- a/docs/architecture/adr/0014-gitea-actions-cicd.md +++ b/docs/architecture/adr/0014-gitea-actions-cicd.md @@ -7,17 +7,19 @@ The project is hosted on a self-managed Gitea (`gitea.101010.cloud`). Environments (kickoff): Dev runs locally on contributors' machines; -Test and Int run as separate Compose stacks on the operator's VPS -(`188.245.116.44`, domains `test.dorfteich.cloud` / `int.dorfteich.cloud`); -the Prod host (`dorfteich.online`) is decided at go-live — the VPS or a -dedicated host — so the architecture must keep that choice and any later -move cheap. Contributors include AI coding sessions — gates must be -automated and objective wherever possible. +Test and Int run as separate Compose stacks on the operator's dedicated +server ONE (`one.101010.cloud`, domains `test.dorfteich.cloud` / +`int.dorfteich.cloud`), which also hosts Gitea itself; Prod +(`dorfteich.online`) goes live on the same host at M8 — the architecture +must keep any later move cheap. Contributors include AI coding sessions — +gates must be automated and objective wherever possible. +(Originally the stages and runner lived on a shared 4-GB VPS, +`188.245.116.44`; everything moved to ONE on 2026-07-11.) ## Decision - **Gitea Actions** is the CI/CD system (GitHub-Actions-compatible syntax); - an act_runner runs on the VPS (`188.245.116.44`) with Docker access. + an act_runner runs on ONE (`one.101010.cloud`) with Docker access. - **Images** are built once per change and promoted, never rebuilt per stage: pushed to the **Gitea container registry** (`gitea.101010.cloud/stwaidele/dorfteich-{web,api,collab}`), tagged with diff --git a/docs/architecture/deployment.md b/docs/architecture/deployment.md index d29232c..c8bb1ef 100644 --- a/docs/architecture/deployment.md +++ b/docs/architecture/deployment.md @@ -2,10 +2,12 @@ Four stages, one Compose definition. Foundational decisions: ADR 0014 (CI/CD), ADR 0015 (backup), kickoff topology decision (Dev local on the -developer's machine; Test and Int on the operator's VPS `188.245.116.44`; -the Prod host is decided at go-live — the architecture must keep that -choice and any later move cheap). DNS status: `*.dorfteich.online` and -`*.dorfteich.cloud` already point to the VPS. +developer's machine; Test, Int and — from M8 — Prod on the operator's +dedicated Hetzner server ONE (`one.101010.cloud`, 168.119.32.247), which +also hosts the Gitea instance and the CI runner; the architecture must +keep any later move cheap). DNS status: `*.dorfteich.online` and +`*.dorfteich.cloud` already point to ONE. (Until 2026-07-11 the stages +ran on a shared 4-GB VPS, `188.245.116.44`.) ## The Compose stack @@ -47,9 +49,9 @@ Self-hosters without a proxy can enable the optional `caddy` Compose profile | Stage | Where | Domain | Purpose | Data | | -------- | ----------------------------------------------------------------- | ---------------------- | --------------------------------------------------------------------------------------- | ------------------------------- | | **Dev** | contributor machine (e.g. the operator's MacBook), Docker Desktop | `localhost` | feature work; hot reload via `compose.dev.yml` overlay (source mounts, vite dev server) | fixtures/seed script | -| **Test** | VPS `188.245.116.44`, `/home/DOCKER/dorfteich-test/` | `test.dorfteich.cloud` | auto-deploy target of `main`; e2e suite runs here | reset-able; seeded | -| **Int** | VPS `188.245.116.44`, `/home/DOCKER/dorfteich-int/` | `int.dorfteich.cloud` | stable preview; manual/exploratory testing; release candidates | persistent test data | -| **Prod** | host decided at go-live (M8): the VPS or a dedicated host | `dorfteich.online` | public flagship instance | real data; full backup + mirror | +| **Test** | ONE `one.101010.cloud`, `/home/DOCKER/dorfteich-test/` | `test.dorfteich.cloud` | auto-deploy target of `main`; e2e suite runs here | reset-able; seeded | +| **Int** | ONE `one.101010.cloud`, `/home/DOCKER/dorfteich-int/` | `int.dorfteich.cloud` | stable preview; manual/exploratory testing; release candidates | persistent test data | +| **Prod** | ONE `one.101010.cloud`, `/home/DOCKER/dorfteich-prod/` (M8, #89) | `dorfteich.online` | public flagship instance | real data; full backup + mirror | Stage layout follows the operator's Docker host convention: compose file + `.env` under `/home/DOCKER/dorfteich-/`, bulk data diff --git a/docs/architecture/roadmap.md b/docs/architecture/roadmap.md index 526fd5e..74b5af0 100644 --- a/docs/architecture/roadmap.md +++ b/docs/architecture/roadmap.md @@ -14,8 +14,9 @@ Goal: empty but deployed. Monorepo scaffold (pnpm, ESLint/Prettier, Vitest, Playwright), NestJS api with `/healthz` + Prisma + first migration, React SPA shell with routing + i18n scaffold (ADR 0012), Dockerfiles + Compose stack + dev overlay, Gitea Actions pipeline (lint/test/build → images → -deploy Test → e2e smoke → promote Int), stage setup on the VPS -(`188.245.116.44`). +deploy Test → e2e smoke → promote Int), stage setup on the operator's +host (originally the VPS `188.245.116.44`; since 2026-07-11 the dedicated +server ONE, `one.101010.cloud`). **Exit criterion**: a commit to `main` automatically reaches `test.dorfteich.cloud` and shows a styled "hello" shell.