This is an old revision of the document!
# OnlyOffice Document Server — Rootless Podman Quadlet
Rootless Podman as user `worker` on host `support`. Apache + Let's Encrypt run as `root`. OnlyOffice is bound to localhost only.
| Role | Bind | Public |
| — | — | — |
| Document Server | `127.0.0.1:8082` → container `80` | `https://files.haacksnetworking.org` |
Image: `docker.io/onlyoffice/documentserver:latest` Data: `~/onlyoffice/{data,logs,lib,db}` Custom fonts: optional bind under `~/onlyoffice` or an existing Podman volume.
Do not use `podman generate systemd`. Units come from Quadlet files in `~/.config/containers/systemd/`. Do not bind-mount `/etc/onlyoffice/documentserver/local.json`. The container rewrites that file on start. A mount desyncs nginx `secure_link` and produces `403` on `/cache/files/`. JWT is the restriction. There is no domain allow list.
—
## 1. Directories and secret (worker)
```bash mkdir -p ~/onlyoffice/{data,logs,lib,db} umask 077 openssl rand -hex 32 | tee ~/onlyoffice/jwt.secret chmod 600 ~/onlyoffice/jwt.secret ```
Placeholder used below:
``` JWT_SECRET=replace-with-your-jwt-secret ```
—
## 2. Quadlet
```bash systemctl –user disable –now container-onlyoffice.service 2>/dev/null || true rm -f ~/.config/systemd/user/container-onlyoffice.service podman rm -f onlyoffice
mkdir -p ~/.config/containers/systemd cat > ~/.config/containers/systemd/container-onlyoffice.container « 'EOF' [Container] ContainerName=onlyoffice Image=docker.io/onlyoffice/documentserver:latest PublishPort=127.0.0.1:8082:80 Environment=JWT_ENABLED=true Environment=JWT_SECRET=replace-with-your-jwt-secret Environment=JWT_HEADER=Authorization Environment=ALLOW_PRIVATE_IP_ADDRESS=false Volume=/home/worker/onlyoffice/logs:/var/log/onlyoffice:Z Volume=/home/worker/onlyoffice/data:/var/www/onlyoffice/Data:Z Volume=/home/worker/onlyoffice/lib:/var/lib/onlyoffice:Z Volume=/home/worker/onlyoffice/db:/var/lib/postgresql:Z Volume=/home/worker/podman-local/volumes/84a360c1a5dd357b0cfe5af71a59f7338eeca694336b1ea8bef5d5c41fe7deb7/_data:/usr/share/fonts/truetype/custom:Z PodmanArgs=–cpus=4 –memory=8g [Service] Restart=always TimeoutStopSec=120 [Install] WantedBy=default.target EOF
systemctl –user daemon-reload systemctl –user reset-failed container-onlyoffice.service systemctl –user start container-onlyoffice.service ```
`WantedBy=default.target` starts it. Do not `systemctl enable` a Quadlet unit. Do not `podman generate systemd`. Drop the fonts `Volume=` line if you have no custom fonts. JWT header must be `Authorization`, not `AuthorizationJwt`.
—
## 3. Verify
```bash sleep 90 systemctl –user is-active container-onlyoffice.service podman inspect onlyoffice –format 'name cpus=hostconfig.nanocpus memory=hostconfig.memory' curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/healthcheck podman exec onlyoffice supervisorctl status ```
Expect `active`, `cpus=4000000000`, `memory=8589934592`, HTTP `200`, and `ds:converter` / `ds:docservice` `RUNNING`. First start takes about 90 seconds.
—
## 4. Upgrade script
`/usr/local/bin/upgrade-onlyoffice.sh`. A tag change is an edit to `Image=` in the `.container` file before `daemon-reload`. The script does not recreate the unit.
```bash #!/bin/bash set -euo pipefail
podman pull docker.io/onlyoffice/documentserver:latest
systemctl –user stop container-onlyoffice.service systemctl –user daemon-reload systemctl –user reset-failed container-onlyoffice.service systemctl –user start container-onlyoffice.service
sleep 90 curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/healthcheck ```
Run it as `worker`:
```bash su - worker -c '/bin/bash /usr/local/bin/upgrade-onlyoffice.sh' ```
Do not `sudo -u worker`. That drops the session bus.
—
## 5. Apache reverse proxy (root)
```bash a2enmod proxy proxy_http proxy_wstunnel headers rewrite ssl ```
`/etc/apache2/sites-available/files.haacksnetworking.org.conf`:
```apache <VirtualHost *:80>
ServerName files.haacksnetworking.org
RewriteEngine On
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
ServerName files.haacksnetworking.org
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/files.haacksnetworking.org/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/files.haacksnetworking.org/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SetEnvIf Host "^(.*)$" THE_HOST=$1
RequestHeader setifempty X-Forwarded-Proto "https"
RequestHeader setifempty X-Forwarded-Host %{THE_HOST}e
ProxyAddHeaders Off
ProxyPreserveHost On
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:8082/$1" [P,L]
ProxyPass / http://127.0.0.1:8082/
ProxyPassReverse / http://127.0.0.1:8082/
ErrorLog ${APACHE_LOG_DIR}/onlyoffice-error.log
CustomLog ${APACHE_LOG_DIR}/onlyoffice-access.log combined
</VirtualHost> ```
```bash a2ensite files.haacksnetworking.org.conf apache2ctl configtest && systemctl reload apache2 curl -sI https://files.haacksnetworking.org/healthcheck ```
—
## 6. Nextcloud
```
Admin → ONLYOFFICE:
- Document Editing Service address: `https://files.haacksnetworking.org` - Secret: contents of `~/onlyoffice/jwt.secret` - Save
JWT header must be `Authorization`.
—
## Facts -