How to Install Wiki.js on Ubuntu 24.04 — Self-Hosted Modern Wiki
A good wiki is the backbone of any engineering team, support organization, or open-source project. Wiki.js is an open-source, Node.js-based wiki engine that feels modern — a proper WYSIWYG editor, Markdown with live preview, a proper visual page tree, and first-class support for single sign-on. This guide walks you through installing Wiki.js 2.x on a fresh Ubuntu 24.04 VPS, from SSH connection to a TLS-secured public instance with SSO, Git-backed storage, and a production-ready systemd service.
Prefer a simpler start? Launch an Ubuntu 24.04 VPS in under a minute and follow along with this guide. View VPS plans — Starter plans from EUR 7.99/month.
Table of Contents
What is Wiki.js?
Wiki.js is a modern, open-source wiki engine written in Node.js. It stores content in a relational database (PostgreSQL, MySQL, MariaDB, MS SQL Server, or SQLite) and renders pages through a Vue.js-based frontend. Unlike older wiki platforms, Wiki.js ships with a dual editor — both a rich WYSIWYG editor and a pure Markdown editor — so non-technical contributors and developers can coexist in the same workspace without friction.
Wiki.js is built around an extension model with four types of modules: authentication (over 20 providers including LDAP, SAML, Google, Azure AD, GitHub, GitLab, Okta, Auth0, Keycloak, and generic OAuth2/OIDC), storage (Git push/pull, Amazon S3, DigitalOcean Spaces, Azure Blob, Dropbox, Google Drive, local disk), search (built-in PostgreSQL FTS, plus Elasticsearch, Algolia, Manticore, AWS CloudSearch), and rendering (Markdown, AsciiDoc, reStructuredText, and HTML). You enable the modules you want from the admin UI — no code changes or redeploys needed.
Teams use Wiki.js for engineering runbooks, internal knowledge bases, product documentation, onboarding handbooks, customer support portals, and public project documentation. The comprehensive admin panel covers page history with diffs, role-based access control scoped per page-path, scheduled publishing, draft mode, comments, tags, and a full REST/GraphQL API for automation.
Why Self-Host Your Wiki?
SaaS wikis like Notion, Confluence, and GitBook are convenient, but self-hosting Wiki.js offers advantages that matter for any organization serious about its documentation.
- You own your content — All pages live in a PostgreSQL database you control, with optional Git mirroring. Nothing is locked inside a proprietary SaaS format. Export, migrate, and back up on your schedule.
- Flat-rate pricing — A VPS costs the same whether you have 3 users or 300. Notion and Confluence charge per seat per month, which scales painfully as your team grows.
- Data sovereignty and compliance — For teams handling regulated data (medical records, financial information, EU personal data), hosting on infrastructure you control simplifies GDPR, HIPAA, and SOC 2 audits. No third-party sub-processors to vet.
- Full extension control — Write custom authentication handlers, add your own render pipelines, or plug Wiki.js into your internal services via its GraphQL API. SaaS wikis are black boxes.
- No forced feature changes — Upgrade on your timeline. Pin to a stable version for regulated environments. Never wake up to a UI redesign that breaks your team's workflow.
- Better performance at low cost — Wiki.js is lightweight Node.js. A single 2 vCPU / 4 GB VPS comfortably serves hundreds of concurrent users with sub-100 ms response times.
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access to your server
- A domain name (e.g.
wiki.yourcompany.com) with an A record pointing at your server's public IP - At least 2 GB of RAM and 2 vCPU (4 GB recommended for teams over 20 users)
- 10 GB+ of free disk space for Wiki.js, PostgreSQL, and content
Recommended Plan: Starter>
For a team wiki of up to a few dozen active editors and several hundred readers, the Starter VPS is the sweet spot:>
- 4 vCPU cores
- 6 GB RAM
- 100 GB NVMe SSD
- Unmetered bandwidth
- EUR 7.99/month>
This leaves comfortable headroom for Wiki.js, PostgreSQL, and the occasional background job (scheduled Git sync, search index rebuild, etc.).
Connect to your server:
ssh root@your-server-ipStep 1: Update System Packages
Refresh package metadata and upgrade installed packages so you are on the latest security patches.
sudo apt update && sudo apt upgrade -yInstall a few utilities you will need in later steps:
sudo apt install -y curl ca-certificates gnupg lsb-release ufwEnable a basic firewall now so nothing is ever unnecessarily exposed. Allow SSH and the web ports, then enable:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enableIf a new kernel was installed, reboot before continuing:
sudo rebootStep 2: Install Node.js 20
Wiki.js 2.x requires Node.js 18 or newer. We will install Node.js 20 LTS from the official NodeSource repository, which is the supported path on Ubuntu 24.04.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejsVerify the installed versions:
node --version
npm --versionExpected output:
v20.15.0
10.7.0Node.js ships with npm, which is all Wiki.js needs at runtime — no build tooling required.
Step 3: Install PostgreSQL 16
PostgreSQL is the recommended database for Wiki.js. It unlocks full-text search, JSONB storage for page metadata, and better long-term performance than SQLite. Install PostgreSQL 16 from the official PGDG repository:
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
--fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | \
sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo apt install -y postgresql-16Confirm the service is running:
sudo systemctl status postgresqlCreate the Wiki.js Database and User
Switch to the postgres system account and create a dedicated role and database:
sudo -u postgres psqlInside the psql prompt, run:
CREATE USER wikijs WITH PASSWORD 'CHANGE_ME_STRONG_PASSWORD';
CREATE DATABASE wiki OWNER wikijs;
GRANT ALL PRIVILEGES ON DATABASE wiki TO wikijs;
\qReplace CHANGE_ME_STRONG_PASSWORD with a strong generated password — you can generate one with openssl rand -base64 24 in a second terminal and keep it for the next step.
Confirm you can connect as the new user:
psql -h 127.0.0.1 -U wikijs -d wiki -WType \q to exit once you have authenticated successfully.
Step 4: Download Wiki.js
Create a dedicated system user for Wiki.js so the Node process never runs as root.
sudo useradd --system --create-home --home /var/wiki --shell /bin/bash wikijsSwitch into the new user's home directory, download the latest 2.x release tarball, and extract it:
sudo -u wikijs bash <<'EOF'
cd /var/wiki
curl -L -o wiki-js.tar.gz https://github.com/Requarks/wiki/releases/download/2.5.307/wiki-js.tar.gz
tar xzf wiki-js.tar.gz
rm wiki-js.tar.gz
cp config.sample.yml config.yml
EOFCheck the releases page at github.com/Requarks/wiki/releases for the latest 2.x version and substitute the version number if a newer one is available.
Verify the layout:
sudo ls -la /var/wikiYou should see server/, assets/, node_modules/, package.json, config.sample.yml, and your freshly copied config.yml.
Step 5: Configure config.yml
Edit the configuration file:
sudo -u wikijs nano /var/wiki/config.ymlReplace the contents with the following, adjusted for your environment:
# Port Wiki.js listens on (internal only — Nginx will terminate TLS)
port: 3000
bindIP: 127.0.0.1Database
db:
type: postgres
host: 127.0.0.1
port: 5432
user: wikijs
pass: CHANGE_ME_STRONG_PASSWORD
db: wiki
ssl: falseWhere uploaded files and caches go
paths:
data: ./data
content: ./data/contentUpload limits (tune for your team)
uploads:
maxFileSize: 10485760 # 10 MB
maxFiles: 20Keep logs at info level in production
logLevel: infoOptional: enable HTTP/2 at the Node layer.
Leave false — Nginx will handle HTTP/2 upstream of Wiki.js.
ssl:
enabled: falseOnly port, bindIP, and the db block are strictly required. Everything else has sensible defaults. Because we bind to 127.0.0.1, Wiki.js is not reachable from the public internet directly — only Nginx on the same host can talk to it.
Save and close the file (Ctrl+O, Enter, Ctrl+X in nano).
Step 6: Create the systemd Service
A systemd unit ensures Wiki.js starts on boot, restarts on failure, and writes logs to journalctl.
sudo tee /etc/systemd/system/wiki.service > /dev/null <<'EOF' [Unit] Description=Wiki.js After=network.target postgresql.service Requires=postgresql.service[Service] Type=simple User=wikijs Group=wikijs WorkingDirectory=/var/wiki ExecStart=/usr/bin/node server Restart=always RestartSec=5 Environment=NODE_ENV=production
Hardening
NoNewPrivileges=true ProtectSystem=strict ReadWritePaths=/var/wiki ProtectHome=true PrivateTmp=true
[Install] WantedBy=multi-user.target EOF
Reload systemd, enable the service at boot, and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now wikiVerify it is running:
sudo systemctl status wikiExpected output (abbreviated):
● wiki.service - Wiki.js
Loaded: loaded (/etc/systemd/system/wiki.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-04-16 12:00:00 UTC; 5s ago
Main PID: 5678 (node)
Tasks: 11 (limit: 4687)
Memory: 185.2MTail the logs to confirm Wiki.js finished its first-run migrations:
sudo journalctl -u wiki -fYou are looking for lines like:
[INFO] Using database driver pg for postgres [ OK ]
[INFO] HTTP Server on port: [ 3000 ]
[INFO] HTTP Server: [ RUNNING ]Press Ctrl+C once you see it.
Step 7: First-Run Admin Setup
Before exposing Wiki.js to the internet, you could connect from your laptop via an SSH tunnel and finish the setup wizard, but it is simpler to set up Nginx first (next step) and then visit the real domain. If you prefer to finish setup via a tunnel now, on your local machine run:
ssh -L 3000:127.0.0.1:3000 root@your-server-ipThen open http://localhost:3000 in your browser. You can also skip this and proceed directly to Step 8 — the setup wizard will be waiting at your real domain after TLS is in place.
The setup wizard asks for:
https://wiki.yourcompany.comClick Install. Wiki.js finalizes the schema, creates your admin account, and redirects you to the login page.
Step 8: Nginx Reverse Proxy and TLS
Install Nginx and Certbot for automated Let's Encrypt certificates:
sudo apt install -y nginx certbot python3-certbot-nginxCreate the site configuration:
sudo tee /etc/nginx/sites-available/wiki > /dev/null <<'EOF' server { listen 80; server_name wiki.yourcompany.com; return 301 https://$host$request_uri; }server { listen 443 ssl http2; server_name wiki.yourcompany.com;
# Certbot will populate these paths ssl_certificate /etc/letsencrypt/live/wiki.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/wiki.yourcompany.com/privkey.pem;
# Security headers add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy no-referrer-when-downgrade always;
# Match the Wiki.js upload limit from config.yml client_max_body_size 10m;
location / { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1;
# Required for Wiki.js GraphQL subscriptions and real-time updates proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s; proxy_send_timeout 600s; } } EOF
Replace wiki.yourcompany.com with your actual domain throughout the file, then enable the site:
sudo ln -s /etc/nginx/sites-available/wiki /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -tIssue the certificate and have Certbot wire it into your config automatically:
sudo certbot --nginx -d wiki.yourcompany.comFollow the prompts (enter your email, accept the terms). Certbot installs the cert, updates Nginx, and schedules auto-renewal via a systemd timer.
Reload Nginx:
sudo systemctl reload nginxOpen https://wiki.yourcompany.com in your browser. You should see either the setup wizard (if you skipped Step 7) or the Wiki.js login page.
Step 9: Authentication Modules (SSO)
Wiki.js ships with a built-in local authentication strategy, but most teams want SSO. Navigate to Administration → Authentication in the admin UI to enable any combination of:
- LDAP / Active Directory — Point at your directory server, map
uid/mail/displayNameattributes, and Wiki.js will authenticate against AD/OpenLDAP. Supports nested groups for role assignment. - SAML 2.0 — Connect to Okta, OneLogin, Auth0, ADFS, or any SAML IdP. You will need the IdP metadata URL or XML and the Wiki.js callback URL (
https://wiki.yourcompany.com/login/<strategy-id>/callback). - Google Workspace — Create OAuth credentials in the Google Cloud Console, paste client ID and secret, and optionally restrict sign-in to a specific Workspace domain.
- Microsoft / Azure AD — Register an application in Azure Portal, enable OpenID Connect, and paste the client ID, client secret, and tenant ID.
- GitHub — Register an OAuth App at
github.com/settings/developers, then paste client ID and secret. Useful for open source communities. - Generic OAuth2 / OIDC — Works with Keycloak, Authentik, Zitadel, Authelia, and any standards-compliant provider.
Always keep at least one local admin account as a break-glass, in case your IdP is ever unreachable.
Step 10: Storage Modules (Git and S3)
Storage modules let Wiki.js mirror your content outside the database. This is essential for disaster recovery, version control, and content portability. Under Administration → Storage:
Git (Push/Pull)
The Git storage module writes every page as a Markdown file to a Git repository and pushes commits on every edit. This means every page history is a real Git log — you can diff, blame, and revert with native Git tooling. It also lets technical writers edit pages in their IDE and push changes back, which Wiki.js will pick up on the next pull cycle.
Configure:
[email protected]:yourorg/wiki-content.git (or any SSH-reachable remote)mainssh-keygen -t ed25519 -f wiki-deploy -N "", add the public key to the remote repo with write access, and paste the private key into Wiki.jsClick Apply, then Execute all pending jobs now to do the initial push. If you pair this with a private Gitea, GitLab, or GitHub repo, you get offsite backups for free. For a self-hosted Git server, see our Gitea install guide.
S3-Compatible Object Storage
The S3 storage module uploads page attachments and periodic JSON exports to Amazon S3, DigitalOcean Spaces, Backblaze B2, Wasabi, or MinIO. Configure:
https://fra1.digitaloceanspaces.com (leave blank for AWS S3)fra1 or us-east-1Click Apply. Wiki.js will begin streaming assets to the bucket. Combined with lifecycle rules on the bucket side, you get automated long-term backups without any cron jobs.
Running Git and S3 storage modules simultaneously is fully supported and gives you two independent recovery paths.
Step 11: Themes and Customization
Wiki.js ships with a default theme and allows custom CSS, custom JS, and custom HTML injection via Administration → Theme. You can:
- Swap the primary color and the page width from a visual picker
- Inject custom CSS to match your corporate brand (sidebar colors, typography, logo sizing)
- Override the logo and favicon via Administration → General
- Add a custom HTML footer for legal notices, support links, or a status badge
- Load Google Fonts or self-hosted fonts via a
<link>in the Head HTML block - Add analytics snippets (Umami, Plausible, Matomo) in the Head HTML block
client/themes/ directory where you can fork the default theme. Most teams find the CSS injection panel sufficient — save forking for when you genuinely need structural changes.Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
502 Bad Gateway from Nginx | Wiki.js not listening on port 3000 | sudo systemctl status wiki and check sudo journalctl -u wiki -n 100 for stack traces |
| Setup wizard shows "Database connection failed" | Wrong password or database name in config.yml | Re-check credentials, test with psql -h 127.0.0.1 -U wikijs -d wiki -W, restart Wiki.js |
EACCES: permission denied, open '/var/wiki/data/...' | wikijs user lacks write permission on data dir | sudo chown -R wikijs:wikijs /var/wiki |
| SSO login loop after IdP redirect | Site URL in admin UI does not match the URL users hit | Set Administration → General → Site URL to the exact public HTTPS URL including the scheme |
| Images/attachments 404 after Git pull | Git storage module only syncs Markdown, not binary assets without LFS | Add S3 storage module in addition to Git, or enable Git LFS on the remote |
| Search returns no results after bulk import | PostgreSQL FTS index not rebuilt | Administration → Search → Rebuild Index |
| High memory use on a 2 GB VPS | Node.js default heap is high | Add Environment=NODE_OPTIONS=--max-old-space-size=1024 to the systemd unit |
Viewing Logs
sudo journalctl -u wiki -fTail PostgreSQL logs when debugging database issues:
sudo tail -f /var/log/postgresql/postgresql-16-main.logFAQ
How do I upgrade Wiki.js to a new version?
Wiki.js has a one-click upgrade built into the admin UI at Administration → System → Upgrade, which downloads the latest release, runs migrations, and restarts the Node process. For air-gapped or locked-down environments, you can also upgrade manually: stop the service, back up the database with pg_dump, replace the contents of /var/wiki with the new release tarball (preserving config.yml and data/), and start the service again. Always take a database snapshot before upgrading major versions. The official upgrade documentation has version-specific notes.
Can I run Wiki.js with MySQL or SQLite instead of PostgreSQL?
Yes. Wiki.js supports PostgreSQL, MySQL 8+, MariaDB 10.2+, MS SQL Server 2012+, and SQLite. Swap the db.type in config.yml to mysql, mariadb, mssql, or sqlite and adjust the connection details. That said, PostgreSQL is the recommended and best-tested option — the built-in search uses PostgreSQL's full-text indexing, and most production deployments and Wiki.js's CI pipeline run on it. SQLite is fine for a personal wiki or lab setup but lacks concurrent write performance for teams.
Is Wiki.js free for commercial use?
Yes. Wiki.js is licensed under the AGPLv3, which means it is free to use commercially on your own infrastructure without any seat limits or paid editions. The AGPL does require that if you modify Wiki.js and offer it as a network-accessible service to third parties (e.g. a SaaS hosting product), you must make your modifications available under the same license. For internal company use — even at thousands of users — there are no licensing restrictions or fees.
How does Wiki.js compare to BookStack, Outline, and DokuWiki?
BookStack organizes content into books, chapters, and pages. It is simpler and more opinionated than Wiki.js — great for formal documentation, less flexible for freeform knowledge bases. PHP/Laravel-based.
Outline is a modern team wiki built on React. It has a beautiful UI and excellent real-time collaborative editing, but its authentication is more limited than Wiki.js's 20+ providers, and it requires Redis in addition to PostgreSQL.
DokuWiki stores pages as flat files on disk — no database required. It is extremely lightweight and has a huge plugin ecosystem, but the editing experience feels dated compared to Wiki.js.
Wiki.js wins when you need modern SSO, WYSIWYG plus Markdown, Git-backed storage, and granular path-based permissions all in one product. Choose BookStack for structured documentation, Outline for real-time team collaboration, and DokuWiki for a zero-dependency lightweight wiki.
Can I import existing content from Confluence, Notion, or MediaWiki?
Partially. Wiki.js has a Markdown import feature under Administration → Utilities that ingests a folder of .md files with frontmatter — this is the smoothest path. Most source systems can export to Markdown: Confluence via the confluence-to-markdown tool, Notion via its native "Export as Markdown" option, and MediaWiki via pandoc. Expect to spend time fixing up image links and internal cross-references after import — no importer is perfect. For complex migrations, scripting against the Wiki.js GraphQL API (to programmatically create pages with correct tags and paths) is usually faster than wrestling with generic converters.
How do I back up Wiki.js?
Three things need to be backed up: (1) the PostgreSQL database, which contains all pages and settings; (2) the /var/wiki/data directory, which holds uploaded assets; and (3) your config.yml. A simple nightly cron on the server handles all three:
sudo -u postgres pg_dump wiki | gzip > /var/backups/wiki-$(date +%F).sql.gz
tar czf /var/backups/wiki-data-$(date +%F).tar.gz /var/wiki/data /var/wiki/config.ymlShip the /var/backups directory to offsite storage (S3, Backblaze, or a second VPS via rsync). If you have the Git storage module enabled, your pages are already mirrored to a remote repo on every edit — that covers most disaster scenarios for free.
Does Wiki.js have an API for automation?
Yes. Wiki.js exposes a comprehensive GraphQL API at /graphql covering pages, users, groups, tags, comments, assets, and admin settings. Authenticate with an API key generated under Administration → API Access. Common automations include nightly sync from an external source of truth, bulk page creation from a CSV, programmatic user provisioning from HR systems, and CI pipelines that publish release notes directly to the wiki. The API explorer at /graphql in your admin UI is interactive — it is the easiest way to discover the schema.
Next Steps
With Wiki.js running, here are practical things to do next:
- Enable your SSO provider and disable local sign-up so only provisioned users can access the wiki. This is the single biggest security improvement you can make after install.
- Configure the Git storage module pointed at a private repo on Gitea or GitHub. You now have offsite backups for every page edit, for free.
- Set up page groups and permissions — under Administration → Groups, define per-path read/write rules so engineering, support, and leadership see the right subset of the wiki.
- Add monitoring — point an Uptime Kuma or Healthchecks.io instance at
https://wiki.yourcompany.comso you get alerted to downtime. - Skim the official documentation — docs.requarks.io covers advanced topics like clustering, Elasticsearch, custom render pipelines, and upgrade notes.
- Seed your wiki with a structure — create top-level pages for "Engineering", "Operations", "Product", "HR", and a "Start Here" page. An empty wiki rarely grows; a wiki with a skeleton does.
Need a VPS for your wiki?>
Our Starter plan is perfectly sized for a team wiki:>
- 4 vCPU, 6 GB RAM, 100 GB NVMe SSD
- Ubuntu 24.04 pre-installed
- Full root access
- 99.9% uptime SLA>
Launch a Starter VPS — from EUR 7.99/month.