Merge pull request #55 from opencloud-eu/certificates

feat: make it possible to add local certificates
This commit is contained in:
Michael Barz
2025-07-01 14:49:45 +02:00
committed by GitHub
10 changed files with 203 additions and 54 deletions

View File

@@ -45,6 +45,22 @@ TRAEFIK_ACME_MAIL=
# When certificates are displayed and are emitted by # "Fake LE Intermediate X1",
# the process went well and the envvar can be reset to empty to get valid certificates.
TRAEFIK_ACME_CASERVER=
# Enable the Traefik ACME (Automatic Certificate Management Environment) for automatic SSL certificate management.
TRAEFIK_SERVICES_TLS_CONFIG="tls.certresolver=letsencrypt"
# Enable Traefik to use local certificates.
#TRAEFIK_SERVICES_TLS_CONFIG="tls=true"
# You also need to provide a config file in ./config/traefik/dynamic/certs.yml
# Example:
# cat ./config/traefik/dynamic/certs.yml
# tls:
# certificates:
# - certFile: /certs/opencloud.test.crt
# keyFile: /certs/opencloud.test.key
# stores:
# - default
#
# The certificates need to copied into ./certs/, the absolute path inside the container is /certs/.
# You can also use TRAEFIK_CERTS_DIR=/path/on/host to set the path to the certificates directory.
## OpenCloud Settings ##

11
.gitignore vendored
View File

@@ -3,7 +3,16 @@
.env
# exclude the apps folder
/config/opencloud/apps
/config/opencloud/apps/*
!/config/opencloud/apps/.gitkeep
# exclude custom compose files
/custom
# exclude certificates
/certs/*
!/certs/.gitkeep
# exclude the certificates config folder
/config/traefik/dynamic/*
!/config/traefik/dynamic/.gitkeep

View File

@@ -6,7 +6,7 @@ This repository provides Docker Compose configurations for deploying OpenCloud i
OpenCloud Compose offers a modular approach to deploying OpenCloud with several configuration options:
- **Standard deployment** with Traefik reverse proxy and Let's Encrypt certificates
- **Standard deployment** with Traefik reverse proxy and Let's Encrypt certificates or certificates from files
- **External proxy** support for environments with existing reverse proxies (like Nginx, Caddy, etc.)
- **Collabora Online** integration for document editing
- **Keycloak and LDAP** integration for centralized identity management
@@ -226,6 +226,77 @@ If you're using **Nginx Proxy Manager (NPM)**, you **should NOT** activate **"Bl
Otherwise, the desktop app authentication will return **error 403 Forbidden**.
## SSL Certificate Support
OpenCloud Compose supports adding SSL certificates for public domains and development environments. This feature enables you to use the "Let's Encrypt ACME challenge" to generate certificates for your public domains as well as using your own certificates.
### Use Let's Encrypt with ACME Challenge
1. **Enable Let's Encrypt**:
- Set `TRAEFIK_LETSENCRYPT_EMAIL` to your email address for the ACME challenge
- Set `TRAEFIK_SERVICES_TLS_CONFIG="tls.certresolver=letsencrypt"` to use Let's Encrypt (default value)
```bash
# In your .env file
TRAEFIK_LETSENCRYPT_EMAIL=devops@your-domain.tld
TRAEFIK_SERVICES_TLS_CONFIG="tls.certresolver=letsencrypt"
```
### Use Certificates from the `certs/` directory
1. **Place your certificates**:
- Copy your certificate files (`.crt`, `.pem`, `.key`) to the `certs/` directory
- The directory structure is flexible - organize as needed for your setup
2. **Configure Traefik dynamic configuration**:
- Place Traefik dynamic configuration files in `config/traefik/dynamic/`
Example `config/traefik/dynamic/certs.yml`:
```yaml
tls:
certificates:
- certFile: /certs/opencloud.test.crt
keyFile: /certs/opencloud.test.key
stores:
- default
- certFile: /certs/wildcard.example.com.crt
keyFile: /certs/wildcard.example.com.key
stores:
- default
```
3. **Configure environment variables**:
- Set `TRAEFIK_SERVICES_TLS_CONFIG="tls=true"` to use your local certificates
```bash
# In your .env file
TRAEFIK_SERVICES_TLS_CONFIG="tls=true"
```
The certificate directory and configuration directories are now available and automatically mounted in the containers:
- `certs/` → `/certs/` (inside the Traefik container)
- `config/traefik/dynamic/` → dynamic configuration loading
> [!TIP]
>
> **Local development or testing with mkcert**
> For local development, you can use `mkcert` to generate self-signed certificates for your local domains. This allows you to test SSL/TLS configurations without needing a public domain or Let's Encrypt. It also brings the advantage that you don't have to accept self-signed certificates in your browser all the time.
> ```bash
> # Install mkcert (if not already installed)
> # macOS: brew install mkcert
> # Linux: apt install mkcert or similar
> # Windows: choco install mkcert or download from GitHub
>
> # Install the local CA
> mkcert -install
>
> # Generate certificates for your local domains
> mkcert -cert-file certs/opencloud.test.crt -key-file certs/opencloud.test.key "*.opencloud.test" opencloud.test
> ```
> [!IMPORTANT]
> The contents of the `certs/` directory and configuration directories are ignored by git to prevent accidentally committing sensitive certificate files.
## Configuration
### Environment Variables
@@ -239,7 +310,7 @@ The configuration is managed through environment variables in the `.env` file:
Key variables:
| Variable | Description | Default |
|---------------------------|----------------------------------------------|---------------------------|
|------------------------------------|-------------------------------------------------------|------------------------------|
| `COMPOSE_FILE` | Colon-separated list of compose files to use | (commented out) |
| `OC_DOMAIN` | OpenCloud domain | cloud.opencloud.test |
| `OC_DOCKER_TAG` | OpenCloud image tag | latest |
@@ -255,6 +326,9 @@ Key variables:
| `LDAP_BIND_PASSWORD` | LDAP password for the bind user | admin |
| `KC_DB_USERNAME` | Database user for keycloak | keycloak |
| `KC_DB_PASSWORD` | Database password for keycloak | keycloak |
| `TRAEFIK_LETSENCRYPT_EMAIL` | Email Address for the Let's Encrypt ACME challenge | example@example.org |
| `TRAEFIK_SERVICES_TLS_CONFIG` | Tell traefik and the services which TLS config to use | tls.certresolver=letsencrypt |
| `TRAEFIK_CERTS_DIR` | Directory for custom certificates. | ./certs |
See `.env.example` for all available options and their documentation.

0
certs/.gitkeep Normal file
View File

View File

View File

@@ -0,0 +1,72 @@
set -e
printenv
# Function to add arguments to the command
add_arg() {
TRAEFIK_CMD="$TRAEFIK_CMD $1"
}
# Initialize the base command
TRAEFIK_CMD="traefik"
# Base Traefik arguments (from your existing configuration)
add_arg "--log.level=${TRAEFIK_LOG_LEVEL:-ERROR}"
# enable dashboard
add_arg "--api.dashboard=true"
# define entrypoints
add_arg "--entryPoints.http.address=:80"
add_arg "--entryPoints.http.http.redirections.entryPoint.to=https"
add_arg "--entryPoints.http.http.redirections.entryPoint.scheme=https"
add_arg "--entryPoints.https.address=:443"
# change default timeouts for long-running requests
# this is needed for webdav clients that do not support the TUS protocol
add_arg "--entryPoints.https.transport.respondingTimeouts.readTimeout=12h"
add_arg "--entryPoints.https.transport.respondingTimeouts.writeTimeout=12h"
add_arg "--entryPoints.https.transport.respondingTimeouts.idleTimeout=3m"
# docker provider (get configuration from container labels)
add_arg "--providers.docker.endpoint=unix:///var/run/docker.sock"
add_arg "--providers.docker.exposedByDefault=false"
# access log
add_arg "--accessLog=true"
add_arg "--accessLog.format=json"
add_arg "--accessLog.fields.headers.names.X-Request-Id=keep"
# Add Let's Encrypt configuration if enabled
if [ "${TRAEFIK_SERVICES_TLS_CONFIG}" = "tls.certresolver=letsencrypt" ]; then
echo "Configuring Traefik with Let's Encrypt..."
add_arg "--certificatesResolvers.letsencrypt.acme.email=${TRAEFIK_ACME_MAIL:-example@example.org}"
add_arg "--certificatesResolvers.letsencrypt.acme.storage=/certs/acme.json"
add_arg "--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http"
add_arg "--certificatesResolvers.letsencrypt.acme.caserver=${TRAEFIK_ACME_CASERVER:-https://acme-v02.api.letsencrypt.org/directory}"
fi
# Add local certificate configuration if enabled
if [ "${TRAEFIK_SERVICES_TLS_CONFIG}" = "tls=true" ]; then
echo "Configuring Traefik with local certificates..."
add_arg "--providers.file.directory=/etc/traefik/dynamic"
add_arg "--providers.file.watch=true"
fi
# Warning if neither certificate method is enabled
if [ "${TRAEFIK_SERVICES_TLS_CONFIG}" != "tls=true" ] && [ "${TRAEFIK_SERVICES_TLS_CONFIG}" != "tls.certresolver=letsencrypt" ]; then
echo "WARNING: Neither Let's Encrypt nor local certificates are enabled."
echo "HTTPS will not work properly without certificate configuration."
fi
# Add any custom arguments from environment variable
if [ -n "${TRAEFIK_CUSTOM_ARGS}" ]; then
echo "Adding custom Traefik arguments: ${TRAEFIK_CUSTOM_ARGS}"
TRAEFIK_CMD="$TRAEFIK_CMD $TRAEFIK_CUSTOM_ARGS"
fi
# Add any additional arguments passed to the script
for arg in "$@"; do
add_arg "$arg"
done
# Print the final command for debugging
echo "Starting Traefik with command:"
echo "$TRAEFIK_CMD"
# Execute Traefik
exec $TRAEFIK_CMD

View File

View File

@@ -11,7 +11,7 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.collaboration.entrypoints=https"
- "traefik.http.routers.collaboration.rule=Host(`${WOPISERVER_DOMAIN:-wopiserver.opencloud.test}`)"
- "traefik.http.routers.collaboration.tls.certresolver=letsencrypt"
- "traefik.http.routers.collaboration.${TRAEFIK_SERVICES_TLS_CONFIG}"
- "traefik.http.routers.collaboration.service=collaboration"
- "traefik.http.services.collaboration.loadbalancer.server.port=9300"
collabora:
@@ -19,6 +19,6 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.collabora.entrypoints=https"
- "traefik.http.routers.collabora.rule=Host(`${COLLABORA_DOMAIN:-collabora.opencloud.test}`)"
- "traefik.http.routers.collabora.tls.certresolver=letsencrypt"
- "traefik.http.routers.collabora.${TRAEFIK_SERVICES_TLS_CONFIG}"
- "traefik.http.routers.collabora.service=collabora"
- "traefik.http.services.collabora.loadbalancer.server.port=9980"

View File

@@ -10,6 +10,6 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.keycloak.entrypoints=https"
- "traefik.http.routers.keycloak.rule=Host(`${KEYCLOAK_DOMAIN:-keycloak.opencloud.test}`)"
- "traefik.http.routers.keycloak.tls.certresolver=letsencrypt"
- "traefik.http.routers.keycloak.${TRAEFIK_SERVICES_TLS_CONFIG}"
- "traefik.http.routers.keycloak.service=keycloak"
- "traefik.http.services.keycloak.loadbalancer.server.port=8080"

View File

@@ -5,9 +5,9 @@ services:
- "traefik.enable=true"
- "traefik.http.routers.opencloud.entrypoints=https"
- "traefik.http.routers.opencloud.rule=Host(`${OC_DOMAIN:-cloud.opencloud.test}`)"
- "traefik.http.routers.opencloud.tls.certresolver=letsencrypt"
- "traefik.http.routers.opencloud.service=opencloud"
- "traefik.http.services.opencloud.loadbalancer.server.port=9200"
- "traefik.http.routers.opencloud.${TRAEFIK_SERVICES_TLS_CONFIG}"
traefik:
image: traefik:v3.3.1
# release notes: https://github.com/traefik/traefik/releases
@@ -15,38 +15,19 @@ services:
opencloud-net:
aliases:
- ${OC_DOMAIN:-cloud.opencloud.test}
command:
- "--log.level=${TRAEFIK_LOG_LEVEL:-ERROR}"
# letsencrypt configuration
- "--certificatesResolvers.letsencrypt.acme.email=${TRAEFIK_ACME_MAIL:-example@example.org}"
- "--certificatesResolvers.letsencrypt.acme.storage=/certs/acme.json"
- "--certificatesResolvers.letsencrypt.acme.httpChallenge.entryPoint=http"
- "--certificatesResolvers.letsencrypt.acme.caserver=${TRAEFIK_ACME_CASERVER:-https://acme-v02.api.letsencrypt.org/directory}"
# enable dashboard
- "--api.dashboard=true"
# define entrypoints
- "--entryPoints.http.address=:80"
- "--entryPoints.http.http.redirections.entryPoint.to=https"
- "--entryPoints.http.http.redirections.entryPoint.scheme=https"
- "--entryPoints.https.address=:443"
# change default timeouts for long-running requests
# this is needed for webdav clients that do not support the TUS protocol
- "--entryPoints.https.transport.respondingTimeouts.readTimeout=12h"
- "--entryPoints.https.transport.respondingTimeouts.writeTimeout=12h"
- "--entryPoints.https.transport.respondingTimeouts.idleTimeout=3m"
# docker provider (get configuration from container labels)
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedByDefault=false"
# access log
- "--accessLog=true"
- "--accessLog.format=json"
- "--accessLog.fields.headers.names.X-Request-Id=keep"
entrypoint: [ "/bin/sh", "/opt/traefik/bin/docker-entrypoint-override.sh"]
environment:
- "TRAEFIK_SERVICES_TLS_CONFIG=${TRAEFIK_SERVICES_TLS_CONFIG:-tls.certresolver=letsencrypt}"
- "TRAEFIK_ACME_EMAIL=${TRAEFIK_ACME_MAIL:-example@example.org}"
- "TRAEFIK_ACME_CASERVER=${TRAEFIK_ACME_CASERVER:-https://acme-v02.api.letsencrypt.org/directory}"
ports:
- "80:80"
- "443:443"
volumes:
- "${DOCKER_SOCKET_PATH:-/var/run/docker.sock}:/var/run/docker.sock:ro"
- "certs:/certs"
- "./config/traefik/docker-entrypoint-override.sh:/opt/traefik/bin/docker-entrypoint-override.sh"
- "${TRAEFIK_CERTS_DIR:-./certs}:/certs"
- "./config/traefik/dynamic:/etc/traefik/dynamic"
labels:
- "traefik.enable=${TRAEFIK_DASHBOARD:-false}"
# defaults to admin:admin
@@ -54,11 +35,8 @@ services:
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DOMAIN:-traefik.opencloud.test}`)"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.routers.traefik.tls.certresolver=letsencrypt"
- "traefik.http.routers.traefik.${TRAEFIK_SERVICES_TLS_CONFIG}"
- "traefik.http.routers.traefik.service=api@internal"
logging:
driver: ${LOG_DRIVER:-local}
restart: always
volumes:
certs: