diff --git a/.env.example b/.env.example index 6e0da0a1..55932fef 100644 --- a/.env.example +++ b/.env.example @@ -45,3 +45,12 @@ API_CLIENT_REGISTRY=forge.lclr.dev API_CLIENT_NAMESPACE=thibaud-lclr API_CLIENT_IMAGE_PREFIX=api-client API_CLIENT_TAG=latest + +#-----------------------Coolify Prod Local Defaults----------------# +# Used only when running docker-compose.prod.yml locally. +# Coolify generates these SERVICE_* values itself in production. +SERVICE_FQDN_HOPPSCOTCH_80=http://localhost:3000 +SERVICE_FQDN_HOPPSCOTCH=http://localhost:3000 +SERVICE_URL_HOPPSCOTCH=localhost:3000 +SERVICE_PASSWORD_POSTGRES=testpass +SERVICE_BASE64_DATA_ENCRYPTION_KEY=0123456789abcdef0123456789abcdef diff --git a/Makefile b/Makefile index 7efdf2aa..47a203fa 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,7 @@ NAMESPACE ?= thibaud-lclr IMAGE_PREFIX ?= api-client TAG ?= latest -BACKEND_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-backend:$(TAG) -APP_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-app:$(TAG) -SH_ADMIN_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-sh-admin:$(TAG) +AIO_IMAGE := $(REGISTRY)/$(NAMESPACE)/$(IMAGE_PREFIX)-aio:$(TAG) PROD_ENV := API_CLIENT_REGISTRY=$(REGISTRY) API_CLIENT_NAMESPACE=$(NAMESPACE) API_CLIENT_IMAGE_PREFIX=$(IMAGE_PREFIX) API_CLIENT_TAG=$(TAG) @@ -52,13 +50,9 @@ ensure-env: @test -f $(ENV_FILE) || cp $(ENV_EXAMPLE) $(ENV_FILE) docker-build-images: - docker build --file prod.Dockerfile --target backend --tag $(BACKEND_IMAGE) . - docker build --file prod.Dockerfile --target app --tag $(APP_IMAGE) . - docker build --file prod.Dockerfile --target sh_admin --tag $(SH_ADMIN_IMAGE) . + docker build --file prod.Dockerfile --target aio --tag $(AIO_IMAGE) . docker-push-images: - docker push $(BACKEND_IMAGE) - docker push $(APP_IMAGE) - docker push $(SH_ADMIN_IMAGE) + docker push $(AIO_IMAGE) docker-build-push-images: docker-build-images docker-push-images diff --git a/README.md b/README.md index 8a3fc788..4cdeacf0 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,10 @@ Fork interne de Hoppscotch pour déploiement self-host. Les images sont buildées en local puis poussées à la main sur le registry. -Images utilisées en prod : +Image utilisée en prod : ```text -forge.lclr.dev/thibaud-lclr/api-client-backend:latest -forge.lclr.dev/thibaud-lclr/api-client-app:latest -forge.lclr.dev/thibaud-lclr/api-client-sh-admin:latest +forge.lclr.dev/thibaud-lclr/api-client-aio:latest ``` Targets Docker : @@ -29,6 +27,7 @@ Targets Docker : backend -> backend + Caddy backend app -> app web + webapp-server + Caddy app sh_admin -> admin + Caddy admin +aio -> app, admin, backend et webapp-server derrière un Caddy unique ``` ## Préparer l'environnement @@ -39,7 +38,7 @@ Créer `.env` si besoin : make ensure-env ``` -Variables importantes : +Variables importantes pour le compose dev : ```env POSTGRES_PASSWORD= @@ -66,6 +65,10 @@ API_CLIENT_IMAGE_PREFIX=api-client API_CLIENT_TAG=latest ``` +Le compose prod local utilise aussi les valeurs `SERVICE_*` présentes dans +`.env.example`. En production Coolify, ces valeurs sont générées par Coolify à +partir de `docker-compose.prod.yml`. + ## Build et push registry Se connecter au registry : @@ -74,13 +77,13 @@ Se connecter au registry : docker login forge.lclr.dev ``` -Builder les trois images en `latest` : +Builder l'image prod en `latest` : ```sh make docker-build-images TAG=latest ``` -Pousser les trois images : +Pousser l'image prod : ```sh make docker-push-images TAG=latest @@ -105,22 +108,27 @@ La prod utilise uniquement `docker-compose.prod.yml`. Ce compose ne contient pas de `build:`. Il tire les images du registry. Sur Coolify, `docker-compose.prod.yml` est la source de vérité des variables -d'environnement. Les variables sont déclarées dans les blocs `environment:` des -services pour que Coolify les crée dans son UI au chargement du compose. Il ne -faut pas compter sur un fichier `.env` du dépôt en prod : il est ignoré par Git. +d'environnement. Les variables sont déclarées dans les blocs `environment:` pour +que Coolify les crée dans son UI au chargement du compose. Il ne faut pas +compter sur un fichier `.env` du dépôt en prod : il est ignoré par Git. + +Le compose prod utilise l'image AIO et un seul domaine Coolify : + +- `/` : app web +- `/admin` : admin +- `/backend` : backend GraphQL/API Variables générées/préremplies pour Coolify : -- `SERVICE_PASSWORD_POSTGRES` : mot de passe PostgreSQL partagé entre la base et le backend -- `SERVICE_BASE64_DATA_ENCRYPTION_KEY` : clé stable de 32 caractères pour `DATA_ENCRYPTION_KEY` -- `SERVICE_URL_HOPPSCOTCH_APP` : URL publique de l'app -- `SERVICE_URL_HOPPSCOTCH_ADMIN` : URL publique de l'admin -- `SERVICE_URL_HOPPSCOTCH_BACKEND` : URL publique du backend -- `SERVICE_FQDN_HOPPSCOTCH_BACKEND` : domaine du backend, utilisé pour `VITE_BACKEND_WS_URL` +- `SERVICE_FQDN_HOPPSCOTCH_80` : domaine public unique du service +- `SERVICE_FQDN_HOPPSCOTCH` : URL publique générée depuis le domaine +- `SERVICE_URL_HOPPSCOTCH` : domaine sans schéma, utilisé pour le WebSocket +- `SERVICE_PASSWORD_POSTGRES` : mot de passe PostgreSQL généré +- `SERVICE_BASE64_DATA_ENCRYPTION_KEY` : clé stable générée de 32 caractères pour `DATA_ENCRYPTION_KEY` -Après l'import du compose dans Coolify, vérifier au minimum que les trois URLs -publiques correspondent aux domaines assignés aux services app, admin et -backend. +Après l'import du compose dans Coolify, renseigner uniquement le domaine du +service `hoppscotch`. Les URLs app/admin/backend sont ensuite dérivées par +sous-chemins. Démarrer avec le tag `latest` : @@ -155,16 +163,13 @@ make prod-down Services prod : - `hoppscotch-db` : PostgreSQL 15 avec volume persistant -- `hoppscotch-backend` : backend + migrations Prisma au démarrage -- `hoppscotch-app` : app web self-host -- `hoppscotch-sh-admin` : admin +- `hoppscotch` : app web, admin, backend, serveur de bundles et migrations Prisma au démarrage -Ports prod : +Routage prod : -- `3000` : app web -- `3100` : admin -- `3170` : backend -- `3200` : serveur de bundles webapp +- `/` : app web +- `/admin` : admin +- `/backend` : backend ## Développement local diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index b5e00d9a..550db48d 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -4,7 +4,7 @@ services: user: postgres environment: - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES:-testpass} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - POSTGRES_DB=${POSTGRES_DB:-hoppscotch} volumes: - hoppscotch-db:/var/lib/postgresql/data @@ -18,74 +18,35 @@ services: timeout: 5s retries: 10 - hoppscotch-backend: - container_name: hoppscotch-backend + hoppscotch: restart: unless-stopped - image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-backend:${API_CLIENT_TAG:-latest} + image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-aio:${API_CLIENT_TAG:-latest} environment: - - DATABASE_URL=postgresql://postgres:${SERVICE_PASSWORD_POSTGRES:-testpass}@hoppscotch-db:5432/${POSTGRES_DB:-hoppscotch} - - DATA_ENCRYPTION_KEY=${SERVICE_BASE64_DATA_ENCRYPTION_KEY:-0123456789abcdef0123456789abcdef} - - VITE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_SHORTCODE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_ADMIN_URL=${SERVICE_URL_HOPPSCOTCH_ADMIN:-http://localhost:3100} - - VITE_BACKEND_GQL_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/graphql - - VITE_BACKEND_WS_URL=wss://${SERVICE_FQDN_HOPPSCOTCH_BACKEND:-localhost:3170}/graphql - - VITE_BACKEND_API_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/v1 + - SERVICE_FQDN_HOPPSCOTCH_80 + - DATABASE_URL=postgresql://postgres:${SERVICE_PASSWORD_POSTGRES}@hoppscotch-db:5432/${POSTGRES_DB:-hoppscotch} + - DATA_ENCRYPTION_KEY=${SERVICE_BASE64_DATA_ENCRYPTION_KEY} + - REDIRECT_URL=${SERVICE_FQDN_HOPPSCOTCH} + - VITE_BASE_URL=${SERVICE_FQDN_HOPPSCOTCH} + - VITE_SHORTCODE_BASE_URL=${SERVICE_FQDN_HOPPSCOTCH} + - VITE_ADMIN_URL=${SERVICE_FQDN_HOPPSCOTCH}/admin + - VITE_BACKEND_GQL_URL=${SERVICE_FQDN_HOPPSCOTCH}/backend/graphql + - VITE_BACKEND_WS_URL=wss://${SERVICE_URL_HOPPSCOTCH}/backend/graphql + - VITE_BACKEND_API_URL=${SERVICE_FQDN_HOPPSCOTCH}/backend/v1 - VITE_APP_TOS_LINK=${VITE_APP_TOS_LINK:-https://docs.hoppscotch.io/support/terms} - VITE_APP_PRIVACY_POLICY_LINK=${VITE_APP_PRIVACY_POLICY_LINK:-https://docs.hoppscotch.io/support/privacy} - VITE_PROXYSCOTCH_ACCESS_TOKEN=${VITE_PROXYSCOTCH_ACCESS_TOKEN:-} - - ENABLE_SUBPATH_BASED_ACCESS=${ENABLE_SUBPATH_BASED_ACCESS:-false} - - WHITELISTED_ORIGINS=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000},${SERVICE_URL_HOPPSCOTCH_ADMIN:-http://localhost:3100} + - ENABLE_SUBPATH_BASED_ACCESS=true + - WHITELISTED_ORIGINS=${SERVICE_FQDN_HOPPSCOTCH}/backend,${SERVICE_FQDN_HOPPSCOTCH},${SERVICE_FQDN_HOPPSCOTCH}/admin - TRUST_PROXY=${TRUST_PROXY:-true} depends_on: hoppscotch-db: condition: service_healthy command: - ["sh", "-c", "pnpm exec prisma migrate deploy && node prod_run.mjs"] - ports: - - "3170:3170" - - hoppscotch-app: - container_name: hoppscotch-app - restart: unless-stopped - image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-app:${API_CLIENT_TAG:-latest} - environment: - - VITE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_SHORTCODE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_ADMIN_URL=${SERVICE_URL_HOPPSCOTCH_ADMIN:-http://localhost:3100} - - VITE_BACKEND_GQL_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/graphql - - VITE_BACKEND_WS_URL=wss://${SERVICE_FQDN_HOPPSCOTCH_BACKEND:-localhost:3170}/graphql - - VITE_BACKEND_API_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/v1 - - VITE_APP_TOS_LINK=${VITE_APP_TOS_LINK:-https://docs.hoppscotch.io/support/terms} - - VITE_APP_PRIVACY_POLICY_LINK=${VITE_APP_PRIVACY_POLICY_LINK:-https://docs.hoppscotch.io/support/privacy} - - VITE_PROXYSCOTCH_ACCESS_TOKEN=${VITE_PROXYSCOTCH_ACCESS_TOKEN:-} - - ENABLE_SUBPATH_BASED_ACCESS=${ENABLE_SUBPATH_BASED_ACCESS:-false} - depends_on: - hoppscotch-backend: - condition: service_started - ports: - - "3000:3000" - - "3200:3200" - - hoppscotch-sh-admin: - container_name: hoppscotch-sh-admin - restart: unless-stopped - image: ${API_CLIENT_REGISTRY:-forge.lclr.dev}/${API_CLIENT_NAMESPACE:-thibaud-lclr}/${API_CLIENT_IMAGE_PREFIX:-api-client}-sh-admin:${API_CLIENT_TAG:-latest} - environment: - - VITE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_SHORTCODE_BASE_URL=${SERVICE_URL_HOPPSCOTCH_APP:-http://localhost:3000} - - VITE_ADMIN_URL=${SERVICE_URL_HOPPSCOTCH_ADMIN:-http://localhost:3100} - - VITE_BACKEND_GQL_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/graphql - - VITE_BACKEND_API_URL=${SERVICE_URL_HOPPSCOTCH_BACKEND:-http://localhost:3170}/v1 - - VITE_APP_TOS_LINK=${VITE_APP_TOS_LINK:-https://docs.hoppscotch.io/support/terms} - - VITE_APP_PRIVACY_POLICY_LINK=${VITE_APP_PRIVACY_POLICY_LINK:-https://docs.hoppscotch.io/support/privacy} - - VITE_PROXYSCOTCH_ACCESS_TOKEN=${VITE_PROXYSCOTCH_ACCESS_TOKEN:-} - - ENABLE_SUBPATH_BASED_ACCESS=${ENABLE_SUBPATH_BASED_ACCESS:-false} - depends_on: - hoppscotch-backend: - condition: service_started - ports: - - "3100:3100" + [ + "sh", + "-c", + "pnpm exec prisma migrate deploy && node /usr/src/app/aio_run.mjs", + ] volumes: hoppscotch-db: