Wiki.js works well inside a FreeBSD jail, but there is one important catch: the official Wiki.js release ships a prebuilt Linux sqlite3 native module. On FreeBSD this needs to be rebuilt locally before Wiki.js will start.

This post covers a simple Wiki.js 2.5.314 installation on FreeBSD 15.1 using SQLite, Node.js 24, and a native rc.d service.

Setup

The jail is a normal FreeBSD 15.1-RELEASE jail with its own IP on the LAN.

FreeBSD 15.1-RELEASE Host
└── wiki jail
    └── Wiki.js :3000

No Docker or Linux emulation is needed. Wiki.js itself runs natively under FreeBSD Node.js.

Installing Wiki.js

I created a small bootstrap script which handles the whole installation.

Inside the jail as root:

fetch https://codeberg.org/dkade/BSD/raw/branch/main/FreeBSD/wikijs/install-wikijs-freebsd-15.1.sh
chmod +x install-wikijs-freebsd-15.1.sh
./install-wikijs-freebsd-15.1.sh

The script installs:

node24
npm-node24
python311
gmake
pkgconf
sqlite3
ca_root_nss

It then downloads Wiki.js 2.5.314 and extracts it under:

/usr/local/wikijs

A dedicated wikijs user is created to run the service instead of running Wiki.js as root.

The SQLite FreeBSD gotcha

The official Wiki.js release includes its node_modules, including a prebuilt sqlite3 native module.

Trying to start it directly on FreeBSD results in errors such as:

Shared object "libc.musl-x86_64.so.1" not found,
required by "node_sqlite3.node"

Running ldd makes the problem obvious:

ldd /usr/local/wikijs/node_modules/sqlite3/build/Release/node_sqlite3.node

returns:

not a FreeBSD ELF shared object

The bundled module is a Linux/musl binary, so it cannot be used natively on FreeBSD.

The solution is to rebuild only the SQLite native module:

cd /usr/local/wikijs

rm -rf node_modules/sqlite3/build

env \
  npm_config_python=/usr/local/bin/python3.11 \
  npm_config_build_from_source=true \
  MAKE=gmake \
  npm rebuild sqlite3

Python 3.11 is used because the version of node-gyp bundled with Wiki.js 2.5.x still depends on Python’s old distutils module, which was removed in Python 3.12.

After the rebuild:

file node_modules/sqlite3/build/Release/node_sqlite3.node

should identify it as a FreeBSD ELF shared object.

Test it directly:

node -e "const s=require('sqlite3'); console.log(s.VERSION); console.log('sqlite3 OK')"

Configuration

Wiki.js uses:

/usr/local/wikijs/config.yml

For a simple SQLite setup:

port: 3000

db:
  type: sqlite
  storage: /usr/local/wikijs/data/wiki.db

Make sure the database directory is writable by the Wiki.js user:

mkdir -p /usr/local/wikijs/data
chown -R wikijs:wikijs /usr/local/wikijs

FreeBSD rc.d service

The installer creates:

/usr/local/etc/rc.d/wikijs

Wiki.js is started using FreeBSD’s daemon(8) and Node.js:

/usr/local/bin/node /usr/local/wikijs/server

The service is enabled with:

sysrc wikijs_enable=YES

Start it:

service wikijs start

Check the status:

service wikijs status

Restart it:

service wikijs restart

Logs are written to:

/var/log/wikijs.log

so they can be followed with:

tail -f /var/log/wikijs.log

Once running, Wiki.js is available at:

http://<jail-ip>:3000

The first connection opens the Wiki.js setup wizard.

Upgrading

Before upgrading, take a ZFS snapshot or at least back up:

/usr/local/wikijs/config.yml
/usr/local/wikijs/data/

After replacing the Wiki.js application files with a newer release, rebuild the SQLite module again:

cd /usr/local/wikijs

env \
  npm_config_python=/usr/local/bin/python3.11 \
  npm_config_build_from_source=true \
  MAKE=gmake \
  npm rebuild sqlite3

Then restart Wiki.js:

service wikijs restart

Avoid blindly running:

npm update

or:

npm audit fix --force

inside the Wiki.js application tree. Wiki.js ships with a specific dependency set and changing package versions independently can break the application.

Gotchas

  • SQLite native module: the bundled node_sqlite3.node is Linux/musl and must be rebuilt for FreeBSD.
  • Python version: use Python 3.11 when rebuilding with the older bundled node-gyp.
  • Node.js: Wiki.js 2.5.314 runs correctly with the FreeBSD node24 package.
  • Do not copy old node_modules: when upgrading, use a clean Wiki.js release tree and preserve only your configuration and database.
  • rc.d PID tracking: when using daemon(8), set procname to /usr/local/bin/node so service wikijs status correctly detects the running process.

Summary

Wiki.js runs cleanly inside a FreeBSD 15.1 jail without Docker or Linux emulation.

The only non-obvious part is rebuilding the bundled SQLite native module for FreeBSD. Once that is done, Wiki.js behaves like any other native FreeBSD service: a dedicated user, an rc.d script, automatic startup, and straightforward ZFS snapshots for backups and upgrades.

The bootstrap script automates the complete process from a fresh jail.


Disclaimer: I use AI as a productivity tool. For a senior engineer, AI is incredibly powerful as one can focus on the solution design and conceptualization and leave the boring part that is implementation to the AI.