Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 203 additions & 13 deletions docs/configuration/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,37 +97,227 @@ docker run -d \

### Environment variables

These are read by the container entrypoint and written into `local.json` and the nginx
configuration at start-up. The four variables that limit file sizes are documented
separately under [Size limits](#size-limits).

#### Authentication

| Variable | Default | Description |
|---|---|---|
| `JWT_ENABLED` | `true` | Enable JWT validation |
| `JWT_SECRET` | random | Shared JWT secret (see note below) |
| `JWT_SECRET` | generated | Shared JWT secret. When unset, a random 32-character secret is generated and stored in `/var/www/euro-office/Data/.private/jwt_secret` |
| `JWT_SECRET_INBOX` / `JWT_SECRET_OUTBOX` | `JWT_SECRET` | Separate secrets per direction |
| `JWT_HEADER` | `Authorization` | HTTP header carrying the token |
| `JWT_HEADER_INBOX` / `JWT_HEADER_OUTBOX` | `JWT_HEADER` | Separate headers per direction |
| `JWT_IN_BODY` | `false` | Accept the token in the request body |
| `JWT_ENABLED_INBOX` / `JWT_ENABLED_OUTBOX` | `JWT_ENABLED` | Enable JWT per direction |

#### Database

| Variable | Default | Description |
|---|---|---|
| `DB_TYPE` | `postgres` | Database engine. The standalone image supports `postgres` only; other engines require the cluster image |
| `DB_HOST` | `localhost` | Database host |
| `DB_PORT` | `5432` | Database port |
| `DB_NAME` | `eurooffice` | Database name |
| `DB_USER` | `eurooffice` | Database user |
| `DB_PWD` | — | Database password |

!!! note "`DB_PASSWORD` is deprecated"
`DB_PASSWORD` is a deprecated alias for `DB_PWD`. It still works, but the container
writes `WARNING: DB_PASSWORD is deprecated, use DB_PWD instead` to its standard error
stream at start-up. `DB_PWD` wins if both are set.

#### Redis

| Variable | Default | Description |
|---|---|---|
| `REDIS_SERVER_HOST` | `localhost` | Redis host |
| `REDIS_SERVER_PORT` | `6379` | Redis port |
| `REDIS_SERVER_USER` | — | Redis username for ACL-based authentication. Only written to the configuration when set |
| `REDIS_SERVER_PASS` | — | Redis password. Only written to the configuration when set |
| `REDIS_SERVER_DB` | — | Redis database number. Only written to the configuration when set |

#### RabbitMQ

| Variable | Default | Description |
|---|---|---|
| `AMQP_HOST` | `localhost` | RabbitMQ host |
| `AMQP_PORT` | `5672` | RabbitMQ port |
| `AMQP_USER` / `AMQP_PWD` | `guest` | RabbitMQ credentials |
| `REDIS_SERVER_HOST` | `localhost` | Redis host |
| `REDIS_SERVER_PORT` | `6379` | Redis port |
| `REDIS_SERVER_PASS` | — | Redis password |
| `WOPI_ENABLED` | `false` | Enable WOPI protocol support |
| `PLUGINS_ENABLED` | `true` | Enable editor plugins |
| `METRICS_ENABLED` | `false` | Send StatsD metrics |
| `GENERATE_FONTS` | `true` | Regenerate the font cache on startup |
| `AMQP_VHOST` | `/` | Virtual host name. A leading slash is added automatically if you omit it |
| `AMQP_URI` | — | Complete AMQP connection URI. Takes precedence over all other `AMQP_*` variables |

!!! note
The container only points the Document Server at an external broker when `AMQP_URI`
is set or `AMQP_HOST` differs from `localhost`. Otherwise the RabbitMQ instance
bundled in the image is used.

#### WOPI

| Variable | Default | Description |
|---|---|---|
| `WOPI_ENABLED` | `false` | Enable WOPI protocol support. An RSA key pair is generated in `/var/www/euro-office/Data` on first start |

#### Outbound requests

These control how the Document Server fetches documents from storage such as Nextcloud.

| Variable | Default | Description |
|---|---|---|
| `ALLOW_PRIVATE_IP_ADDRESS` | `false` | Allow fetching documents from private IPs |
| `ALLOW_META_IP_ADDRESS` | `false` | Allow fetching documents from meta-private IPs (169.254.0.0/16) |
| `USE_UNAUTHORIZED_STORAGE` | `false` | Disable TLS certificate validation for outbound requests to storage |

!!! warning "`USE_UNAUTHORIZED_STORAGE` disables certificate validation"
`USE_UNAUTHORIZED_STORAGE=true` sets `rejectUnauthorized: false` on every outbound
HTTPS connection the Document Server makes. The certificate chain, the host name, and
the expiry date of the storage server are no longer checked, so any machine on the
network path can impersonate your Nextcloud instance and read or modify the documents
in transit. It has no effect on plain HTTP connections, which never present a
certificate.

Only use it for self-signed certificates in a trusted network, and prefer adding the
certificate authority to the container's trust store instead.

#### HTTPS and TLS termination

| Variable | Default | Description |
|---|---|---|
| `SSL_CERTIFICATE_PATH` | — | Path inside the container to the TLS certificate |
| `SSL_KEY_PATH` | — | Path inside the container to the matching private key |
| `SSL_DHPARAM_PATH` | — | Path to a Diffie-Hellman parameter file. When unset or unreadable, the `ssl_dhparam` directive is removed |
| `SSL_VERIFY_CLIENT` | `off` | Value for the nginx `ssl_verify_client` directive (client certificate verification) |
| `ONLYOFFICE_HTTPS_HSTS_ENABLED` | `true` | Send an HSTS header. When `false`, the `max-age` directive is removed |
| `ONLYOFFICE_HTTPS_HSTS_MAXAGE` | `31536000` | HSTS max-age in seconds (default 1 year) |

!!! important "The HSTS and client-verification variables need a certificate"
`SSL_DHPARAM_PATH`, `SSL_VERIFY_CLIENT`, and both `ONLYOFFICE_HTTPS_HSTS_*` variables
are only applied when `SSL_CERTIFICATE_PATH` and `SSL_KEY_PATH` are both set **and**
both files exist inside the container. Without them the container serves plain HTTP
and these four variables have no effect at all.

#### Nginx

| Variable | Default | Description |
|---|---|---|
| `NGINX_WORKER_PROCESSES` | `1` | Number of nginx worker processes |
| `NGINX_WORKER_CONNECTIONS` | `768` | Value for the nginx `worker_connections` directive. When unset, the value from the base image's `nginx.conf` is left unchanged |
| `NGINX_ACCESS_LOG` | `false` | Write an access log to `/var/log/euro-office/documentserver/nginx.access.log` |
| `NGINX_CLIENT_MAX_BODY_SIZE` | `100m` | Maximum size of an inbound request body — see [Size limits](#size-limits) |
| `SECURE_LINK_SECRET` | generated | Secret used for the nginx secure link URLs. When unset, a random 20-character secret is generated and stored in `/var/www/euro-office/Data/.private/secure_link_secret` |

#### Metrics

| Variable | Default | Description |
|---|---|---|
| `METRICS_ENABLED` | `false` | Enable StatsD metrics collection and start the metrics service |
| `METRICS_HOST` | `localhost` | StatsD host |
| `METRICS_PORT` | `8125` | StatsD port |
| `METRICS_PREFIX` | `ds.` | Prefix prepended to every metric name |

!!! note
`METRICS_HOST`, `METRICS_PORT`, and `METRICS_PREFIX` are only written to the
configuration when `METRICS_ENABLED=true`.

#### Logging and optional services

| Variable | Default | Description |
|---|---|---|
| `DS_LOG_LEVEL` | `WARN` | log4js level for the default category, for example `ERROR`, `WARN`, `INFO`, or `DEBUG` |
| `PLUGINS_ENABLED` | `true` | Enable editor plugins |
| `GENERATE_FONTS` | `true` | Regenerate the font cache on startup |
| `ADMINPANEL_ENABLED` | `false` | Start the administration panel service |
| `EXAMPLE_ENABLED` | `false` | Start the bundled example application at `/example/`. Do not enable it on a public instance |

### Size limits

Four variables limit file sizes, and they apply to two independent paths through the
Document Server. Which variables matter depends on which path the file takes — raising
the wrong pair has no effect.

#### Documents the server downloads

When a user opens or converts a document that is already stored in Nextcloud, the
Document Server fetches the file itself over HTTP from Nextcloud. Nothing is uploaded
from the browser, so neither the nginx request body limit nor the internal request body
limit is involved. Two variables apply:

**1. The server downloads the file** — `FILECONVERTER_MAX_DOWNLOAD_BYTES` is the maximum
number of bytes the Document Server will fetch. Default is `524288000` (500 MB). A larger
document fails to open:

```bash
-e FILECONVERTER_MAX_DOWNLOAD_BYTES=838860800
```

**2. The server unzips the archive** — `FILECONVERTER_INPUT_LIMIT_UNCOMPRESSED` limits
the *uncompressed* size of the XML inside the office file's ZIP container. Default is
`500MB`:

```bash
-e FILECONVERTER_INPUT_LIMIT_UNCOMPRESSED=800MB
```

For example, a user opens a **200 MB `.pptx`**. The 500 MB download limit is already
sufficient, so no change is needed there. But a 200 MB presentation with embedded images,
shapes, or animations can hold 800 MB of uncompressed XML, which exceeds the 500 MB
default — so only `FILECONVERTER_INPUT_LIMIT_UNCOMPRESSED` has to be raised.

!!! note "`FILECONVERTER_MAX_DOWNLOAD_BYTES` takes no unit suffix"
It must be a plain byte count. A value such as `800MB` is rejected: the container
writes a warning to its standard error stream at start-up, silently keeps the
built-in default, and starts normally. Check the container log after changing it.

!!! note "`FILECONVERTER_INPUT_LIMIT_UNCOMPRESSED` replaces the whole limit list"
It accepts a size suffix and applies the same value to all four format groups the
Document Server knows — `docx`, `xlsx`, `pptx`, and `vsdx` and their variants. It
replaces the whole limit list rather than patching a single entry, so a format group
added by a future release would lose its own default until this variable is updated.

#### Files posted to the server

These limits apply to requests that carry a file in the request body — inserting an image
into an open document, saving a document back, and conversion or command requests posted
to the Document Server. They do **not** apply to opening a stored document.

**1. Nginx accepts the request body** — `NGINX_CLIENT_MAX_BODY_SIZE` must be higher than
the payload. Default is `100m`; a larger body is rejected with
`413 Request Entity Too Large`:

```bash
-e NGINX_CLIENT_MAX_BODY_SIZE=250m
```

**2. The Document Server parses the body** — `MAX_FILE_SIZE` is the internal request body
limit in bytes. Default is `104857600` (100 MB):

```bash
-e MAX_FILE_SIZE=268435456
```

Both have to be raised together. Nginx rejects the request first, so raising only
`MAX_FILE_SIZE` changes nothing.

#### Summary

| Variable | Default | Applies to |
|---|---|---|
| `FILECONVERTER_MAX_DOWNLOAD_BYTES` | `524288000` | Documents the server downloads from Nextcloud |
| `FILECONVERTER_INPUT_LIMIT_UNCOMPRESSED` | `500MB` | Uncompressed XML inside any office file the server opens |
| `NGINX_CLIENT_MAX_BODY_SIZE` | `100m` | Request bodies posted to the server (image inserts, save-back, conversion) |
| `MAX_FILE_SIZE` | `104857600` | Request bodies posted to the server (image inserts, save-back, conversion) |

!!! note "Persisting the JWT secret"
If `JWT_SECRET` is not set, a random secret is generated on first start and
stored under `/var/www/euro-office/Data/.private/`. Mount the `Data`
directory as a volume to keep it stable across container restarts, or set
`JWT_SECRET` explicitly.
!!! note "Persisting generated secrets"
`JWT_SECRET` and `SECURE_LINK_SECRET` are generated on first start when unset, and the
WOPI key pair is generated when `WOPI_ENABLED=true`. All of it lives under
`/var/www/euro-office/Data`, which is a separate tree from
`/var/lib/euro-office/documentserver`. Mount it as a volume to keep the values stable
across container recreation, or set the secrets explicitly — see
[persistent data](../installation/docker.md#persistent-data). A regenerated JWT secret
no longer matches the one configured in the Nextcloud app, and the connection stays
broken until the new value is copied over.

!!! warning "JWT secret length"
When using the Nextcloud integration, the JWT secret must be at least
Expand Down
18 changes: 17 additions & 1 deletion docs/installation/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ Then open `http://localhost:8080/example/` in your browser.

## Persistent data

By default, documents and configuration are lost when the container is removed. Mount volumes to persist them:
By default, documents, configuration, and the secrets generated on first start are lost
when the container is removed. Mount volumes to persist them:

```bash
docker run -d \
Expand All @@ -72,11 +73,26 @@ docker run -d \
-e JWT_ENABLED=true \
-e JWT_SECRET=at-least-32-chars-long-for-hs256 \
-v /path/to/data:/var/lib/euro-office/documentserver \
-v /path/to/private:/var/www/euro-office/Data \
-v /path/to/logs:/var/log/euro-office/documentserver \
-v /path/to/config:/etc/euro-office/documentserver \
ghcr.io/euro-office/documentserver:latest
```

`/var/www/euro-office/Data` holds state the container creates at run time and is easy to
overlook, because it is a separate tree from `/var/lib/euro-office/documentserver`:

- `runtime.json` — the administration panel password and any settings changed at run time
- `.private/jwt_secret` — only created when `JWT_SECRET` is not supplied
- `.private/secure_link_secret` — only created when `SECURE_LINK_SECRET` is not supplied
- `wopi_private.key` and `wopi_public.key` — only created when `WOPI_ENABLED=true`

Without this volume all of it is discarded when the container is recreated, and the
generated values differ on the next start. Secrets you pass in as environment variables
are not affected, but a regenerated JWT secret no longer matches the one configured in the
Nextcloud connector app, and the connection stays broken until the new value is copied
over.

## Environment variables

The most common variables are listed below. For the full set, including the
Expand Down