Install Wiki.js with Node.js, PostgreSQL, and Nginx on Ubuntu 20.04 LTS

Updated on June 18, 2021
Install Wiki.js with Node.js, PostgreSQL, and Nginx on Ubuntu 20.04 LTS header image

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

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 in pass: wikijsrocks with the password of the wikijs role you set in step 2.
  • Replacing wiki in db: wiki with wikidb, 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.