How to Deploy Wiki.js on a VPS
Updated Sep 2026
verified on Ubuntu 26.04 · Sep 2026Self-host Wiki.js 2 on a small VPS with PostgreSQL, HTTPS through Caddy, a locked-down setup wizard, and database backups you can restore.
- A VPS with at least 1 GB RAM (the Wiki.js documented minimum on Linux)
- A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
- A dedicated domain or subdomain — Wiki.js can't be served from a subfolder
- Docker Engine + Compose installed (see the base guide below)
What Wiki.js is
Wiki.js is a Node.js wiki released under the AGPL-3.0 licence. You write pages in Markdown or a visual editor, organize them by path, and control who can read or edit what with groups and page rules. Its authentication modules are unusually broad for a free build: local accounts, social logins, and enterprise options such as LDAP, SAML, OIDC and CAS are all included, with optional two-factor authentication.
Wiki.js brings its own web server but no database — you run one next to it. PostgreSQL is the one upstream recommends, and it's the only engine the next major version will keep supporting, so this guide uses it.
Weighing it against the other common pick? Wiki.js vs BookStack covers the difference: Wiki.js is free-form paths and Markdown, BookStack is a fixed shelves-books-pages structure. The BookStack guide covers that install.
Server sizing
Upstream's requirements are specific: at least 1 GB of RAM on Linux, and one CPU core works, but two or more are recommended so the background workers (rendering, search indexing) have room. The Wiki.js process usually sits around 70 MB and spikes during rendering and indexing. On our install-verification run (GCP e2-standard-2, Ubuntu 26.04) Wiki.js plus PostgreSQL idled at about 94 MB of RAM and 1.4 GB of disk.
- 1 GB RAM / 1 vCPU — the floor for a small team wiki.
- 2 GB RAM / 2 vCPU — the comfortable choice, and what upstream's CPU advice points to.
Upstream suggests at least 1 GB of storage for Wiki.js itself; text barely grows, uploads do. 20 GB of disk is a sensible start.
Prepare the server
This guide assumes Docker Engine and the Compose plugin are installed, along
with a non-root user and a ufw firewall. If not, follow
Docker & Compose on Ubuntu first.
Only SSH, 80 and 443 should be reachable:
sudo ufw status verbose
Paid link — we earn a commission if you shop through it.
Install Wiki.js (Docker Compose)
Create the project directory:
mkdir -p ~/wikijs && cd ~/wikijs
Generate the database password once into a .env file. Compose reads it
automatically, and the guard means re-running this step never replaces the
password of a database that already exists:
[ -f .env ] || echo "DB_PASS=$(openssl rand -hex 16)" > .env
chmod 600 .env
The compose file follows the example in the Wiki.js Docker docs — the
ghcr.io/requarks/wiki:2 image (upstream advises the major-version tag over
latest) and postgres:15-alpine — with two changes: the password comes from
.env, and the port is bound to loopback so only the reverse proxy can reach
it:
cat > docker-compose.yml <<'YAML'
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: wiki
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_USER: wikijs
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
wiki:
image: ghcr.io/requarks/wiki:2
depends_on: [db]
init: true
environment:
DB_TYPE: postgres
DB_HOST: db
DB_PORT: 5432
DB_USER: wikijs
DB_PASS: ${DB_PASS}
DB_NAME: wiki
restart: unless-stopped
ports:
# Loopback only: Caddy is the only way in from outside.
- "127.0.0.1:3000:3000"
volumes:
db-data:
YAML
Start it and wait until Wiki.js answers:
docker compose up -d
for i in $(seq 1 60); do
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000/)
[ "$code" = "200" ] && break
sleep 5
done
echo "Wiki.js answered HTTP $code"
docker compose ps
HTTP 200 means the setup page is being served. Wiki.js doesn't store content
in the container: pages, users and settings live in PostgreSQL, and uploads are
stored in the database too, which keeps backups to one dump.
HTTPS + domain
Wiki.js needs its own hostname — upstream is explicit that it can't be
mapped to a subfolder. Point an A record for wiki.example.com at the
server, wait for it to resolve, and put TLS in front with
Automatic HTTPS with Caddy:
wiki.example.com {
reverse_proxy 127.0.0.1:3000
}
If you run Caddy as a container, proxy to wiki:3000 on a shared network
instead and drop the host port publish. Wiki.js can also request Let's Encrypt
certificates itself (LETSENCRYPT_DOMAIN), but that means publishing its ports
directly; letting Caddy handle TLS keeps renewals out of the application.
Run the setup wizard — immediately
The first visit to https://wiki.example.com shows a setup screen that
asks for the administrator email, password and the site URL. Whoever submits it
first owns the wiki, so complete it as soon as the domain resolves, before
anyone else finds the page. Enter the https:// address as the site URL; it's
used to build links and can be changed later under Administration → General.
Once you're in:
- Administration → Users: create accounts for your team rather than sharing the admin login.
- Administration → Groups: the built-in Guests group decides what logged-out visitors can see. For a private wiki, remove its read permissions.
- Administration → Authentication: turn off self-registration on the local strategy unless you mean to allow it, or connect your LDAP, SAML or OIDC provider. Enable two-factor authentication for administrators.
- Administration → Mail: SMTP is needed for invitations and password resets.
Backups
Everything that matters is in PostgreSQL. Dump it with the tools inside the database container:
cd ~/wikijs
docker compose exec -T db pg_dump -U wikijs wiki > wikijs-$(date +%F).sql
test -s wikijs-$(date +%F).sql && ls -lh wikijs-*.sql
Keep a copy of .env and docker-compose.yml with it, and copy all of it
off the server. To restore onto a fresh install, start only the database
(docker compose up -d db), feed the dump back with
docker compose exec -T db psql -U wikijs wiki < wikijs-DATE.sql, then start
the wiki service.
Wiki.js also has storage modules (under Administration → Storage) that can sync your pages to Git, S3 or a local folder as Markdown files. That's a useful second copy — pages you can read without Wiki.js — but it isn't a full backup of users and settings, so keep the database dump.
Upgrades
The :2 tag follows the latest 2.x release. To move to it:
cd ~/wikijs
docker compose pull
docker compose up -d
Wiki.js runs its database migrations on start. Take a dump first. Upstream has said the next major version will drop MySQL, MariaDB, MS SQL and SQLite, and an export/import tool is planned for moving between major versions — another reason to start on PostgreSQL.
Troubleshooting
The container restarts in a loop. Read docker compose logs wiki. A
database connection error on the first boot usually means PostgreSQL was still
initializing; it recovers on its own. A persistent authentication error means
DB_PASS changed after the database was created — the password is set only
when the data volume is first initialized.
Links and redirects point to the wrong host. The site URL from the setup wizard is wrong. Fix it under Administration → General.
Search returns nothing useful. The default basic search engine is limited.
With PostgreSQL you can switch to the PostgreSQL search module under
Administration → Search; the postgres image already includes the pg_trgm
extension it needs.
Pages are slow right after a big import. Rendering and indexing run in the background and can spike memory; on a 1 GB box, give it a few minutes or add RAM.
Verification + next steps
You're done when https://wiki.example.com loads with a valid certificate, the
setup wizard is gone and you can sign in as the administrator, a logged-out
private window sees only what the Guests group allows, and a database dump
sits somewhere off the server.
Next: connect your identity provider, turn on a Git storage module for a
readable copy of every page, and schedule the pg_dump with cron. If you want
real-time co-editing instead, see the Docmost
guide. For host choices, see Best VPS for
Self-Hosting.