Install Wiki.js with Node.js, PostgreSQL, and Nginx on Ubuntu 20.04 LTS
Introduction
Wiki.js is an open-source, lightweight, and powerful wiki software released under the AGPL-v3 license. Its modern and extensible user interface makes it suitable for all kinds of documents, especially software documents. Wiki.js also provides a WYSIWYG editor for non-technical peopleΒ and a Markdown editor for developers.
This tutorial explains how to install Wiki.js on Ubuntu 20.04 LTS and optionally set up HTTPS using a free Let's Encrypt TLS certificate.
Prerequisites
- A Ubuntu 20.04 server.
- Follow Vultr's best practices guides to create a sudo user and update the Ubuntu server.
- (Optional) Configure the Ubuntu firewall (keep the ports 80, 443, and 22 open).
This tutorial assumes you own a domain name such as example.com, and you have pointed it to the server IP address. If not, replace example.com with the server IP address.
Make sure to replace example.com in the code examples with your domain name or IP address.
1. Install Node.js LTS 14
Written in JavaScript, Wiki.js run on any platform where Node.js available. Installing Node.js from the NodeSource repository is one of the methods recommended by the OpenJS Foundation.
Log in to the server as a non-root sudo user via SSH, then enable the NodeSource repository.
$ curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
Install Node.js LTS 14.
$ sudo apt-get install -y nodejs
2. Install PostgreSQL 12
At the time of writing, the latest version of Wiki.js is 2.x and supports several database software. But PostgreSQL is the only database supported since version 3 of Wiki.js and later. Install PostgreSQL 12 with the following command.
$ sudo apt-get install postgresql postgresql-contrib -y
During the installation, PostgreSQL creates a default user named postgres
. Switch to that user to manage PostgreSQL.
$ sudo su - postgres
Log in to the PostgreSQL command line.
$ psql
Create a new role named wikijs
for Wiki.js.
postgres=# CREATE ROLE wikijs WITH LOGIN;
Set a strong password for the wikijs
role. You can use a free password manager like KeePassXC or an online tool such as Random Password Generator to generate strong passwords.
postgres=# \password wikijs
Enter a strong password twice when prompted. Then create a new database named wikidb
for Wiki.js.
postgres=# CREATE DATABASE wikidb;
Grant all privileges on the wikidb
database to the wikijs
role.
postgres=# GRANT ALL PRIVILEGES ON DATABASE wikidb TO wikijs;
Exit the PostgreSQL command-line.
postgres=# \q
You have just finished the PostgreSQL installation. Now switch back to the sudo user to install Wiki.js.
$ exit
3. Install Wiki.js
Download the Source Code
To enhance the security of your server, create a dedicated user named wikijs
as the user of Node.js processes for Wiki.js. This user also owns the Wiki.js source code files.
$ sudo adduser wikijs
Every time you want to add, delete, or update the source code files, you need to switch to this user.
Create a folder to store the Wiki.js source code.
$ sudo mkdir -p /var/www/wikijs
Set wikijs
as the owner of the source code folder.
$ sudo chown wikijs:wikijs /var/www/wikijs
Switch to the wikijs
user.
$ sudo su wikijs
Download the latest Wiki.js source code archive.
$ cd /var/www/wikijs && wget https://github.com/Requarks/wiki/releases/latest/download/wiki-js.tar.gz
Extract the archive.
$ tar xzf wiki-js.tar.gz
Configure Wiki.js
Create the configuration file from the sample file.
$ cp config.sample.yml config.yml
Update the configuration file with the appropriate information.
$ nano config.yml
Find the following database settings:
# PostgreSQL / MySQL / MariaDB / MS SQL Server only:
host: localhost
port: 5432
user: wikijs
pass: wikijsrocks
db: wiki
You do not need to update the following settings as they are already correct.
host: localhost
port: 5432
user: wikijs
But you need to update the last two settings by:
- Replacing
wikijsrocks
inpass: wikijsrocks
with the password of thewikijs
role you set in step 2. - Replacing
wiki
indb: wiki
withwikidb
, the name of the database you created in step 2.
For best performance and security, you will use Nginx as a reverse proxy for Wiki.js. Find and update the setting bindIP: 0.0.0.0
to bindIP: 127.0.0.1
to make Wiki.js listen on the loopback address.
Save the configuration file and exit. Then run Wiki.js for the first time.
$ node server
You should see something like this:
2021-06-09T16:46:48.187Z [MASTER] info: =======================================
2021-06-09T16:46:48.190Z [MASTER] info: = Wiki.js 2.5.201 =====================
2021-06-09T16:46:48.191Z [MASTER] info: =======================================
2021-06-09T16:46:48.191Z [MASTER] info: Initializing...
2021-06-09T16:46:49.079Z [MASTER] info: Using database driver pg for postgres [ OK ]
2021-06-09T16:46:49.086Z [MASTER] info: Connecting to database...
2021-06-09T16:46:49.117Z [MASTER] info: Database Connection Successful [ OK ]
2021-06-09T16:46:49.467Z [MASTER] warn: DB Configuration is empty or incomplete. Switching to Setup mode...
2021-06-09T16:46:49.468Z [MASTER] info: Starting setup wizard...
2021-06-09T16:46:49.740Z [MASTER] info: Starting HTTP server on port 3000...
2021-06-09T16:46:49.741Z [MASTER] info: HTTP Server on port: [ 3000 ]
2021-06-09T16:46:49.745Z [MASTER] info: HTTP Server: [ RUNNING ]
2021-06-09T16:46:49.745Z [MASTER] info: π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»π»
2021-06-09T16:46:49.745Z [MASTER] info:
2021-06-09T16:46:49.746Z [MASTER] info: Browse to http://YOUR-SERVER-IP:3000/ to complete setup!
2021-06-09T16:46:49.746Z [MASTER] info:
2021-06-09T16:46:49.746Z [MASTER] info: πΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊπΊ
If so, the configuration is correct, and Wiki.js is running. Press Ctrl + C to stop Wiki.js, then switch back to the sudo user to continue with the setup.
$ exit
Create a systemd Service
You will create a systemd service to run Wiki.js as a background service. That service helps you operate Wiki.js easier. Also, every time the operating system starts, it will automatically run Wiki.js.
Create a new file named wikijs.service
inside the /etc/systemd/system
directory.
$ sudo nano /etc/systemd/system/wikijs.service
Paste the following contents:
[Unit]
Description=Wiki.js
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/node server
Restart=always
User=wikijs
Environment=NODE_ENV=production
WorkingDirectory=/var/www/wikijs
[Install]
WantedBy=multi-user.target
Save the service file and exit. Then reload systemd.
$ sudo systemctl daemon-reload
Enable the service on system boot.
$ sudo systemctl enable wikijs.service
4. Install Nginx
For high performance and security, it is best to use Nginx as a reverse proxy for Wiki.js. Install Nginx with the following command.
$ sudo apt install nginx -y
Disable the default configuration.
$ sudo rm /etc/nginx/sites-enabled/default
Create a new configuration file for Wiki.js.
$ sudo nano /etc/nginx/sites-available/wikijs-http.conf
Paste the following contents:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
root /var/www/wikijs;
# Pass requests to the Wiki.js service listening on 127.0.0.1:3000
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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;
}
}
Save the configuration file and exit. Then enable the new configuration.
$ sudo ln -s /etc/nginx/sites-available/wikijs-http.conf /etc/nginx/sites-enabled/wikijs-http.conf
Check the new configuration.
$ sudo nginx -t
Reload Nginx for the changes to take effect.
$ sudo systemctl reload nginx.service
5. (Optional) Configure HTTPS
If you own a valid domain name, you can set up HTTPS for your Wiki.js at no cost. Using the Certbot program, you can get a free TLS certificate from Let's Encrypt, a certificate authority.
Install Certbot with Snap
Ubuntu has built-in Snap Store support that makes it easy to get the latest version of Certbot with features like automatic certificate renewal.
$ sudo snap install --classic certbot
Make the certbot
command globally available.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Get a Let's Encrypt Certificate
Rename the HTTP configuration file to make it the template for the HTTPS configuration file.
$ sudo mv /etc/nginx/sites-available/wikijs-http.conf /etc/nginx/sites-available/wikijs-https.conf
Create a new configuration file to serve HTTP requests.
$ sudo nano /etc/nginx/sites-available/wikijs-http.conf
Paste the following contents:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com;
root /var/www/wikijs;
location / {
return 301 https://$server_name$request_uri;
}
location /.well-known/acme-challenge/ {}
}
This configuration makes Nginx redirect all HTTP requests, except those from Let's Encrypt, to corresponding HTTPS requests.
Save the configuration file and exit. Then check the Nginx configuration.
$ sudo nginx -t
Apply the new configuration.
$ sudo systemctl reload nginx.service
Now you can run the following command to get the Let's Encrypt certificate.Β Press Y when prompted.
$ sudo certbot certonly --webroot -w /var/www/wikijs -d example.com -m admin@example.com --agree-tos
When finished, certbot
tells you the path of your certificate file and key file:
/etc/letsencrypt/live/example.com/fullchain.pem
/etc/letsencrypt/live/example.com/privkey.pem
Another critical file, located in the same folder, also needed for the next step, is chain.pem
.
Install the Certificate with Nginx
Generate a file with DH parameters for DHE ciphers.
$ sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
2048 is the recommended size of DH parameters. This process may take a while, so please be patient.
Update the HTTPS configuration file.
$ sudo nano /etc/nginx/sites-available/wikijs-https.conf
Find the following lines:
listen 80 default_server;
listen [::]:80 default_server;
Replace them with:
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
# DH parameters file
ssl_dhparam /etc/nginx/dhparam.pem;
# intermediate configuration
ssl_protocols TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
#
# Uncomment the following line only if your website fully supports HTTPS
# and you have no intention of going back to HTTP, otherwise, it will
# break your site.
#
# add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# Use Cloudflare DNS resolver
resolver 1.1.1.1;
Save the configuration file and exit. Then enable the new configuration.
$ sudo ln -s /etc/nginx/sites-available/wikijs-https.conf /etc/nginx/sites-enabled/wikijs-https.conf
Apply the new configuration.
$ sudo systemctl reload nginx.service
Automate Renewal
Let's Encrypt certificates are valid for 90 days, so you must renew your TLS certificate at least once every three months. The Certbot installation automatically created a systemd timer unit to automate this task. Run the following command to verify the timer is active.
$ sudo systemctl list-timers | grep 'certbot\|ACTIVATES'
After renewing the certificate, Certbot will not automatically reload Nginx, so Nginx still uses the old certificate. You must write a script inside the /etc/letsencrypt/renewal-hooks/deploy
folder to reload Nginx.
Open your text editor.
$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Paste the following contents into the editor:
#!/bin/bash
/usr/bin/systemctl reload nginx.service
Save and exit. Then make the script executable.
$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
Test the renewal process with a dry run.
$ sudo certbot renew --dry-run
This Vultr article explains all the above steps in more detail. This kind of TLS setup gives you an A on the SSL Labs test.
6. Complete the Wiki.js Setup
Restart the server to see if everything is working fine.
$ sudo reboot
Wait a moment for the system to boot, then open the http://example.com link in your browser. You will see the Setup screen.
Enter your email and a strong password for your administrator account.
In the Site URL field, enter https://example.com if you have configured HTTPS in step 5, or enter http://example.com if not.
Click the Install button and wait for a while for Wiki.js to complete the installation. When finished, it redirects you to the Login screen.
Enter your credentials then click the Log In button.
Wiki.js is now ready, and you can create the home page.
You may want to read the Wiki.js User Guide to learn more about how to manage Wiki.js.