ONLYOFFICE Docs (the Document Server) is a free, open-source online office suite: Word documents, spreadsheets, presentations and PDFs, edited in the browser with real-time co-editing and excellent Microsoft Office compatibility. On its own it is an editing engine; you plug it into something that stores files, such as Nextcloud, and suddenly every .docx in your cloud opens in a full editor.
In this guide we will run the Community Edition of the Document Server in Docker using the official image, secure it with a JWT secret, and connect it to Nextcloud with the official ONLYOFFICE connector app.
onlyoffice/documentserver. The Community Edition is free and supports up to 20 simultaneous connections.✅ Before you start
- A Linux host with Docker and Docker Compose v2 installed (
docker compose versionshould work). Usedocker composewith a space: the old Pythondocker-composev1 can crash on modern Docker. - At least 2 CPU cores and 4 GB of RAM (plus swap). The Document Server bundles its own PostgreSQL, RabbitMQ and Redis, so it is not small.
- A Nextcloud server (see my Nextcloud guide), reachable over HTTPS.
- A hostname for ONLYOFFICE, such as
office.example.com, on your reverse proxy. Browsers load the editors from it directly, so it has to be reachable by your users and by Nextcloud.
STEP 1: User and group IDs (and your secrets)
The Document Server image does not use PUID/PGID; it runs its own services inside the container and manages their folders.
What you do need is a JWT secret. It stops anyone else from using your Document Server, and Nextcloud must know the same secret. Make it long and random:
openssl rand -hex 32Keep them somewhere safe, such as your password manager. In the examples below they appear as placeholders like CHANGE_ME_STRONG_PASSWORD and change-me.
JWT_SECRET, the image generates a random one on every fresh container, and your Nextcloud connection breaks each time the container is recreated. Always set your own.STEP 2: Create the folders
I keep every app's files under one parent folder so a backup is a single job. Create the folders for ONLYOFFICE:
mkdir -p /path/to/appdata/onlyoffice/{logs,data,lib,db,rabbitmq,redis}If Nextcloud runs on the same host, put both on this proxy network and they can reach each other by container name.
When you are done, the layout should look like this:
/path/to/appdata/onlyoffice/
docker-compose.yml
logs/ # /var/log/onlyoffice
data/ # /var/www/onlyoffice/Data (certificates)
lib/ # /var/lib/onlyoffice (cache, document files)
db/ # bundled PostgreSQL
rabbitmq/ # bundled RabbitMQ
redis/ # bundled RedisFolder layout
Finally, I give every web app that sits behind my reverse proxy one shared Docker network called proxy. ONLYOFFICE joins it so Traefik or Nginx Proxy Manager can reach it by container name, while its database and helpers stay on the stack's own private network. Create it once (if it already exists, Docker just tells you so):
docker network create proxySTEP 3: The compose file
Create /path/to/appdata/onlyoffice/docker-compose.yml and paste in the following. It is based on the official compose file and README, with the JWT settings filled in, persistent folders for every bundled service and the shared proxy network added. Use the copy button in the top right corner of the block.
services:
onlyoffice:
image: onlyoffice/documentserver:latest
container_name: onlyoffice
restart: always
stop_grace_period: 60s
environment:
JWT_ENABLED: "true"
JWT_SECRET: change-me # the secret from STEP 1
JWT_HEADER: Authorization
ALLOW_PRIVATE_IP_ADDRESS: "true" # needed if Nextcloud is on a private IP/LAN
ports:
- "8082:80"
volumes:
- /path/to/appdata/onlyoffice/logs:/var/log/onlyoffice
- /path/to/appdata/onlyoffice/data:/var/www/onlyoffice/Data
- /path/to/appdata/onlyoffice/lib:/var/lib/onlyoffice
- /path/to/appdata/onlyoffice/db:/var/lib/postgresql
- /path/to/appdata/onlyoffice/rabbitmq:/var/lib/rabbitmq
- /path/to/appdata/onlyoffice/redis:/var/lib/redis
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/info/info.json"]
interval: 30s
retries: 5
start_period: 60s
timeout: 10s
networks:
- proxy
networks:
proxy:
external: truedocker-compose.yml
STEP 4: The settings explained
| Setting | What it does |
|---|---|
JWT_ENABLED |
Requires a signed token on every request. On by default; keep it on. |
JWT_SECRET |
The shared secret. Nextcloud's ONLYOFFICE app must use exactly the same value. |
JWT_HEADER |
The HTTP header the token travels in. Default Authorization. If you change it (the README's Nextcloud example uses AuthorizationJwt), change it in Nextcloud too. |
ALLOW_PRIVATE_IP_ADDRESS |
Lets the Document Server download and save files from servers on private IP addresses. Default false; you need true when Nextcloud is on your LAN or a Docker network. |
8082:80 |
The Document Server listens on 80 inside the container. Your reverse proxy handles HTTPS. |
| Volumes | Logs, certificates, cache and the bundled PostgreSQL, RabbitMQ and Redis data, so nothing is lost when the container is recreated. |
stop_grace_period: 60s |
Gives the bundled services a full minute to shut down cleanly, as in the official file. |
healthcheck |
Polls the internal /info/info.json endpoint so docker ps shows when the server is really ready. |
Add
USE_UNAUTHORIZED_STORAGE: "true" so the Document Server accepts them. Better still, use a real certificate from your reverse proxy.STEP 5: Start ONLYOFFICE
From the folder containing your compose file:
cd /path/to/appdata/onlyoffice
docker compose up -d
docker compose logs -fWait until the logs settle down (press Ctrl+C to stop following them; the container keeps running), then check it is up:
docker ps --filter name=onlyofficeThe first start takes a couple of minutes while the bundled services initialise. When docker ps shows (healthy), open http://192.168.1.20:8082: you should see the Document Server is running welcome page.
STEP 6: First-run setup (connect Nextcloud)
The Document Server has no users or admin page of its own; all the setup happens in Nextcloud. Before you start, put ONLYOFFICE behind your proxy (STEP 7) so it has an HTTPS address: browsers refuse to load an http:// editor inside an https:// Nextcloud.
- In Nextcloud, go to Apps, search for ONLYOFFICE and click Download and enable.
- Open Administration settings → ONLYOFFICE.
- Set ONLYOFFICE Docs address to
https://office.example.com/. This address must work from your users' browsers and from the Nextcloud server. - Set Secret key to the same value as
JWT_SECRET. - If both containers share the
proxynetwork, open Advanced server settings and set ONLYOFFICE Docs address for internal requests from the server tohttp://onlyoffice/and Server address for internal requests from ONLYOFFICE Docs tohttp://nextcloud/. That keeps the server-to-server traffic inside Docker. - Click Save. Nextcloud checks the connection; if it is happy, choose which file types should open in ONLYOFFICE by default.
- Open a
.docxfile in Nextcloud. It should open in the ONLYOFFICE editor.
You can do the same from the command line with occ, then ask the connector to check everything:
cd /path/to/appdata/nextcloud
docker compose exec -u 33 app php occ config:app:set onlyoffice DocumentServerUrl --value="https://office.example.com/"
docker compose exec -u 33 app php occ config:app:set onlyoffice DocumentServerInternalUrl --value="http://onlyoffice/"
docker compose exec -u 33 app php occ config:app:set onlyoffice StorageUrl --value="http://nextcloud/"
docker compose exec -u 33 app php occ config:app:set onlyoffice jwt_secret --value="change-me"
docker compose exec -u 33 app php occ onlyoffice:documentserver --checkhttp://onlyoffice/, it is blocking requests to local servers. Either leave the internal addresses empty (everything then goes via the public hostname), or allow local addresses as described in the connector's README.STEP 7: Put ONLYOFFICE behind a reverse proxy
Use a dedicated hostname such as office.example.com. The editors use WebSockets, and the Document Server needs the X-Forwarded-Proto and X-Forwarded-Host headers to build correct https:// links (Traefik and Nginx Proxy Manager send these by default).
Option A: Traefik (Docker labels)
If Traefik runs on the same Docker host and is attached to the proxy network, add these labels to the onlyoffice service. They assume your HTTPS entry point is called websecure and your certificate resolver is called cloudflare; change them to match your Traefik config.
labels:
- traefik.enable=true
- traefik.http.routers.onlyoffice.rule=Host(`office.example.com`)
- traefik.http.routers.onlyoffice.entrypoints=websecure
- traefik.http.routers.onlyoffice.tls.certresolver=cloudflare
- traefik.http.services.onlyoffice.loadbalancer.server.port=80docker-compose.yml (extra lines)
Option B: Traefik (file provider)
If Traefik runs on a different machine, add a router and service to your dynamic config file instead:
http:
routers:
onlyoffice:
rule: Host(`office.example.com`)
entryPoints:
- websecure
tls:
certResolver: cloudflare
service: onlyoffice
services:
onlyoffice:
loadBalancer:
servers:
- url: http://192.168.1.20:8082dynamic.yml
Option C: Nginx Proxy Manager
Add a Proxy Host for office.example.com with scheme http, forward hostname onlyoffice (if NPM is on the proxy network) or 192.168.1.20, and forward port 80 (or 8082 if you use the host IP). Request a certificate on the SSL tab and tick Force SSL. Turn Websockets Support on. If large documents fail to open or save, add client_max_body_size 100m; under the Advanced tab.
Once Nextcloud reaches ONLYOFFICE through the proxy (or the shared network), you can remove the ports: section or limit it to "127.0.0.1:8082:80".
Updating ONLYOFFICE
The latest tag follows the newest release. To update:
cd /path/to/appdata/onlyoffice
docker compose pull
docker compose up -d
docker image prune -fdocker exec onlyoffice documentserver-prepare4shutdown.sh first, which saves everything that is still being edited. Pin an exact version (for example onlyoffice/documentserver:9.4.0, if that tag exists on Docker Hub) if you want to control upgrades.Troubleshooting
Nextcloud says "Error when trying to connect" or the token is invalid. The secret in Nextcloud does not match JWT_SECRET, or the headers differ. Run occ onlyoffice:documentserver --check to see what it is complaining about.
The editor opens but says "Download failed". The Document Server cannot reach Nextcloud. Set ALLOW_PRIVATE_IP_ADDRESS: "true", check the "Server address for internal requests" setting, and test from the container: docker exec onlyoffice curl -I http://nextcloud/.
Mixed-content errors in the browser. The Docs address is http:// while Nextcloud is https://, or your proxy is not sending X-Forwarded-Proto.
Nextcloud was fine yesterday, broken after a container recreate. You did not set JWT_SECRET, so a new random one was generated. Set it in the compose file and in Nextcloud.
The container is slow to become healthy or gets killed. It is out of memory. ONLYOFFICE needs about 4 GB of RAM including swap.
That's it! Your Nextcloud now has a full office suite built in, and your documents never leave your server. 📝