From dcc8ea15101e07f2ac808b7b0744d85db83f9c76 Mon Sep 17 00:00:00 2001 From: Felix Kemmler Date: Mon, 10 Aug 2026 18:14:32 +0200 Subject: [PATCH] Make omsorgapp's backend URL runtime-configurable, use dedicated API subdomain - omsorgapp now reads the omsorgCore URL from a runtime env-config.js generated by the container entrypoint from OMSORG_CORE_URL, instead of only baking it in at image build time - docker-compose.yml pulls pre-built images from the registry, so a build-time-only value couldn't be changed without a rebuild. - docker-compose.yml: omsorgCore gets its own subdomain (core.omsorg-pflegedienste.de) rather than being proxied under the frontend's domain - omsorgWeb never needs browser-side access to it anyway (server-side cURL only), and a dedicated API host is more future-proof without being any less secure (backend still only bound to 127.0.0.1). Includes the nginx server-block snippet needed for the new subdomain. - Drop the now-unused OMSORG_CORE_PUBLIC_URL build-arg wiring from the Gitea Actions workflow. Co-Authored-By: Claude Sonnet 5 --- .gitea/workflows/docker-build.yml | 2 +- docker-compose.yml | 49 ++++++++++++++++++++++++++----- omsorgapp/Dockerfile | 10 +++++-- omsorgapp/docker-entrypoint.sh | 11 +++++++ omsorgapp/index.html | 2 +- omsorgapp/public/env-config.js | 4 +++ omsorgapp/src/api/config.js | 10 +++++-- 7 files changed, 72 insertions(+), 16 deletions(-) create mode 100644 omsorgapp/docker-entrypoint.sh create mode 100644 omsorgapp/public/env-config.js diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml index 3e827e8..99b6ee7 100644 --- a/.gitea/workflows/docker-build.yml +++ b/.gitea/workflows/docker-build.yml @@ -20,7 +20,7 @@ jobs: build_args: "" - image: omsorgapp dockerfile: omsorgapp/Dockerfile - build_args: "VITE_OMSORG_CORE_URL=${{ vars.OMSORG_CORE_PUBLIC_URL }}" + build_args: "" - image: omsorgweb dockerfile: omsorgWeb/Dockerfile build_args: "" diff --git a/docker-compose.yml b/docker-compose.yml index 1aaccba..dc39200 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,11 +7,36 @@ name: omsorg # nicht öffentlich lesbar sind. Über OMSORG_IMAGE_TAG lässt sich ein bestimmter Versions-Tag # pinnen (z.B. `OMSORG_IMAGE_TAG=v0.1.0 docker compose up -d`), Default ist `latest`. # -# WICHTIG: omsorgapp bäckt die omsorgCore-URL (VITE_OMSORG_CORE_URL) zur BUILD-Zeit in den -# JS-Bundle ein (siehe omsorgapp/src/api/config.js) - das passiert jetzt in der CI über die -# Repo-Variable OMSORG_CORE_PUBLIC_URL, nicht mehr hier. omsorgweb.environment.OMSORG_CORE_URL -# ist davon unabhängig und bleibt der interne Compose-Servicename, da PHP dort serverseitig per -# cURL aufruft (kein Browser-Kontext), siehe omsorgWeb/docker/bootstrap-config.php. +# omsorgCore bekommt eine eigene Subdomain (core.omsorg-pflegedienste.de), nicht denselben +# Hostnamen wie omsorgapp - Begründung: omsorgWeb (beide mitarbeiter-app*-Apps) braucht ohnehin nie +# Browser-Zugriff auf omsorgCore (PHP ruft serverseitig per cURL auf, siehe +# omsorgWeb/docker/bootstrap-config.php/OMSORG_CORE_URL unten), nur omsorgapp tut das - eine eigene +# Subdomain macht die API trotzdem unabhängig von omsorgapps Hosting adressierbar (künftige +# Clients, Doku, Swagger) und ist nicht unsicherer als Pfad-basiertes Proxying: in beiden Fällen +# ist omsorgCore nur über 127.0.0.1 erreichbar (Port-Mapping unten), nie direkt öffentlich. +# Browser-seitiges Cross-Origin läuft über CORS + HttpOnly-Cookie mit credentials:"include" (siehe +# omsorgCore/CLAUDE.md, Abschnitt "Auth-Flow") - dafür muss Cors__AllowedOrigins__0 unten exakt +# der Origin von omsorgapp entsprechen (https://app.omsorg-pflegedienste.de). +# +# Nginx-Server-Block für die neue Subdomain (analog zum bestehenden app.omsorg-pflegedienste.de- +# Block, eigenes Zertifikat z.B. per `certbot --nginx -d core.omsorg-pflegedienste.de`): +# +# server { +# server_name core.omsorg-pflegedienste.de; +# location / { +# proxy_pass http://127.0.0.1:8080; +# proxy_http_version 1.1; +# proxy_set_header Host $host; +# proxy_set_header X-Real-IP $remote_addr; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header X-Forwarded-Proto $scheme; +# } +# listen 443 ssl; # managed by Certbot +# ssl_certificate /etc/letsencrypt/live/core.omsorg-pflegedienste.de/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/core.omsorg-pflegedienste.de/privkey.pem; +# include /etc/letsencrypt/options-ssl-nginx.conf; +# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; +# } # # Alle persistenten Daten liegen bewusst als Bind-Mounts unter /root/data/ auf der Platte (keine # benannten Docker-Volumes) - vor dem ersten `docker compose up` einmalig anlegen: @@ -49,16 +74,24 @@ services: ASPNETCORE_ENVIRONMENT: Development ConnectionStrings__OmsorgCore: "Host=postgres;Port=5432;Database=omsorg_core;Username=omsorg_core;Password=omsorg_core_dev_password" Jwt__Secret: "CHANGE_ME_LOCAL_DEV_SECRET_MIN_32_CHARS_LONG" - Cors__AllowedOrigins__0: "http://localhost:5173" + Cors__AllowedOrigins__0: "https://app.omsorg-pflegedienste.de" ports: - - "8080:8080" + # Nur auf dem Host erreichbar (für den Reverse-Proxy oben), nie auf der öffentlichen + # Schnittstelle - matcht das 127.0.0.1:5173-Muster im bestehenden Host-nginx. + - "127.0.0.1:8080:8080" volumes: - /root/data/omsorgcore/documents:/app/App_Data/documents omsorgapp: image: git.omsorg-pflegedienste.de/admin/omsorg/omsorgapp:${OMSORG_IMAGE_TAG:-latest} + environment: + # Vom BROWSER erreichbare Adresse von omsorgCore - der Container-Entrypoint schreibt das + # zur Laufzeit in env-config.js (siehe omsorgapp/docker-entrypoint.sh/src/api/config.js), + # kein Rebuild bei einer geänderten Backend-URL nötig. + OMSORG_CORE_URL: "https://core.omsorg-pflegedienste.de" ports: - - "5173:80" + # Nur auf dem Host, wie omsorgcore oben - der Host-nginx proxied bereits 127.0.0.1:5173. + - "127.0.0.1:5173:80" depends_on: - omsorgcore diff --git a/omsorgapp/Dockerfile b/omsorgapp/Dockerfile index c8e6023..c14ac44 100644 --- a/omsorgapp/Dockerfile +++ b/omsorgapp/Dockerfile @@ -13,9 +13,10 @@ RUN npm ci COPY omsorgapp/ . -# Vite bäckt import.meta.env.VITE_OMSORG_CORE_URL (src/api/config.js) zur Build-Zeit ein - kein -# Runtime-Wert. Default passt zum docker-compose.yml-Setup, für einen echten Deploy überschreibt -# CI das per --build-arg mit der öffentlich erreichbaren omsorgCore-URL. +# Fallback für lokale/CI-Builds ohne Container (npm run dev/build) - im Container selbst +# entscheidet ausschließlich die Laufzeit-Env-Var OMSORG_CORE_URL (siehe docker-entrypoint.sh), +# da dieses Image aus der Registry gezogen und per docker-compose.yml konfiguriert wird, nicht +# pro Zielumgebung neu gebaut (siehe src/api/config.js). ARG VITE_OMSORG_CORE_URL=http://localhost:8080 ENV VITE_OMSORG_CORE_URL=$VITE_OMSORG_CORE_URL RUN npm run build @@ -23,4 +24,7 @@ RUN npm run build FROM nginx:1.27-alpine AS runtime COPY --from=build /app/dist /usr/share/nginx/html COPY omsorgapp/nginx.conf /etc/nginx/conf.d/default.conf +COPY omsorgapp/docker-entrypoint.sh /docker-entrypoint.sh +RUN chmod +x /docker-entrypoint.sh EXPOSE 80 +ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/omsorgapp/docker-entrypoint.sh b/omsorgapp/docker-entrypoint.sh new file mode 100644 index 0000000..e8c72d4 --- /dev/null +++ b/omsorgapp/docker-entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -eu + +# Schreibt die Laufzeit-Backend-Adresse in env-config.js, bevor nginx startet - siehe +# src/api/config.js. OMSORG_CORE_URL kommt aus docker-compose.yml, muss vom BROWSER erreichbar +# sein (nicht der interne Compose-Servicename), z.B. https://core.omsorg-pflegedienste.de. +cat > /usr/share/nginx/html/env-config.js <Omsorg Business Controls Pro
+Omsorg Business Controls Pro
diff --git a/omsorgapp/public/env-config.js b/omsorgapp/public/env-config.js new file mode 100644 index 0000000..654ab80 --- /dev/null +++ b/omsorgapp/public/env-config.js @@ -0,0 +1,4 @@ +// Dev-Default (Vite serviert alles unter public/ unverändert unter /) - im Docker-Image wird +// diese Datei vom Entrypoint (docker-entrypoint.sh) aus der OMSORG_CORE_URL-Env-Var überschrieben, +// siehe src/api/config.js. +window.__OMSORG_ENV__ = {}; diff --git a/omsorgapp/src/api/config.js b/omsorgapp/src/api/config.js index f688fe4..bffa3b5 100644 --- a/omsorgapp/src/api/config.js +++ b/omsorgapp/src/api/config.js @@ -1,4 +1,8 @@ // Einzige Stelle im Projekt, die die Adresse von omsorgCore kennt. -// Default passt zum lokalen `dotnet run --project src/OmsorgCore.Api` (http-Profil, Port 5245), -// überschreibbar per Vite-Env-Variable (VITE_OMSORG_CORE_URL) für andere Umgebungen. -export const API_BASE = import.meta.env.VITE_OMSORG_CORE_URL || "http://localhost:5245"; +// Reihenfolge: 1) Laufzeit-Konfiguration (window.__OMSORG_ENV__, aus env-config.js - vom +// nginx-Entrypoint im Container aus der OMSORG_CORE_URL-Env-Var generiert, siehe +// omsorgapp/docker-entrypoint.sh) - so lässt sich die Backend-Adresse rein über +// docker-compose.yml setzen, ohne das Image neu zu bauen. 2) Vite-Build-Zeit-Env +// (VITE_OMSORG_CORE_URL, für `npm run dev`/lokale Builds ohne Container). 3) localhost-Default. +export const API_BASE = + window.__OMSORG_ENV__?.OMSORG_CORE_URL || import.meta.env.VITE_OMSORG_CORE_URL || "http://localhost:5245";