How much server a wiki really needs
Less than you might think, going by the Wiki.js requirements page:
- Processor: one core runs it; two or more are recommended so its background workers have room.
- Memory: 1 GB of RAM as a floor on Linux. The process itself usually uses around 70 MB and jumps briefly while it renders or indexes pages.
- Disk: 1 GB or more set aside. A wiki of mostly text stays tiny; images and videos are what make it grow.
- Address: a domain or sub-domain of its own, like wiki.yourcompany.com. Wiki.js cannot be placed in a subfolder of another site.
So the real question is whether your team's knowledge sits on a machine you control, with nobody else's workload on it, and backups you have tested.
Run version 2, with PostgreSQL
Use the 2.x release. Version 3.0 is being built in the main requarks/wiki repository, whose README marks it as a beta and says not to use it in production; the stable 2.x code now sits in a separate requarks/wiki-v2 repository, which tagged v2.5.316 on 2 October 2026.
Choose PostgreSQL as the database. Version 2 will also run on SQLite, MySQL, MariaDB or MS SQL, but the requirements page warns that the next major release drops all four, so a wiki started on one of them faces a database move later. PostgreSQL's Docker image also comes with pg_trgm, the extension its search module relies on.
The server that fits
Every machine in our dedicated server catalogue has more than enough for a wiki, so pick by what else you want on it and by how you would get back in after a mistake.
- If the wiki is its only job, a small cartridge server is plenty. If you plan to add more of your team's apps, say a self-hosted Forgejo to hold the wiki's Git copy, take an everyday single-processor server.
- Rack servers and blades include a console you can open yourself, the screen and the power button even when the system will not start, and so do two cartridge models, the m510 and m710x. Every other cartridge offers power control alone.
- Choose an Intel or AMD machine rather than the X-Gene ARM cartridge, which runs only Ubuntu 16.04 or 18.04 and has no remote console.
- The port is unmetered, one IPv4 address comes with the server and IPv6 costs nothing, and a ready server is handed over within 30 minutes of the payment being approved.
Up and running in an evening
- Put Ubuntu 24.04 LTS on the server, a release the Wiki.js Ubuntu guide supports. Then add Docker Engine (28 or newer) and Compose from Docker's apt repository.
- Switch on ufw letting in SSH alone, before any container runs, and create the env file for the database password. It starts life empty with mode 600, so other ordinary users cannot read it, and the secret never goes on a command line. That file is our simplification: the Ubuntu guide mounts a password file into both containers instead (POSTGRES_PASSWORD_FILE and DB_PASS_FILE). One caveat either way: whoever may run docker commands can see the value through
docker inspect, so give Docker access only to people who already hold root. - Save the Compose file below as
/srv/wikijs/compose.yaml, change into that folder, and bring the stack up withsudo docker compose up --detach.
sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
sudo ufw allow OpenSSH
sudo ufw --force enable
sudo mkdir -p /srv/wikijs
cd /srv/wikijs
sudo install -m 600 /dev/null wiki.env
SECRET=$(openssl rand -hex 32)
printf "POSTGRES_PASSWORD='%s'\n" "$SECRET" | sudo tee -a wiki.env > /dev/null
printf "DB_PASS='%s'\n" "$SECRET" | sudo tee -a wiki.env > /dev/null
unset SECRET
# /srv/wikijs/compose.yaml
services:
wikidb:
image: postgres:17
env_file: wiki.env
environment:
POSTGRES_DB: wiki
POSTGRES_USER: wikijs
restart: unless-stopped
volumes:
- pgdata:/var/lib/postgresql/data
wikijs:
image: ghcr.io/requarks/wiki:2
depends_on:
- wikidb
init: true
env_file: wiki.env
environment:
DB_TYPE: postgres
DB_HOST: wikidb
DB_PORT: 5432
DB_USER: wikijs
DB_NAME: wiki
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
volumes:
pgdata:
The sed line comes first because ufw only creates the IPv6 twin of a rule made after IPV6=yes is set. The port is tied to 127.0.0.1 because a bare 3000:3000 makes Docker listen on every address the server has, IPv4 0.0.0.0 and IPv6 [::]. Over IPv4, connections to such a port bypass ufw entirely. Over IPv6 they bypass it too if you have switched on IPv6 inside Docker; if you have not, a docker-proxy process holds the [::] port and ufw still filters it. With the loopback address, and Docker Engine 28 or newer, only programs on the server itself can connect.
Become the admin first, in private
A fresh Wiki.js shows a setup screen to the first person who opens it, and that person becomes the administrator. With the port on 127.0.0.1, only an SSH tunnel gets you there:
- On your laptop, run
ssh -L 8080:127.0.0.1:3000 you@server-ip, signing in with your own account. - Open
http://localhost:8080. Fill in your email, a strong password, and the Site URL your team will use, for examplehttps://wiki.yourcompany.com. Telemetry is a separate, optional switch on the same screen. - Before going public, while the tunnel is still open, log in and go to Administration, Groups. Lock the Guests group by flipping its page rule to Deny or taking away every global permission it holds. Then look under Administration, Authentication, Local and make sure self-registration is off.
- Only now make it public. Create the DNS record for your wiki's name, then set up Caddy using the project's apt packages, and in
/etc/caddy/Caddyfileadd a site block for that name containingreverse_proxy 127.0.0.1:3000. Caddy fetches and renews the HTTPS certificate for you. - Let web traffic in: run
sudo ufw allow http, thensudo ufw allow https. Caddy is an ordinary program on the server, not a container, so ufw stops its visitors over both IPv4 and IPv6 until those rules exist; thanks to IPV6=yes, each one opens both.
Moved the wiki to a new name? Update the Site URL under Administration, General, or links in the wiki's emails go astray, as the troubleshooting page notes.
Keep strangers out
Why that step on the tunnel matters: out of the box, sign-ups are closed but reading is not. The setup code in requarks/wiki-v2 (server/setup.js) creates the Local login with self-registration switched off, and gives the Guests group permission to read every page.
- Adding people. Create accounts yourself under Users. Each account needs at least one group, or it can see nothing.
- Both ways to go private. The docs treat a Deny page rule on Guests and an empty set of Guests permissions as equivalent; whichever you chose, check it again after editing groups.
- Turn on two-factor sign-in. Since 2.5, Administration, Security can require it of every user.
- Open sign-ups for colleagues only? Turn self-registration on, allow just your company's email domain, and pick the group newcomers join.
A copy of every page, somewhere else
Your pages are stored in the database. Wiki.js can also push them to a storage target: SFTP, Git, a local folder, Amazon S3, DigitalOcean Spaces or Azure's blob storage. Git is the useful one for most teams, because it syncs both ways and your pages land as files in a repository you can browse and clone.
Give the wiki an empty repository of its own. Changes travel every 5 minutes by default, and Add Untracked Changes sends over pages written before Git was set up. How the key reaches the container is our own recipe: the docs only say the key must sit where Wiki.js can read it, and for permission trouble they suggest switching the container to root, an option the Docker guide itself calls unsafe. Working in /srv/wikijs:
- Make a key with an empty passphrase, because the Git storage guide says password-protected keys will not work. Run
sudo ssh-keygen -N '' -t rsa -b 4096 -f /srv/wikijs/gitsync-key. - Add
gitsync-key.pubto the repo's deploy keys, with permission to push. - Give the private key to the user the wiki runs as, and keep it private:
WUID=$(sudo docker compose exec -T wikijs id -u),sudo chown "$WUID" /srv/wikijs/gitsync-key, thensudo chmod 600 /srv/wikijs/gitsync-key(600, never 644). The-Tmatters, since a TTY would tack a carriage return onto the number. - In
compose.yaml, give the wikijs service avolumes:list holding./gitsync-key:/etc/wiki/gitsync-key:ro, then runsudo docker compose up --detachso the container is rebuilt with the key. - In Administration, Storage, Git, pick ssh and type
/etc/wiki/gitsync-keyinto the field for the private key path.
Git is a second copy of your pages, not a backup of the whole wiki: accounts, groups and settings stay in the database. For that, dump PostgreSQL every night. Wiki.js keeps uploaded files in the database as well (its 2.x asset code stores each one in an assetData table and only caches it on disk), so the dump covers images too. Make the folder first, then add the cron file:
sudo mkdir -p -m 700 /var/backups/wikijs
printf '%s\n' '15 2 * * * root umask 077; cd /srv/wikijs && docker compose exec -T wikidb pg_dump -U wikijs -F c wiki > /var/backups/wikijs/wiki-$(date +\%F).dump' | sudo tee /etc/cron.d/wikijs-dump
Copy those dumps, the Compose file and wiki.env off the server on a schedule of your own. You manage the server; we keep the hardware and the network running.
Practise a restore once, following the transfer guide, and always prove the dump is sound first: the next steps delete the live database, so a broken file would cost you everything. Inside /srv/wikijs, with DUMP pointing at the file, say DUMP=/var/backups/wikijs/wiki-2026-10-23.dump:
- Check it:
sudo test -s "$DUMP" && sudo cat "$DUMP" | sudo docker compose exec -T wikidb pg_restore -l > /dev/null && echo restorable. Ifrestorabledoes not print, stop here. - Stop the wiki with
sudo docker compose stop wikijs. - Empty the database:
sudo docker compose exec -T wikidb dropdb -U wikijs wikiandsudo docker compose exec -T wikidb createdb -U wikijs wiki. - Load the dump with
sudo cat "$DUMP" | sudo docker compose exec -T wikidb pg_restore -d wiki -U wikijs, and start the wiki again withsudo docker compose start wikijs.
Staying current, and the licence
The :2 image tag always points at the newest 2.x release, which is why the Docker guide prefers it to latest. To update, fetch the new image with sudo docker compose pull wikijs, then replace the container using sudo docker compose up --detach --force-recreate wikijs. Take a fresh dump first: the upgrade page warns you cannot return to an older version once the database has been upgraded.
Wiki.js is released under AGPL-3.0, version 3 of the GNU Affero GPL, on both its 2.x and 3.0 repositories. Read this as a general summary, not legal advice. Running it as released is free and puts no duty on you. Give a copy of the software to someone else and it travels with its source under the same licence. Change the code and let people use your changed wiki over the network, your own colleagues included, and you must offer them that changed source. The pages your team writes remain yours.
Questions people ask
- Wiki.js or BookStack for a small team?
- Both are documentation wikis you can run on your own server, and they organise pages differently. Wiki.js gives each page a path, controls access with group rules on those paths, and can sync pages to Git. Our BookStack guide walks through the other one, so you can compare the two before you commit.
- Can Wiki.js handle its own HTTPS certificate?
- Yes, from version 2.1 it can request one from Let's Encrypt, but then the container must publish its web ports to the internet and keep HTTP reachable for renewals. With Caddy in front, the wiki stays private to the server.
- I forgot the admin password. Can I get back in?
- Yes, through the database. The troubleshooting page has you hash a new password with bcrypt at a cost of 12 and store it as your user's password in the users table. Open psql in the wikidb container to make that change.
- Is the Ubuntu guide's Update Companion worth adding?
- It lets you upgrade from the Administration area, but it gets access to the Docker socket, which can control every container on the server. We prefer two Compose commands run by you, after a backup. That is our own view; Wiki.js does not require either way.