--- name: deployment description: Production deployment setup for tibi-projects – Basispanel subdomain, .env, CI-Pipeline, Makefile. Use when deploying a new project to production or setting up a staging environment. --- # Deployment ## Überblick Ein tibi-Projekt wird per Gitea Actions CI gebaut und via rsync auf den Produktionsserver (dock4) deployed. Davor muss die Subdomain im Basispanel angelegt und der Kunde korrekt konfiguriert sein. ## 1. Basispanel – Subdomain anlegen ### Kunde prüfen ```bash # Domain des Kunden suchen mcp_call(server="basispanel", tool="bp_list_domains", args={"search": ""}) # → liefert Customer-ID, Domain-ID, Company, Username ``` ### Subdomain anlegen ```bash # 1. Config holen (verfügbare Webserver + Storages sehen) mcp_call(server="basispanel", tool="bp_get_config") # 2. Subdomain erstellen (ohne Webserver) mcp_call(server="basispanel", tool="bp_create_subdomain", args={ "domainId": , "name": "", # oder leer für bare domain }) # 3. Löschen + neu mit Webserver (wenn Update nicht klappt) mcp_call(server="basispanel", tool="bp_delete_subdomain", args={"id": }) mcp_call(server="basispanel", tool="bp_create_subdomain", args={ "domainId": , "name": "", "webserverKey": "dock4_lamp2", "webserverStorage": "dock4_webroots2", "webserverSettings": { "redirectType": "docroot", "docroot": "/./frontend", "gitbaseRepository": "/", "deployRoot": "./..", "defaultAlias": "wwwAlias", "defaultSubdomain": "defaultSubdomain", "wwwRedirect": "wwwRedirect", "php": "phpDisabled", # tibi-SPA kein PHP "https": "noHttps", # erstmal aus, später aktivieren "certbot": "noCertbot", }, }) ``` Wichtige Keys (aus `bp_get_config`): | Server | Key | Storage | |--------|-----|---------| | dock4 | `dock4_lamp2` | `dock4_webroots2` | | dock1 | `dock1_...` | `dock1_webroots...` | ### Status prüfen ```bash mcp_call(server="basispanel", tool="bp_get_subdomain_status", args={"id": }) ``` Achtung: Health-Check zeigt DNS-Warnungen (externe Nameserver) – das ist normal solange der Kunde sein DNS selbst verwaltet. ## 2. `.env` konfigurieren ```env # Basis PROJECT_NAME= TIBI_PREFIX=tibi TIBI_NAMESPACE= # RSYNC für Deploy RSYNC_HOST=ftp1.webmakers.de RSYNC_PORT=22223 PRODUCTION_RSYNC_UID=10000 # z.B. 10051300 PRODUCTION_RSYNC_GID=33 # Production Server PRODUCTION_SERVER=dock4.basehosts.de PRODUCTION_TIBI_PREFIX=tibi PRODUCTION_PATH=/webroots2/customers//htdocs # Staging STAGING_PATH=/staging///dev # URLs LIVE_URL=http://..dock4.basispanel.de # Preview-URL STAGING_URL=https://dev-.staging.testversion.online CODING_URL=https://.code.testversion.online ``` ## 3. CI-Pipeline (`.gitea/workflows/deploy.yml`) ```yaml name: deploy to production on: "push" jobs: deploy: steps: - checkout + git fetch --tags - node 22 + yarn install - yarn validate - ./scripts/ci-modify-config.sh # injiziert LIVE_URL, release, preview - yarn build # frontend - yarn build:server # SSR - sourcemaps → sentry - if dev-branch: ./scripts/ci-staging.sh - if master-branch: ./scripts/ci-deploy.sh ``` **Wichtig:** Das aktuelle Workflow-File führt `yarn validate`, `yarn build` und `yarn build:server` im CI aus. Wenn `validate` dort scheitert, behebe den eigentlichen Typ- oder Pfadfehler statt den Schritt stillschweigend zu entfernen. ## 4. Deploy-Skripte ### `scripts/ci-deploy.sh` (Production) - Liest `.env` und `api/config.yml.env` - rsynct `frontend/`, `api/`, `media/` via SSH zu `RSYNC_HOST` - deshalb muessen Collection-Dateiuploads auf den Repo-Root `media/` zeigen, typischerweise via `uploadPath: ../media/` in `api/collections/*.yml` - `api/media` ist in diesem Setup nicht der persistente Deploy-Zielpfad fuer Uploads - Nutzt `RSYNC_USER` + `RSYNC_PASS` (aus Gitea Secrets) - Auf master: excludiert `src/` und `*.map` - Reloadt den projektlokalen Proxy-Endpunkt via `LIVE_URL/api/_/admin/reload` mit `Authorization: Bearer ${ADMIN_TOKEN}` - Cleared SSR cache via `LIVE_URL/api/ssr?clear=1` ### `scripts/ci-staging.sh` (Dev/Staging) - rsynct `api/`, `frontend/dist`, und `frontend/assets` nach `/data/${{ github.repository }}/${{ github.ref_name }}` - Startet `docker-compose-staging.yml` - Reloadt den projektlokalen Proxy-Endpunkt via `STAGING_URL/api/_/admin/reload` mit `Authorization: Bearer ${ADMIN_TOKEN}` ### `scripts/ci-modify-config.sh` - Injiziert `LIVE_URL` als `originURL` in `api/hooks/config-client.js` - Injiziert `LIVE_URL` als `PREVIEW_URL` in `api/config.yml.env` - Setzt `release` + `buildTime` für Sentry - Kopiert `frontend/spa.html` → `api/templates/spa.html` (SSR-Template) - Ersetzt `__TIMESTAMP__` in spa.html (Cache-Busting) ## 5. Makefile Wichtige Targets: ```makefile # Media von Production syncen media-sync-master-to-local: rsync -v -e "ssh ... -l $(PRODUCTION_RSYNC_UID),$(PRODUCTION_RSYNC_GID),$(PRODUCTION_PATH)/media" \ -az $(RSYNC_HOST):/ media/ # MongoDB von Production syncen (via Chisel-Tunnel) mongo-sync-master-to-local: chisel client --auth coder:$$PASSWORD http://$(PRODUCTION_SERVER):10987 27017:mongo:27017 & mongodump ... | mongorestore ... ``` ## 6. DNS Der Kunde verwaltet sein DNS selbst (externe Nameserver). Für die Subdomain muss ein A-Record gesetzt werden: ``` . IN A 45.129.180.102 (IP von dock4) ``` Die Preview-URL `http://..dock4.basispanel.de` funktioniert ohne DNS (wird von Basispanel intern aufgelöst). ## 7. HTTPS nachträglich aktivieren Sobald das Projekt live geht: 1. Im Basispanel Subdomain updaten: - `https`: `"https"` (statt `"noHttps"`) - `certbot`: `"certbot"` (automatisches Letsencrypt) - `httpsRedirect`: `"httpsRedirect"` (HTTP→HTTPS) 2. `.env`: `LIVE_URL` auf `https://www.` ändern 3. `api/hooks/config-client.js`: `originURL` entsprechend setzen (wird von CI überschrieben) ## 8. Typische Fehler | Problem | Ursache | Fix | | ------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------ | | `invalid webserverKey: dock4` | Falscher Key | Mit `bp_get_config` prüfen → `dock4_lamp2` | | `subdomain exists` | Doppelt angelegt | Mit `bp_delete_subdomain` löschen, neu anlegen | | `yarn validate` scheitert in CI | Typen/Submodule/Pfade nicht sauber eingecheckt | Checkout-, Submodule- und Include-Pfade korrigieren; `validate` im Workflow belassen | | Rsync "Permission denied" | Falscher RSYNC_USER | In Gitea Secrets prüfen | | 404 auf Subdomain | DNS nicht gesetzt | A-Record beim Kunden-DNS-Provider eintragen |