Allow to change TLD for docker dev stack

Instead of assuming that the TLD is .local, we allow
to overwrite it with different TLDs, so that the local setup
can be adapted to developer needs.
This commit is contained in:
Jan Sandbrink
2026-01-26 10:30:48 +01:00
parent fc15231737
commit 827f577c85
18 changed files with 75 additions and 46 deletions
+3
View File
@@ -44,6 +44,9 @@ PORT=3000
FE_HOST=localhost
FE_PORT=4200
# Default TLD for docker dev stack (e.g. when set to "local", services will be openproject.local, nextcloud.local, etc.)
OPENPROJECT_DOCKER_DEV_TLD=local
# Use this variables to configure hostnames for frontend and backend, e.g. to enable HTTPS in docker development setup
OPENPROJECT_DEV_HOST=localhost
OPENPROJECT_DEV_URL=http://${OPENPROJECT_DEV_HOST}:${FE_PORT}
+1 -1
View File
@@ -87,7 +87,7 @@ services:
networks:
- network
environment:
__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS: "openproject-assets.local"
__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS: "openproject-assets.${OPENPROJECT_DOCKER_DEV_TLD}"
ports:
- "${FE_PORT:-4200}:4200"
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
+2 -2
View File
@@ -19,10 +19,10 @@ services:
networks:
- external
extra_hosts:
- "openproject.local:host-gateway"
- "openproject.${OPENPROJECT_DOCKER_DEV_TLD}:host-gateway"
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.rule=Host(`gitlab.local`)"
- "traefik.http.routers.gitlab.rule=Host(`gitlab.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.gitlab.entrypoints=websecure"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
+2 -2
View File
@@ -5,7 +5,7 @@ services:
image: openproject/hocuspocus:latest
labels:
- "traefik.enable=true"
- "traefik.http.routers.hocuspocus.rule=Host(`hocuspocus.local`)"
- "traefik.http.routers.hocuspocus.rule=Host(`hocuspocus.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.hocuspocus.service=hocuspocus-service"
- "traefik.http.routers.hocuspocus.tls=true"
- "traefik.http.services.hocuspocus-service.loadbalancer.server.port=1234"
@@ -14,7 +14,7 @@ services:
networks:
- gateway
environment:
- ALLOWED_DOMAINS=openproject.local,localhost
- ALLOWED_DOMAINS=openproject.${OPENPROJECT_DOCKER_DEV_TLD},localhost
- NODE_TLS_REJECT_UNAUTHORIZED=0
- SECRET=secret12345
networks:
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
+2 -4
View File
@@ -35,7 +35,7 @@ services:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin
- KC_DB_SCHEMA=public
- KC_HOSTNAME=keycloak.local
- KC_HOSTNAME=keycloak.${OPENPROJECT_DOCKER_DEV_TLD}
- KC_TRANSACTION_XA_ENABLED=false
volumes:
- /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt:ro
@@ -43,10 +43,8 @@ services:
- ./themes/:/opt/keycloak/themes/
labels:
- "traefik.enable=true"
- "traefik.http.routers.keycloak-sub-secure.rule=Host(`keycloak.local`)"
- "traefik.http.routers.keycloak-sub-secure.rule=Host(`keycloak.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.keycloak-sub-secure.entrypoints=websecure"
- "traefik.http.routers.keycloak-sub-secure.tls=true"
- "traefik.http.routers.keycloak-sub-secure.tls.certresolver=step"
depends_on:
- db-keycloak
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
+2 -2
View File
@@ -19,13 +19,13 @@ services:
- "traefik.enable=true"
# MinIO API
- "traefik.http.routers.minio.entrypoints=websecure"
- "traefik.http.routers.minio.rule=Host(`minio.local`)"
- "traefik.http.routers.minio.rule=Host(`minio.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.minio.service=minio"
- "traefik.http.routers.minio.tls.certresolver=step"
- "traefik.http.services.minio.loadbalancer.server.port=9000"
# MinIO Admin Console (Management UI)
- "traefik.http.routers.minioadmin.entrypoints=websecure"
- "traefik.http.routers.minioadmin.rule=Host(`minioadmin.local`)"
- "traefik.http.routers.minioadmin.rule=Host(`minioadmin.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.minioadmin.service=minioadmin"
- "traefik.http.routers.minioadmin.tls.certresolver=step"
- "traefik.http.services.minioadmin.loadbalancer.server.port=9001"
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
+1 -1
View File
@@ -11,7 +11,7 @@ services:
# - ../nextcloud_apps:/var/www/html/custom_apps
labels:
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.local`)"
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
cron:
+1
View File
@@ -0,0 +1 @@
OPENPROJECT_DOCKER_DEV_TLD=local
@@ -6,30 +6,30 @@ x-op-env-override: &environment
SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt
# uncomment and set all the envs below to integrate keycloak with OpenProject
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_DISPLAY__NAME: Keycloak
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_HOST: keycloak.local
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_IDENTIFIER: https://openproject.local
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_HOST: keycloak.${OPENPROJECT_DOCKER_DEV_TLD}
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_IDENTIFIER: https://openproject.${OPENPROJECT_DOCKER_DEV_TLD}
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_SECRET: <The client secret you copied from keycloak>
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_ISSUER: https://keycloak.local/realms/<REALM>
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_ISSUER: https://keycloak.${OPENPROJECT_DOCKER_DEV_TLD}/realms/<REALM>
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_AUTHORIZATION__ENDPOINT: /realms/<REALM>/protocol/openid-connect/auth
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_TOKEN__ENDPOINT: /realms/<REALM>/protocol/openid-connect/token
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_USERINFO__ENDPOINT: /realms/<REALM>/protocol/openid-connect/userinfo
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_END__SESSION__ENDPOINT: https://keycloak.local/realms/<REALM>/protocol/openid-connect/logout
# OPENPROJECT_OPENID__CONNECT_KEYCLOAK_END__SESSION__ENDPOINT: https://keycloak.${OPENPROJECT_DOCKER_DEV_TLD}/realms/<REALM>/protocol/openid-connect/logout
# uncomment the following for using minio (local S3) as file storage with TLS support:
# OPENPROJECT_ATTACHMENTS__STORAGE: "fog"
# OPENPROJECT_FOG_DIRECTORY: "openproject-uploads"
# OPENPROJECT_FOG_CREDENTIALS_PROVIDER: "AWS" # Minio is S3 compliant, so we can use the AWS provider
# OPENPROJECT_FOG_CREDENTIALS_ENDPOINT: "https://minio.local"
# OPENPROJECT_FOG_CREDENTIALS_ENDPOINT: "https://minio.${OPENPROJECT_DOCKER_DEV_TLD}"
# OPENPROJECT_FOG_CREDENTIALS_AWS__ACCESS__KEY__ID: "minioadmin"
# OPENPROJECT_FOG_CREDENTIALS_AWS__SECRET__ACCESS__KEY: "minioadmin"
# OPENPROJECT_FOG_CREDENTIALS_PATH__STYLE: "true"
# OPENPROJECT_FOG_CREDENTIALS_REGION: "us-east-1"
# OPENPROJECT_DEV_EXTRA_HOSTS: "${OPENPROJECT_DEV_HOST},minio.local"
# OPENPROJECT_DEV_EXTRA_HOSTS: "${OPENPROJECT_DEV_HOST},minio.${OPENPROJECT_DOCKER_DEV_TLD}"
services:
backend:
environment:
<<: *environment
OPENPROJECT_CLI_PROXY: "https://openproject-assets.local"
OPENPROJECT_CLI_PROXY: "https://openproject-assets.${OPENPROJECT_DOCKER_DEV_TLD}"
networks:
- external
volumes:
@@ -42,7 +42,7 @@ services:
# - ~/.step/certs:/usr/local/share/ca-certificates
labels:
- "traefik.enable=true"
- "traefik.http.routers.openproject.rule=Host(`openproject.local`)"
- "traefik.http.routers.openproject.rule=Host(`openproject.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.openproject.entrypoints=websecure"
worker:
@@ -77,7 +77,7 @@ services:
- external
labels:
- "traefik.enable=true"
- "traefik.http.routers.openproject-assets.rule=Host(`openproject-assets.local`)"
- "traefik.http.routers.openproject-assets.rule=Host(`openproject-assets.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.openproject-assets.entrypoints=websecure"
# You need to define the same external network
@@ -14,18 +14,7 @@ services:
step:
condition: service_healthy
networks:
external:
aliases:
# Traefik is aliased to all the services that run behind it here.
# The reason to do this is that step-ca tries to validate the domains
# by connecting to them, and we'd like it to go through traefik, instead
# of calling the service containers directly.
- openproject.local
- openproject-assets.local
- nextcloud.local
- gitlab.local
- keycloak.local
- hocuspocus.local
- minio.local
- minioadmin.local
# Enabling traefik for the traefik container itself will give you access to the Traefik Dashboard, which can be a useful
# tool to inspect whether everything is working fine. It's not advised to publicly expose this dashboard.
labels:
- "traefik.enable=true"
+16
View File
@@ -10,6 +10,22 @@ services:
- ./acme.json:/acme.json
- step:/step:ro
restart: unless-stopped
networks:
external:
aliases:
- traefik.${OPENPROJECT_DOCKER_DEV_TLD}
- openproject.${OPENPROJECT_DOCKER_DEV_TLD}
- openproject-assets.${OPENPROJECT_DOCKER_DEV_TLD}
- nextcloud.${OPENPROJECT_DOCKER_DEV_TLD}
- gitlab.${OPENPROJECT_DOCKER_DEV_TLD}
- keycloak.${OPENPROJECT_DOCKER_DEV_TLD}
- hocuspocus.${OPENPROJECT_DOCKER_DEV_TLD}
- minio.${OPENPROJECT_DOCKER_DEV_TLD}
- minioadmin.${OPENPROJECT_DOCKER_DEV_TLD}
labels:
- "traefik.http.routers.traefik.rule=Host(`traefik.${OPENPROJECT_DOCKER_DEV_TLD}`)"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.entrypoints=websecure"
step:
image: smallstep/step-ca:latest
+7
View File
@@ -1,9 +1,15 @@
log:
level: INFO
api:
dashboard: true
disabledashboardad: true
providers:
docker:
network: gateway
exposedByDefault: false
entryPoints:
web:
address: ":80"
@@ -16,6 +22,7 @@ entryPoints:
http:
tls:
certresolver: step # Using step by default, overwritable via CLI
certificatesresolvers:
step:
acme:
@@ -264,13 +264,6 @@ define for your services to your `/etc/hosts`.
::1 openproject.local openproject-assets.local traefik.local
```
#### DNS? Where are you?
We have plans to add a local DNS to this development setup, making two things possible:
1. No requirement to amend your `/etc/hosts` file anymore.
2. Being accessible from another device within your internal network (e.g. a cellphone).
### Local certificate authority
We use [traefik](https://traefik.io/) as a reverse proxy and [step-ca](https://smallstep.com/docs/step-ca/) as a local
@@ -457,6 +450,23 @@ to have Nextcloud running to test the Nextcloud-OpenProject integration. To do t
2. Make sure step-ca can reach it to validate it for SSH. In `docker/dev/tls/docker-compose.override.yml`, add the host
to the `aliases` section of the traefik networking.
### Alternative: Using Let's encrypt
An alternative approach is to issue certificates through Let's encrypt. This allows you to skip steps related to usage and setup
of a custom, non-trusted CA. However, it requires that you have access to a domain name that you control and requires additional
step to make the reverse proxy publicly reachable, which is not in scope of what this documentation can cover.
If you need such a setup, you can change the `docker-compose.override.yml` for the reverse proxy, to use `letsencrypt` (see the
corresponding `docker-compose.override.example.yml`). Make sure to export an environment variable with your alternative DNS zone
before starting anything via docker compose. For example:
```bash
export OPENPROJECT_DOCKER_DEV_TLD=dev.example.com
docker compose up -d backend frontend
```
Will make your containers available under openproject.dev.example.com and openproject-assets.dev.example.com respectively.
### Troubleshooting
After this setup you should be able to access your OpenProject development instance at `https://openproject.local`. If
@@ -564,7 +574,7 @@ Upon setting up all the things correctly, we can see a login with `keycloak` opt
## MinIO Service (local S3 storage backend)
Within `docker/dev/minio` a compose file is provided for running a local MinIO instance with TLS support which can be used as a S3 storage for uploading files.
Within `docker/dev/minio` a compose file is provided for running a local MinIO instance with TLS support which can be used as a S3 storage for uploading files.
When running with TLS support, the MinIO instance will be accessible on `https://minio.local` and a management UI (MinIO Console) will be available on `https://minioadmin.local/`.
### Running the MinIO Instance
@@ -578,8 +588,8 @@ docker compose --project-directory docker/dev/minio up -d
```
This will automatically create a bucket named `openproject-uploads` which is used to store uploaded files.
If you want to use TLS support, make sure to copy and uncomment the MinIO configuration environment variables in `docker/dev/tls/docker-compose.core.override.example.yml` to your `docker-compose.override.yml` file in the project root directory. If you want to use MinIO without TLS support, make sure to copy the environment variables from `docker/dev/minio/docker-compose.core-override.example.yml` to your `docker-compose.override.yml` file (in the project root directory).
After that, hard restart the `backend` service to apply the changes:
If you want to use TLS support, make sure to copy and uncomment the MinIO configuration environment variables in `docker/dev/tls/docker-compose.core.override.example.yml` to your `docker-compose.override.yml` file in the project root directory. If you want to use MinIO without TLS support, make sure to copy the environment variables from `docker/dev/minio/docker-compose.core-override.example.yml` to your `docker-compose.override.yml` file (in the project root directory).
After that, hard restart the `backend` service to apply the changes:
```
docker compose down backend