The Way to Your Own Cloud (Part 14) – Your Own Wiki

Knowledge is power – and especially in projects and teams it is worth gold. Instead of scattered documents, PDFs, and emails, a wiki provides a central, searchable, and versioned knowledge base.

Wiki.js is a modern, elegant open-source alternative to Atlassian Confluence or MediaWiki: fast UI, Markdown editor, roles & permissions, auth integrations, and many extensions.

Setup

First, create a new user and database with psql:

sudo -u postgres psql
CREATE USER wikijsuser WITH PASSWORD '<STRONG-PASSWORD>';

CREATE DATABASE wikijs WITH OWNER wikijsuser;

GRANT ALL PRIVILEGES ON DATABASE wikijs TO wikijsuser;
\q

Then create the working directory:

sudo mkdir -p /opt/wikijs
cd /opt/wikijs

Inside it, create a file called docker-compose.yaml:

services:
  wikijs:
    image: localhost:5000/requarks/wiki:2
    container_name: wikijs
    restart: unless-stopped
    environment:
      - DB_TYPE=postgres
      - DB_HOST=host.docker.internal
      - DB_PORT=5432
      - DB_USER=wikijsuser
      - DB_PASS=<STRONG-PASSWORD>
      - DB_NAME=wikijs
      # Optional: Language/Timezone
      - TZ=Europe/Berlin
      - LANG=de_DE.UTF-8
    ports:
      - "9163:3000"
    volumes:
      - wikijs_data:/wiki/data
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/healthz', r => process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))"]
      interval: 30s
      timeout: 5s
      retries: 5

volumes:
  wikijs_data:
    name: wikijs_data

Load the Docker image into your local registry:

docker pull requarks/wiki:2
docker tag requarks/wiki:2 localhost:5000/requarks/wiki:2
docker push localhost:5000/requarks/wiki:2

Now start the service as a background process:

docker compose up -d

For secure external communication, generate a random port:

echo $(shuf -i 1024-65535 -n 1)

Then create the NGINX config file at /etc/nginx/sites-available/wikijs:

server {
  listen <RANDOM-PORT> ssl;
  server_name <CLOUD-DOMAIN>;

  ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;

  client_max_body_size 1024M;

  location / {
    proxy_pass http://localhost:9163;
    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_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $http_connection;

    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
  }
}

Enable and reload:

sudo ln -s /etc/nginx/sites-available/wikijs /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl restart nginx

Finally, open the firewall:

sudo ufw allow <RANDOM-PORT>
sudo ufw reload

Now you can access your wiki via:
https://<CLOUD-DOMAIN>:<RANDOM-PORT>

Backup

Create a plugin file at /opt/backup/plugins/wikijs.sh:

#!/bin/bash

PLUGIN_OUTPUT_DIR="$1"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S.%3N')] $*"
}

WIKIJS_DIR="/var/lib/docker/volumes/wikijs_data/_data"
BACKUP_FILE="$PLUGIN_OUTPUT_DIR/wikijs_files_$(date '+%Y-%m-%d').tar.gz"

log "[INFO] Backup data in $WIKIJS_DIR ..."
tar -czf "$BACKUP_FILE" -C "$WIKIJS_DIR" .

if [ $? -eq 0 ]; then
    log "[INFO] Backup was successful: $BACKUP_FILE"
else
    log "[ERROR] Backup failed!"
fi

Make it executable:

chmod +x /opt/backup/plugins/wikijs.sh

Quick & Dirty

DB_PASS='STRONG_PASSWORD'
DOMAIN='cloud.example.com'
PORT=$(shuf -i 1024-65535 -n 1)

sudo -u postgres psql <<EOF
CREATE USER wikijsuser WITH PASSWORD '$DB_PASS';
CREATE DATABASE wikijs WITH OWNER wikijsuser;
GRANT ALL PRIVILEGES ON DATABASE wikijs TO wikijsuser;
\q
EOF

sudo mkdir -p /opt/wikijs
cd /opt/wikijs

cat <<EOF > docker-compose.yaml
services:
  wikijs:
    image: localhost:5000/requarks/wiki:2
    container_name: wikijs
    restart: unless-stopped
    environment:
      - DB_TYPE=postgres
      - DB_HOST=host.docker.internal
      - DB_PORT=5432
      - DB_USER=wikijsuser
      - DB_PASS=$DB_PASS
      - DB_NAME=wikijs
      - TZ=Europe/Berlin
      - LANG=de_DE.UTF-8
    ports:
      - "9163:3000"
    volumes:
      - wikijs_data:/wiki/data
    extra_hosts:
      - "host.docker.internal:host-gateway"

volumes:
  wikijs_data:
    name: wikijs_data
EOF

docker pull requarks/wiki:2
docker tag requarks/wiki:2 localhost:5000/requarks/wiki:2
docker push localhost:5000/requarks/wiki:2

docker compose up -d

cat <<EOF | sudo tee /etc/nginx/sites-available/wikijs
server {
  listen $PORT ssl;
  server_name $DOMAIN;
  ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
  location / {
    proxy_pass http://localhost:9163;
    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;
  }
}
EOF

sudo ln -s /etc/nginx/sites-available/wikijs /etc/nginx/sites-enabled/
sudo systemctl restart nginx
sudo ufw allow $PORT && sudo ufw reload

cat <<'EOF' > /opt/backup/plugins/wikijs.sh
#!/bin/bash
PLUGIN_OUTPUT_DIR="$1"
WIKIJS_DIR="/var/lib/docker/volumes/wikijs_data/_data"
tar -czf "$PLUGIN_OUTPUT_DIR/wikijs_files_$(date '+%Y-%m-%d').tar.gz" -C "$WIKIJS_DIR" .
EOF
chmod +x /opt/backup/plugins/wikijs.sh