HTTPS + OnlyOffice + (Traefik or Wiredoor) - example configuration. #1237
Replies: 3 comments 10 replies
-
|
Can't wait to have docs in git that everyone can contribute to -- this kind of thing would be perfect. Thanks for the post @BaccanoMob ! |
Beta Was this translation helpful? Give feedback.
-
|
Related to my last comment on #1192, If is for help I'll post here my traefik config, and docker-compose of both services (onlyoffice and traefik), wait a bit. (Will take a while) |
Beta Was this translation helpful? Give feedback.
-
|
Edit: Filebrowser and onlyoffice behind traefik with labels
You can use this configs, replicating the exact same file structure (if you want) and replacing the fake/changed info with your own. And of course you can modify all at your convenience. For some context: I use traefik with labels on all the services that I want to deploy with the certbot that renew my certificates for my domains automatically every 80~ days aprox (this is the default of traefik, so I don't need to do something special). The tricky part is with the DDNS and your domain, you must have a valid domain name linked with a DDNS of you choice that traefik support (I use dynu for this). And also, you don't need a self-signed certificate, let's encrypt will do this automatically with the certbot. First I created a new docker network with:
docker network create \
--driver=bridge \
--subnet=172.18.0.0/24 \ # You can change it to whatever subnet you want, this is just an example
--gateway=172.18.0.1 \ # Same here
--ip-range=172.18.0.128/25 \ # Dynamic IPs
--label=Reserved_IPs="172.18.0.2-127" \ # Reserved IPs for other services that need a static IP
proxy_network # Name of the docker networkOverall directory structure (example):docker_apps
├── filebrowser
├── onlyoffice
└── traefik
10 directories, 13 filesTraefik
traefik
├── certs
│ ├── acme.json # Certificates. Need `chmod 600 acme.json` permissions
│ └── acme.json.bak # Backup of the certificates, just in case
├── config
│ ├── dynamic
│ │ └── services.yaml # This file is empty, but I have it just in case.
│ └── static
│ └── traefik.yaml # My static traefik config
├── docker-compose.yaml # The docker compose file of traefik
└── .env # Environmet variables for the docker compose file
5 directories, 6 files
My traefik compose file (docker-compose.yaml)# Docker compose of traefik
services:
traefik:
image: traefik:latest
container_name: traefik
security_opt:
- no-new-privileges: true
ports:
- "80:80"
- "443:443"
# - "8080:8080" # I disabled this because is behind traefik itself.
environment:
- DYNU_API_KEY=${DYNU_API_KEY} # On .env file, I use dynu as my DDNS provider, you can check for more on the offical traefik page.
- TRAEFIK_DASHBOARD_CREDENTIALS=${TRAEFIK_DASHBOARD_CREDENTIALS}
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock
- ./config/static/traefik.yaml:/etc/traefik/traefik.yaml:ro
- ./certs/acme.json:/var/traefik/certs/acme.json:rw
- ./config/dynamic:/etc/traefik/config
networks:
- proxy_network # Here you'll need to use your actual docker network or create one with the command above
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls.certresolver=crypt"
- "traefik.http.routers.traefik.rule=Host(`traefik.my-domain.com`)"
- "traefik.http.routers.traefik.tls.domains[0].main=my-domain.com"
- "traefik.http.routers.traefik.tls.domains[0].sans=*.my-domain.com"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.services.traefik.loadbalancer.passhostheader=true"
- "traefik.http.services.traefik.loadbalancer.server.port=8080"
- "traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https"
# Basic auth on dashboard
- "traefik.http.routers.traefik.middlewares=traefik-auth"
- "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}"
# For generate the hashed password, you can use: docker run --rm httpd:alpine htpasswd -nb admin your-password | sed -e 's/\$/\$\$/g'
# Then, the alpine container will delete itself when stopped
restart: unless-stopped
networks:
proxy_network: # same name as the network created
external: trueMy traefik environment file (.env)DYNU_API_KEY=PMSDOIDNFOP9234J023NRFP # My DDNS API
TRAEFIK_DASHBOARD_CREDENTIALS=Bob:$$a$$sofsdOSDFISDFfsdfsO
# username and hashed password with command:
# docker run --rm httpd:alpine htpasswd -nb Bob your-password | sed -e 's/\$/\$\$/g'My traefik config (traefik.yaml)# traefik.yaml
global:
checkNewVersion: true
sendAnonymousUsage: false
log:
level: INFO # DEBUG, INFO, WARN, ERROR, FATAL, PANIC
#accessLog:
# fields:
# defaultMode: keep
# names:
# ClientUsername: drop
# headers:
# defaultMode: keep
# names:
# User-Agent: keep
# Authorization: drop
# Content-Type: keep
api:
dashboard: true
insecure: true
entryPoints:
web:
address: :80
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
http2:
maxConcurrentStreams: 500
websecure:
address: :443
http:
tls:
certResolver: crypt
transport:
respondingTimeouts:
readTimeout: "0"
writeTimeout: "0"
idleTimeout: "300s"
lifeCycle:
graceTimeOut: "20s"
keepAliveMaxTime: "0"
keepAliveMaxRequests: "0"
http2:
maxConcurrentStreams: 500
asDefault: true
serversTransport:
insecureSkipVerify: true
forwardingTimeouts:
dialTimeout: "60s" # Time to establish TCP connection
responseHeaderTimeout: "75s" # Time for backend to send headers
idleConnTimeout: "90s"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
network: "proxy_network"
exposedByDefault: false
file:
directory: "/etc/traefik/config/dynamic"
watch: true
http:
serversTransports:
default:
insecureSkipVerify: true
forwardingTimeouts:
dialTimeout: "30s"
responseHeaderTimeout: "60s"
idleConnTimeout: "90s"
readIdleTimeout: "3600s"
timeouts:
readTimeout: "3600s"
writeTimeout: "3600s"
idleTimeout: "3600s"
middlewares:
# Global security headers (applies to all routes)
security-headers:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 15552000
customFrameOptionsValue: "SAMEORIGIN"
customRequestHeaders:
X-Forwarded-Proto: "https"
routers:
http:
middlewares:
- "security-headers"
certificatesResolvers:
crypt:
acme:
email: [email protected]
storage: /var/traefik/certs/acme.json
caServer: https://acme-v02.api.letsencrypt.org/directory # production
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory # Use this first and test, then change to production.
dnsChallenge:
provider: dynu
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
#disablePropagationCheck: true # uncomment this if you have issues pulling certificates, By setting this to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
#delayBeforeCheck: "60s" # uncomment along with disablePropagationCheck if needed to ensure the TXT record is ready before verification is attemptedFilebrowser Quantum:
filebrowser
├── data
│ ├── config.yaml # configuration file of filebrowser
│ ├── config.yaml.bak # backup, just in case
│ └── database.db # database
├── docker-compose.yml # docker compose file
└── .env # env file for the compose file
2 directories, 5 filesFilebrowser compose file (docker-compose.yaml):# docker-compose.yaml of Filebrowser
services:
filebrowser:
container_name: filebrowser
image: gtstef/filebrowser
env_file: .env
environment:
FILEBROWSER_CONFIG: "data/config.yaml"
FILEBROWSER_ADMIN_PASSWORD: $FILEBROWSER_ADMIN_PASSWORD
TZ: $TZ
volumes:
- '/files:/files'
- '/files/Shared:/shared'
- '/files/syncthing:/syncthing'
- './data:/home/filebrowser/data'
# - './tmp/:/home/filebrowser/tmp/' # Only if using another user besides "filebrowser"
# ports: # Using traefik for handle this
# - '8082:80'
user: filebrowser # non-root filebrowser user
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=crypt"
- "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.port=${TRAEFIK_SERVICE_PORT}"
- "traefik.http.services.${TRAEFIK_SERVICE_NAME}.loadbalancer.passhostheader=true"
networks:
proxy_network:
restart: unless-stopped
networks:
proxy_network:
external: trueFilebrowser environment file (.env)FILEBROWSER_ADMIN_PASSWORD=MY-FILEBROWSER-PASSWORD
DOMAIN_NAME=`my-filebrowser-domain.com`
TRAEFIK_SERVICE_NAME=filebrowser
TRAEFIK_SERVICE_PORT=80
TZ=YOUR/TIMEZONEConfiguration file of filebrowser (config.yaml)# Filebrowser configuration (config.yaml)
server:
minSearchLength: 3
numImageProcessors: 2
disableUpdateCheck: false
disablePreviews: false
disablePreviewResize: false
disableTypeDetectionByHeader: false
port: 80
baseURL: "/"
logging:
- levels: "debug|info|warning|error"
apiLevels: "debug|info|warning|error"
output: "stdout"
noColors: false
json: false
utc: false
debugMedia: false
database: "/home/filebrowser/data/database.db"
sources:
- path: "/files"
name: "Data"
config:
defaultEnabled: true
denyByDefault: false
createUserDir: true
- path: "/shared"
name: "Shared"
config:
defaultEnabled: false
denyByDefault: false
createUserDir: false
- path: "/syncthing"
name: "Syncthing"
config:
defaultEnabled: false
denyByDefault: false
createUserDir: false
externalUrl: "https://my-filebrowser-domain.com" # The internal and external URLs
internalUrl: "http://filebrowser:80" # The name of my docker container is "filebrowser"
cacheDir: "tmp"
auth:
tokenExpirationHours: 6
adminUsername: admin-user
methods:
noauth: false
password:
enabled: true
minLength: 8
signup: false
frontend:
name: "FileBrowser Quantum"
disableDefaultLinks: true
disableUsedPercentage: false
externalLinks:
- text: "Homepage"
title: "Go to the Homepage"
url: "https://my-homepage-domain.com"
disableNavButtons: false
styling:
customCSS: ""
darkBackground: "black"
customThemes: .
default:
description: Default theme
css: ""
favicon: ""
description: "FileBrowser Quantum is a web-based filemanager, is really useful, try it out!"
userDefaults:
editorQuickSave: true
hideSidebarFileActions: false
disableQuickToggles: false
stickySidebar: true
darkMode: true
locale: "es"
viewMode: "normal"
singleClick: false
dateFormat: true
gallerySize: 4
themeColor: "var(--red)"
quickDownload: false
disablePreviewExt: ".txt .csv .html .conf"
disableViewingExt: ""
lockPassword: true
disableSettings: false
preview:
disableHideSidebar: false
highQuality: false
image: true
video: true
motionVideoPreview: true
office: true
popup: true
autoplayMedia: true
defaultMediaPlayer: false
folder: false
permissions:
api: false
admin: false
modify: true
share: true
realtime: false
loginMethod: "password"
disableUpdateNotifications: false
deleteWithoutConfirming: false
fileLoading:
maxConcurrentUpload: 5
uploadChunkSizeMb: 100
disableOnlyOfficeExt: ".txt .html .md"
showSelectMultiple: true
debugOffice: true
integrations: # Office config
office:
url: "https://my-onlyoffice-domain.com"
internalUrl: "https://my-filebrowser-domain.com"
secret: "MY-ONLYOFFICE-SECRET"
viewOnly: false
media:
ffmpegPath: "ffmpeg"
convert:
imagePreview:
heic: trueOnlyofficeI have onlyoffice on a separate docker-compose file (and directory), but you can use it on only one within filebrowser. onlyoffice
├── docker-compose.yaml
└── .env
2 filesOnlyoffice compose file:# docker-compose.yaml
services:
onlyoffice:
container_name: onlyoffice
image: onlyoffice/documentserver
env_file: .env
environment:
TZ: $TZ
ONLYOFFICE_HTTPS_HSTS_ENABLED: false
JWT_ENABLED: true
JWT_SECRET: $ONLYOFFICE_SECRET
JWT_HEADER: Authorization
#ports:
# - '8081:80'
stdin_open: true
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=crypt"
- "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.port=${TRAEFIK_SERVICE_PORT}"
- "traefik.http.services.${TRAEFIK_SERVICE_NAME}.loadbalancer.passhostheader=true"
## Middleware definition
# Headers for onlyoffice, see https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues/151 for details
- "traefik.http.routers.${TRAEFIK_SERVICE_NAME}.middlewares=${TRAEFIK_SERVICE_NAME}-headers"
- "traefik.http.middlewares.${TRAEFIK_SERVICE_NAME}-headers.headers.customrequestheaders.X-Forwarded-Proto=https"
- "traefik.http.middlewares.${TRAEFIK_SERVICE_NAME}-headers.headers.accesscontrolalloworiginlist=*"
networks:
proxy_network:
restart: unless-stopped
networks:
proxy_network:
external: trueOnlyoffice environment file (.env):TRAEFIK_SERVICE_NAME=onlyoffice
TRAEFIK_SERVICE_PORT=80
DOMAIN_NAME=`onlyoffice.your-domain.com`
ONLYOFFICE_SECRET=KDSpcNwKAos2moijgdfi9jf9wr3wek=
TZ=YOUR/TIMEZONE |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Traefik
Onlyoffice does not work with HTTPS out of the box. It will throw either
mixed contentor related errors, well bottom line it does not work when you have Onlyoffice running with HTTP but access via HTTPS from reverse proxy.To fix it, you will need to start Onlyoffice in HTTPS. To do that you will need create self signed certs for onlyoffice and bind it to the container. Technically, you can use certbots or other means to get proper certs as well but self signed was more easy.There are a few ways to do this. (Lower the method number easier it is)
Method 0: With labels
Follow this reply
#1237 (comment)
Method 1: With skipping cert verification
Below methods follows Onlyoffice official docs with some modifications to make things easier.
Adding Certs
You have to bind
./certs:/var/www/onlyoffice/Data/certsfor Onlyoffice. If you make a folder else where bind it accordingly.Openssl command breakdown (click to view)
req -x509: SSL/TLS specnodes: no passphrase for cert-days 20000: expiry in days (20000 days ~= 50 years). It is actually bad practice to set it more than 13 months but since traefik only sees this cert to verify, it does not matter. Traefik will use its lets encrypt certificate when you access it from the browser.-subj "/CN=onlyoffice": If you do not set this, you will prompt a series of questions with 99% of them having default value as empty text. 1% that need a text isCNand actually stands for common name though its value does not matter since we are not gonna use this cert out in the public.newkey rsa:2048: to create key val pair with rsa 2048 specsonlyofficeAFAIK.If you are using certbot or similar means you will have to do renewals.
Now if you try to start it, I think you will get
too many redirectsorinternal server errorerrors but onlyoffice will start to use https instead of http.Fixing errors
You need to configure
serverstransportto fix it but unfortunately this is only possible via dynamic configuration aka can not configure via labels. While it is possible just configureserverstransportin file provider alone and the rest in labels, I recommend using whole config in file so you have all traefik config in one place for Onlyoffice.New to dynamic configuration or file provider? (click to view)
You will need to add file provider in your
traefik.ymlAdd a new volume bind for traefik to store file configurations and bind it to
/dynamic. I use./dynamic:/dynamic:ro. Note directory name can be anything, if you want to change it be sure to update else where accordingly.Add file configuration
onlyoffice.ymlin the file provider directoryNow, you will have Onlyoffice in HTTPS working without errors.
Method 2: Without skipping cert verification
If, for some reason, you do not like
insecureSkipVerify: trueand want to set to false (default value), then you only need a way to verify the certs. First we create the cert configuration filecert.confin the certs folder (delete above certs if you created any).cert.conf
Some of the Method 1 flags/args are used in conf file instead of commandline now. And the verification method is using altnames which are container's IP address and container name. The container's IP address can be any private IP, though its preferred to be in the same subnet as the rest of the containers. It is important that the you have
255or any higher number than 100 will do, docker always auto allocates with lower number. If you try to skip IP.1, you will getIP SANSerrors in traefik log when verifying.Now, run command to create certs with the above config,
Since we specified
IP.1 = 172.18.0.255andDNS.1 = onlyoffice, we need to update your compose file accordingly.Now we have to bind
certs/onlyoffice.crtto traefik volume. For example,/path/to/certs/onlyoffice.crt:/certs/onlyoffice.crt:roso cert is available at/certs/onlyoffice.crtvia traefik container. Alternatively, you can bind the certs folder like/path/to/certs:/certs:ro. But make sure you are properly binding and referencing the correct files/volumes.Lastly we update the file configuration for only office,
Just in case restart your containers, and you will have Onlyoffice working in HTTPS now.
Method 3: Certbots and similar
I have not tried and will not do so. If you have a working configuration for it comment/reply to this discussion and Ill link it to this post.
Method 4: Extract certs from Traefik
I have not tried this as well. I will try it at some point. Though you must keep in mind Lets encrypt certs have a validity of 90 days I think, so you may have to re-extract the certs again and again when it s not valid (possibly). Will update this if I ever try it.
According to #1192, you will need to set
externalUrlandinternalUrl(internal url can be set to the same value as external url) in server configuration for onlyoffice to work (for 0.8.4+ supposedly). I verified this myself that setting those 2 fixes the issue in 0.8.6-beta (latest at the time of writing) but not sure what was the cause since I was not using Onlyoffice for a while.If you have a working configuration for other reverse proxy like NPM, Caddy, nginx, cloudflare tunnel, etc comment/reply to this discussion and Ill link it to this post and update the title accordingly. (Also lmk if I made any mistakes as well)
Wiredoor
Check this discussion for basic setup Wiredoor.
You will need to patch the
security.confdocker compose exec -u root wiredoor bash apk add nano nano /etc/nginx/partials/security.confYou should comment out (add
#at the beginning of the line)add_header X-Frame-Options "DENY" always;line (mentioned in discussion's answer)add_header X-Frame-Options "SAMEORIGIN" always;line (mentioned later in a reply)Beta Was this translation helpful? Give feedback.
All reactions