VPS Tutorials
Deploying Outline Knowledge Base on a VPS (2026): Docker Compose, PostgreSQL, Redis, OAuth and HTTPS
Deploy the Outline team knowledge base on an Ubuntu 24.04 VPS with Docker Compose, covering PostgreSQL, Redis, OAuth login, Caddy HTTPS, attachment storage, backup and restore, upgrade and rollback, and common troubleshooting.

Deploying Outline Knowledge Base on a VPS (2026): Docker Compose, PostgreSQL, Redis, OAuth and HTTPS
Outline is an open-source wiki suited to internal team documentation, product manuals and technical knowledge bases. Its search, Markdown editing, permissions and version history are better suited to long-term collaboration than a simple file directory, but a production deployment requires at least PostgreSQL, Redis, object storage (or a local attachment directory) and HTTPS. This article uses Ubuntu 24.04, Docker Compose and a dedicated domain name as an example to deploy a maintainable Outline instance from scratch.
The Outline pages themselves are not heavy; what really consumes resources is PostgreSQL, Redis, full-text search and attachment processing. Small teams can plan from the following starting points:
| Scenario | Recommended configuration | Notes |
|---|---|---|
| Personal testing | 2 cores, 2GB, 40GB SSD | Only a small number of documents; not recommended for team production |
| 5-20 person team | 2-4 cores, 4GB, 80GB SSD | PostgreSQL, Redis and Outline on the same machine |
| 20+ people | 4 cores, 8GB, 160GB+ NVMe | Database and attachments should be backed up separately or split onto separate machines |
If the VPS has only 1GB of memory, first complete VPS low-memory ZRAM and Swap optimization, then deploy Outline. Swap can only relieve startup peaks; it cannot replace the memory needed for long-term operation.
Point the A/AAAA records of docs.example.com to the VPS, and install Docker Compose:
sudo apt update
sudo apt install -y ca-certificates curl openssl
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER"
newgrp docker
sudo mkdir -p /opt/outline/{data,postgres,redis}
sudo chown -R "$USER":"$USER" /opt/outline
cd /opt/outline
Only open SSH, 80 and 443. Do not map PostgreSQL's 5432 or Redis's 6379 to the public internet.
Outline requires at least SECRET_KEY and UTILS_SECRET. Use random values; do not copy examples from the internet:
openssl rand -hex 32
openssl rand -hex 32
Create .env:
URL=https://docs.example.com
PORT=3000
FORCE_HTTPS=true
SECRET_KEY=替换为第一条随机值
UTILS_SECRET=替换为第二条随机值
DATABASE_URL=postgres://outline:替换数据库密码@postgres:5432/outline
REDIS_URL=redis://redis:6379
POSTGRES_USER=outline
POSTGRES_PASSWORD=替换数据库密码
POSTGRES_DB=outline
# OAuth 以 GitHub 为例,生产环境应使用组织级 OAuth App
OIDC_CLIENT_ID=
OIDC_CLIENT_SECRET=
OIDC_AUTH_URI=
OIDC_TOKEN_URI=
OIDC_USERINFO_URI=
OIDC_LOGOUT_URI=
OIDC_USERNAME_CLAIM=preferred_username
OIDC_DISPLAY_NAME=公司账号
Outline is not suitable for directly opening up "anyone can register". Before OAuth is connected, keep the site within a VPN, access control or a temporary test environment.
Create compose.yml:
services:
outline:
image: outlinewiki/outline:latest
container_name: outline
restart: unless-stopped
env_file: .env
command: sh -c "yarn sequelize:migrate --env production-ssl-disabled && yarn start"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
ports:
- "127.0.0.1:3000:3000"
volumes:
- ./data:/var/lib/outline/data
postgres:
image: postgres:16
container_name: outline-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- ./postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
container_name: outline-redis
restart: unless-stopped
command: redis-server --appendonly yes
volumes:
- ./redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 10
Start and check the logs:
docker compose up -d
docker compose ps
docker compose logs --tail=100 outline
The first startup runs database migrations. If outline keeps exiting, first check docker compose logs outline, focusing on the URL, secrets, database password and OAuth callback address; do not directly delete the PostgreSQL data directory.
Outline requires correct HTTPS and Host headers; otherwise login callbacks, attachment URLs and cookies are prone to errors. After installing Caddy, write the following into the Caddyfile:
docs.example.com {
reverse_proxy 127.0.0.1:3000
}
Caddy will automatically obtain certificates. After modifying, check:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://docs.example.com
If you do not yet have a reverse proxy entry point, refer to Configuring automatic HTTPS with Caddy on a VPS. Do not expose Outline's port 3000 directly to the public internet.
Using an OIDC-compatible identity provider as an example, create an application in the admin console and fill in the callback address:
https://docs.example.com/auth/oidc.callback
Write the client ID, Secret and four OIDC URLs into .env and restart:
docker compose up -d --force-recreate outline
docker compose logs -f outline
If you are redirected back to the homepage after login or encounter redirect_uri mismatch, check each item:
- Whether the callback address registered with the provider uses HTTPS exactly;
- Whether
URLmatches the domain accessed by the browser; - Whether Caddy forwards the original Host and protocol;
- Whether the OIDC issuer, userinfo and logout addresses belong to the same tenant.
Before changing OAuth parameters, keep a working administrator login path to avoid locking all administrators out of the site.
During testing you can use ./data:/var/lib/outline/data, but a single-machine disk failure will lose both the database and attachments. For production, S3-compatible storage is more recommended, for example the previously deployed VPS MinIO object storage, keeping attachments and the database stored separately.
Whether using a local directory or S3, restrict permissions:
chmod 600 /opt/outline/.env
sudo chown -R 1001:1001 /opt/outline/data
Do not set the attachment bucket to public write. Front-end download links should be generated by the application, and the Secret Key should only be placed in server-side environment variables.
The database is the most important backup target. Export PostgreSQL daily, and save .env, the Compose file and attachments at the same time:
mkdir -p /opt/outline/backups
docker compose exec -T postgres pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" | gzip > /opt/outline/backups/outline-$(date +%F).sql.gz
tar -czf /opt/outline/backups/outline-config-$(date +%F).tar.gz .env compose.yml
Do not keep backups only on the same VPS. You can combine the VPS backup and restore drill guide to sync the archive off-site, and regularly restore it once on a temporary instance.
Before upgrading, pin the current image version and back up:
docker compose pull
docker compose up -d
docker compose logs --tail=200 outline
If the new version's migration fails, do not repeatedly run destructive commands; keep the logs, roll back to the previous image tag, and restore from the database backup to an isolated instance for verification.
Confirm whether the Outline container is listening on 3000, whether Caddy is proxying to 127.0.0.1:3000, and check:
docker compose ps
curl -I http://127.0.0.1:3000
Prioritize checking URL, HTTPS, the cookie domain and system time. When the proxy layer downgrades HTTPS to HTTP, secure cookies are discarded by the browser.
First check PostgreSQL logs, disk I/O and container memory, then check whether Redis is healthy. Do not blindly increase Node.js memory without data and metrics.
- Do not commit
.envto Git; store secrets in a password manager. - PostgreSQL, Redis and 3000 should only listen on localhost or the Docker internal network.
- OAuth callbacks should only allow the official domain; disable unnecessary self-service registration.
- Update system security patches weekly, and back up the database before every Outline upgrade.
- Keep at least one off-site copy of the database and attachments, and perform restore drills.
- The admin console can additionally be placed in a WireGuard, Tailscale or Headscale private network.
Stable operation of Outline depends on four things: PostgreSQL persistence, Redis availability, correct HTTPS callbacks, and backups that can actually be restored. Personal testing can run three containers on the same machine; team production should at least include the database and attachments in off-site backups, and verify the migration and rollback path before upgrading.