Run BentoPDF with Docker or Podman. Covers quick start, Docker Compose, Podman Quadlet, reverse proxies, custom builds, and non-root PUID/PGID support.
Docker is the recommended way to self-host BentoPDF in a production environment. The official image is based on nginx-unprivileged and runs as a non-root user on port 8080.
Office conversions require HTTPS on non-loopback addresses.LibreOffice-based tools (Word, Excel, PowerPoint conversion) require SharedArrayBuffer, which browsers only enable when the page is cross-origin isolated and served from a secure context. http://localhost works for same-device testing, but http://192.168.x.x or any LAN IP requires HTTPS. The official image already sends the required Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp headers — if you add a reverse proxy, ensure those headers are preserved.
All docker commands work with Podman. Replace docker with podman and docker-compose with podman-compose.
Create a container unit file at ~/.config/containers/systemd/bentopdf.container (user) or /etc/containers/systemd/bentopdf.container (system):
bentopdf.container
[Unit]Description=BentoPDF - Privacy-first PDF toolkitAfter=network-online.targetWants=network-online.target[Container]Image=ghcr.io/alam00000/bentopdf:latestContainerName=bentopdfPublishPort=3000:8080AutoUpdate=registry[Service]Restart=alwaysTimeoutStartSec=300[Install]WantedBy=default.target
[Unit]Description=BentoPDF with health monitoringAfter=network-online.targetWants=network-online.target[Container]Image=ghcr.io/alam00000/bentopdf:latestContainerName=bentopdfPublishPort=3000:8080AutoUpdate=registryHealthCmd=wget --spider -q http://localhost:8080 || exit 1HealthInterval=30sHealthTimeout=10sHealthRetries=3[Service]Restart=alwaysTimeoutStartSec=300[Install]WantedBy=default.target
For environments that require running as a specific user — NAS devices, Kubernetes with security contexts, organizational policies — BentoPDF provides Dockerfile.nonroot with LSIO-style PUID/PGID support.
The standard Dockerfile already runs as nginx-unprivileged (UID 101) and is recommended for most deployments. Use Dockerfile.nonroot only when you need a specific UID/GID.
# Build the non-root imagedocker build -f Dockerfile.nonroot -t bentopdf-nonroot .# Run with custom UID/GIDdocker run -d \ --name bentopdf \ -p 3000:8080 \ -e PUID=1000 \ -e PGID=1000 \ --restart unless-stopped \ bentopdf-nonroot
Variable
Description
Default
PUID
User ID to run as
1000
PGID
Group ID to run as
1000
DISABLE_IPV6
Disable the IPv6 listener
false
PUID and PGID cannot be 0 (root). The entrypoint validates inputs and exits with an error for invalid values.
The container starts as root, creates a user with the specified PUID/PGID, adjusts ownership on all writable directories, then drops privileges using su-exec. The nginx process runs entirely as your specified user.Docker Compose example: