mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Merge pull request #21772 from opf/dev-tls-flexibility
Improve flexibility of TLS dev stack
This commit is contained in:
@@ -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
@@ -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"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
OPENPROJECT_DOCKER_DEV_TLD=local
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
OPENPROJECT_DOCKER_DEV_TLD=local
|
||||
@@ -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:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
OPENPROJECT_DOCKER_DEV_TLD=local
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
OPENPROJECT_DOCKER_DEV_TLD=local
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
OPENPROJECT_DOCKER_DEV_TLD=local
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
services:
|
||||
traefik:
|
||||
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
|
||||
# Overwrite to enable Let's encrypt instead of using Step CA for certificate generation
|
||||
# command: >
|
||||
# --entryPoints.websecure.http.tls.certresolver=letsencrypt
|
||||
# --certificatesresolvers.letsencrypt.acme.email=you@example.com
|
||||
|
||||
# For step CA only: Overwrite trusted CA certificates with Step root CA (not needed for Let's encrypt)
|
||||
environment:
|
||||
- LEGO_CA_CERTIFICATES=/step/certs/root_ca.crt
|
||||
|
||||
# Necessary for certificates via Step CA only
|
||||
depends_on:
|
||||
step:
|
||||
condition: service_healthy
|
||||
|
||||
# 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"
|
||||
|
||||
@@ -1,44 +1,29 @@
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:latest
|
||||
command: >
|
||||
--log.level=INFO
|
||||
--providers.docker
|
||||
--providers.docker.network=gateway
|
||||
--providers.docker.exposedByDefault=false
|
||||
--api.dashboard=true
|
||||
--api.disabledashboardad=true
|
||||
--entryPoints.web.address=:80
|
||||
--entryPoints.web.http.redirections.entrypoint.to=websecure
|
||||
--entryPoints.websecure.address=:443
|
||||
--entryPoints.websecure.http.tls=true
|
||||
--entryPoints.websecure.http.tls.certresolver=step
|
||||
--certificatesresolvers.step.acme.caserver=https://step:9000/acme/acme/directory
|
||||
--certificatesresolvers.step.acme.tlschallenge=true
|
||||
--certificatesresolvers.step.acme.email=root@localhost
|
||||
--certificatesresolvers.step.acme.keytype=RSA4096
|
||||
--certificatesresolvers.step.acme.storage=acme.json
|
||||
environment:
|
||||
- TZ=UTC
|
||||
- LEGO_CA_CERTIFICATES=/step/certs/root_ca.crt
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./traefik.yaml:/etc/traefik/traefik.yaml:ro
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./acme.json:/acme.json
|
||||
- step:/step:ro
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
step:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
external:
|
||||
aliases:
|
||||
- traefik.local
|
||||
- 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.enable=true"
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.local`)"
|
||||
- "traefik.http.routers.traefik.rule=Host(`traefik.${OPENPROJECT_DOCKER_DEV_TLD}`)"
|
||||
- "traefik.http.routers.traefik.service=api@internal"
|
||||
- "traefik.http.routers.traefik.entrypoints=websecure"
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
log:
|
||||
level: INFO
|
||||
|
||||
api:
|
||||
dashboard: true
|
||||
disabledashboardad: true
|
||||
|
||||
providers:
|
||||
docker:
|
||||
network: gateway
|
||||
exposedByDefault: false
|
||||
|
||||
entryPoints:
|
||||
web:
|
||||
address: ":80"
|
||||
http:
|
||||
redirections:
|
||||
entrypoint:
|
||||
to: websecure
|
||||
websecure:
|
||||
address: ":443"
|
||||
http:
|
||||
tls:
|
||||
certresolver: step # Using step by default, overwritable via CLI
|
||||
|
||||
certificatesresolvers:
|
||||
step:
|
||||
acme:
|
||||
caserver: https://step:9000/acme/acme/directory
|
||||
tlschallenge: true
|
||||
email: root@localhost
|
||||
keytype: RSA4096
|
||||
storage: acme.json
|
||||
letsencrypt:
|
||||
acme:
|
||||
keytype: RSA4096
|
||||
storage: acme.json
|
||||
httpChallenge:
|
||||
entryPoint: web
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user