schedule Published: September 20, 2025
update Last updated: December 14, 2025

Internal HTTPS setup for onlyoffice using self-signed certificates with traefik.

Overview

In this guide we will setup OnlyOffice with internal HTTPS using generated self-signed certificates with Traefik.

OnlyOffice configuration

Step 01: Generate OnlyOffice self-signed certificates

First navigate to your OnlyOffice directory (where you have the docker-compose.yaml), once there create the directory for the certificates:

BASH
1
mkdir -p certs && cd certs

After that, generate the certificates with this command:

SHELL
1
2
3
4
openssl req -x509 -nodes -days 20000 -subj "/CN=onlyoffice" \
  -newkey rsa:2048 \
  -keyout onlyoffice.key \
  -out onlyoffice.crt

Command explanation

FlagPurpose
-x509Create self-signed certificate (not a request)
-nodesNo password required
-days 20000Valid for ~50 years (only for internal use)
-subj "/CN=onlyoffice"Set Common Name without prompts
-newkey rsa:2048Generate RSA 2048-bit key pair

Step 02: Update OnlyOffice with the new created certificates

You will need to mount the self-signed certificates to OnlyOffice in your docker-compose.yaml.

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
services:
  onlyoffice:
    container_name: onlyoffice
    image: onlyoffice/documentserver
    environment:
      TZ: $TZ
      JWT_SECRET: $ONLYOFFICE_SECRET
      ONLYOFFICE_HTTPS_HSTS_ENABLED: false
      # Add this two env vars
      SSL_CERTIFICATE_PATH: /var/www/onlyoffice/Data/certs/onlyoffice.crt
      SSL_KEY_PATH: /var/www/onlyoffice/Data/certs/onlyoffice.key
    # And this volume mount
    volumes:
      - ./certs:/var/www/onlyoffice/Data/certs  # Mount certificates
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.tls=true"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.entrypoints=websecure"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.tls.certresolver=letsencrypt"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.tls.options=default"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.rule=Host(${DOMAIN_NAME})"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.service=${TRAEFIK_SERVICE_NAME}"
      - "traefik.http.services.${TRAEFIK_SERVICE_NAME}.loadbalancer.server.url=${OFFICE_INTERNAL}" # change port with url, and set the container name with https
      - "traefik.http.services.${TRAEFIK_SERVICE_NAME}.loadbalancer.passhostheader=true"
      - "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.middlewares=no-frame-block@file"

      # Headers for onlyoffice, see https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/151 for details
      - "traefik.http.middlewares.${TRAEFIK_SERVICE_NAME}-headers.headers.accesscontrolalloworiginlist=*"
    networks:
      proxy_network:
    restart: unless-stopped

networks:
  proxy_network:
    external: true

Then, modify the .env (environment) file of onlyoffice:

ENV
1
2
3
4
5
6
7
8
9
DOMAIN_NAME=your-domain.com         # Your root domain here.
DYNU_API_KEY=your-dynu-api-key-here # DDNS API Key (we are using dynu - check the traefik documentation about other providers)

# Traefik Dashboard Credentials
# Generate with: docker run --rm httpd:alpine htpasswd -nb your-username your-password | sed -e 's/\$/\$\$/g'
TRAEFIK_DASHBOARD_CREDENTIALS=admin:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/

# Add this
OFFICE_INTERNAL=https://onlyoffice

Alternative: Traefik file provider

Instead of use traefik labels as above, we can also deploy onlyoffice using File Provider. This is similar to when we created the middlewares.yaml file. You should have a dynamic directory that traefik reads, so, in that same directory where the middlewares.yaml is, create a file called onlyoffice.yaml or how you prefer.

  • traefik/config/dynamic/onlyoffice.yaml:
YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
http:
  routers:
    onlyoffice:
      entrypoints:
        - websecure
      rule: Host(`onlyoffice.yourdomain.com`)
      tls:
        certResolver: letsencrypt
      service: onlyoffice
      middlewares:
        - onlyoffice-headers
        - no-frame-block

  services:
    onlyoffice:
      loadBalancer:
        servers:
          - url: "https://onlyoffice"  # Note: HTTPS, not HTTP
        serversTransport: onlyoffice  # Reference to transport below

  middlewares:
    onlyoffice-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
        accessControlAllowOriginList:
          - "*"

  serversTransports:
    onlyoffice:
      insecureSkipVerify: true  # This skips certificate verification

Step 03: Configure Traefik

Traefik needs to be told to skip certificate verification, so if you followed the previous guide, we are validating the verification of the certificates in our traefik.yaml static config file by setting it to false, we need to set it to true:

YAML
1
2
3
4
5
6
serversTransport:
  insecureSkipVerify: true  # Set this to true to skip the verification
  forwardingTimeouts:
    dialTimeout: "60s"
    responseHeaderTimeout: "60s"
    idleConnTimeout: "90s"

Step 04: Update FileBrowser Configuration

YAML
1
2
3
4
5
integrations:
  office:
    url: "https://onlyoffice.yourdomain.com"  # External HTTPS URL
    internalUrl: "https://onlyoffice" # Internal HTTPS URL, the one that we defined in the .env file which should be the container name.
    secret: "your-jwt-secret"

Step 05: Re-deploy the services

Navigate to the directory of each service and then run the next command in each one:

BASH
1
docker compose up -d --force-recreate

Verify Configuration

BASH
1
2
3
4
5
# Check OnlyOffice is using HTTPS (You should see that is listening to 0.0.0.0:443 and is using SSL)
docker exec onlyoffice cat /etc/onlyoffice/documentserver/nginx/ds.conf | grep ssl

# Test from Traefik perspective (Should perform the helthcheck successfully)
docker exec traefik wget --no-check-certificate https://onlyoffice/healthcheck

Self-Signed Certificates with Full Verification

First of all, make SURE that you have insecureSkipVerify set to false.

  • traefik.yaml
YAML
1
2
3
4
5
6
serversTransport:
  insecureSkipVerify: false  # Set this to false to NOT skip the verification
  forwardingTimeouts:
    dialTimeout: "60s"
    responseHeaderTimeout: "60s"
    idleConnTimeout: "90s"

Step 01: Create Certificate Configuration

You will need to create a config file for the onlyoffice certificates.

Create onlyoffice/certs/cert.conf:

INI
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
x509_extensions = v3_req

[dn]
CN = onlyoffice

[v3_req]
subjectAltName = @alt_names

[alt_names]
IP.1 = 192.168.2.125  # Static IP for OnlyOffice container
DNS.1 = onlyoffice   # Docker service name

Step 02: Generate Certificates with config

BASH
1
2
3
4
5
cd certs
openssl req -x509 -nodes -days 20000 \
  -keyout onlyoffice.key \
  -out onlyoffice.crt \
  -config cert.conf

Step 3: Assign Static IP to OnlyOffice

Update onlyoffice/docker-compose.yaml:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
services:
  onlyoffice:
    image: onlyoffice/documentserver
    container_name: onlyoffice
    environment:
      - JWT_ENABLED=true
      - JWT_SECRET=your-secret
      - ONLYOFFICE_HTTPS_HSTS_ENABLED=false
    volumes:
      - ./certs:/var/www/onlyoffice/Data/certs
    networks:
      proxy_network:
        ipv4_address: 192.168.2.125  # Must match cert.conf

Step 4: Mount Certificate in Traefik

Traefik needs access to the certificate to verify it:

YAML
1
2
3
4
5
6
7
traefik:
  image: traefik:latest
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - ./config/static/traefik.yaml:/etc/traefik/traefik.yaml:ro
    - ./config/dynamic:/dynamic:ro
    - /path/to/certs/onlyoffice.crt:/certs/onlyoffice.crt:ro  # Add this

Step 5: Update Traefik Dynamic Config

Create dynamic/onlyoffice.yml:

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
http:
  routers:
    onlyoffice:
      entrypoints:
        - websecure
      rule: Host(`onlyoffice.yourdomain.com`)
      tls:
        certResolver: letsencrypt
      service: onlyoffice
      middlewares:
        - onlyoffice-headers
        - no-frame-block

  services:
    onlyoffice:
      loadBalancer:
        servers:
          - url: "https://onlyoffice"
        serversTransport: onlyoffice

  middlewares:
    onlyoffice-headers:
      headers:
        customRequestHeaders:
          X-Forwarded-Proto: "https"
        accessControlAllowOriginList:
          - "*"

  serversTransports:
    onlyoffice:
      insecureSkipVerify: false  # Change it to false
      rootCAs:
        - /certs/onlyoffice.crt  # Path inside Traefik container

Step 6: Restart containers

BASH
1
2
3
4
5
6
7
8
# Restart all services
docker compose restart traefik 
docker compose restart onlyoffice
docker compose restart filebrowser

# Check Traefik can verify certificate
docker exec traefik wget https://onlyoffice/healthcheck
# Should succeed without certificate errors

Check Certificate Details

If you want to check the details of your certificates you can use this commands:

SHELL
1
2
3
4
5
6
7
8
# Check certificate subject and SAN (Subject Alternative Name)
openssl x509 -in certs/onlyoffice.crt -noout -text | grep -A1 "Subject:"
openssl x509 -in certs/onlyoffice.crt -noout -text | grep -A2 "Subject Alternative"

# Should show something like this:
# Subject: CN = onlyoffice
# Subject Alternative Name:
#   DNS:onlyoffice, IP Address: <configured ip address>

Troubleshooting

First of all try to check logs of the apps, there you should find some essential info about why you are having the errors/issues.

BASH
1
docker logs traefik -f
SHELL
1
docker logs onlyoffice -f

Certificate Errors

If you used the full verification method, you could have some errors with the certificates.

Some common errors could be:

  • x509: certificate signed by unknown authority: Maybe you forget to specify the rootCAs in transport when configuting file provider for onlyoffice.
  • x509: certificate is valid for X, not Y: Maybe you set the wrong IP adress or DNS, either in the certificate configuration or in the container, and now is mismatching. Make sure that they are the same in both.
  • tls: bad certificate: You mounted a wrong path for the certificate in onlyoffice, or traefik.

OnlyOffice not Starting with HTTPS

BASH
1
2
3
4
5
6
7
8
9
# Check OnlyOffice nginx config
docker exec onlyoffice cat /etc/onlyoffice/documentserver/nginx/ds.conf

# Check certificate files
docker exec onlyoffice ls -la /var/www/onlyoffice/Data/certs/

# Should show:
# -rw-r--r-- onlyoffice.crt
# -rw-r--r-- onlyoffice.key

Mixed Content Errors

Ensure all URLs use https:// in FileBrowser config:

YAML
1
2
3
4
5
6
7
8
server:
  externalUrl: "https://files.yourdomain.com"
  internalUrl: "https://files.yourdomain.com"

integrations:
  office:
    url: "https://onlyoffice.yourdomain.com"
    internalUrl: "https://onlyoffice:80"

FBQ not trusting OnlyOffice certs

If for some reason the filebrowser container doesn’t trust the certificates (even configured via traefik), you’ll need to mount and update the certificates of the filebrowser container in startup.

YAML
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
services:
  filebrowser:
    container_name: filebrowser
    image: gtstef/filebrowser:latest
    env_file: .env
    environment:
    # ... Existent enviroment variables
    volumes:
      - './data:/home/filebrowser/data'
      # ... Other volumes
      - /path/to/certs/onlyoffice.crt:/usr/local/share/ca-certificates/onlyoffice.crt:ro # Mount the OO certs
    labels:
    # ... Existent labels
    networks:
      proxy_network:
    restart: unless-stopped

    # trust certs and launch filebrowser
    entrypoint: sh -c "update-ca-certificates && ./filebrowser"

networks:
  proxy_network:
    external: true

Other issues

If you have other issues related with onlyoffice and filebrowser, check the Office Troubleshooting guide, which covers some of the most commons issues with solutions.

Next Steps