Skip to content

Deployment ​

This document covers installing ProjectWikit, starting it for the first time, creating the first site and administrator, serving the site on a domain over HTTPS, and running pwikit as a system service. Every setting is described in Configuration, and every command in Command line.

Requirements ​

ItemNeeded for
Windows (amd64), Linux (amd64 or arm64), or macOS (amd64 or arm64)Running pwikit
A domain name for the pages, optionally a second one for uploaded files, with DNS records pointing at the machinePublic access over HTTPS
TCP ports 80 and 443 reachable from the internetAutomatic HTTPS certificates
glibc 2.28 or newer (RHEL 8, Debian 10, Ubuntu 20.04 and later)Running pwikit on Linux
systemdInstalling pwikit as a service on Linux
PostgreSQL 14 or newerOnly when you use your own database instead of the bundled PostgreSQL

Getting pwikit ​

Using the install script ​

The install script downloads the release package for this machine, checks its sha256, puts pwikit into the install directory, and makes pwikit runnable by name from any directory. It creates no site and installs no service.

On Linux and macOS:

sh
curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sh

In PowerShell on Windows:

powershell
irm https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.ps1 | iex

The scripts install into the current directory, which must be empty. Create a directory for the instance, change into it, and run the script there.

The install directory belongs to the account that runs the script; through sudo, to the account sudo was run from; on Linux, logged in as root, to root. See Running as root.

Options for install.sh go after sh -s --:

sh
curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sudo sh -s -- --dir /srv/wiki
OptionMeaning
--version <vX.Y.Z>Install this release instead of the newest
--dir <directory>Install directory instead of the current directory. It must not exist or be empty
--mirror <url>Mirror to use when GitHub cannot be reached. It is also written into pwikit.toml, so later automatic updates use it too
--user <account>Owner of the install directory when run as root. Defaults to the account sudo was run from; logged in as root, the directory belongs to root. On macOS, pass it when running as root
--no-pathDo not make pwikit runnable by name

Piped into iex, install.ps1 reads the same choices from the environment variables PWIKIT_VERSION, PWIKIT_DIR, PWIKIT_MIRROR and PWIKIT_NO_PATH; saved to a file, it also takes -Version, -Dir, -Mirror and -NoPath.

When GitHub cannot be reached, fetch the script from a mirror instead. A mirror uses the same addresses as GitHub Releases, with https://github.com/WikitTeam/ProjectWikit/releases replaced by the mirror's address:

sh
curl -fsSL https://wikit.unitreaty.org/projwikit/update/latest/download/install.sh | sh
powershell
irm https://wikit.unitreaty.org/projwikit/update/latest/download/install.ps1 | iex

A script fetched from a mirror downloads from that mirror and writes the mirror's address into pwikit.toml, so later automatic updates use the mirror when GitHub cannot be reached. https://wikit.unitreaty.org/projwikit/update is a mirror run by the ProjectWikit maintainers for servers, such as those in mainland China, that cannot reach GitHub reliably. Releases are not signed, so use only a mirror you trust; see Download source and mirrors.

Downloading by hand ​

Download the package for this machine from GitHub Releases and check it against the SHA256SUMS of the same release:

SystemPackage
Linux (amd64 / arm64)pwikit-<version>-linux-amd64.tar.gz / pwikit-<version>-linux-arm64.tar.gz
macOS (Intel / Apple silicon)pwikit-<version>-darwin-amd64.tar.gz / pwikit-<version>-darwin-arm64.tar.gz
Windowspwikit-<version>-windows-amd64.zip

The unpacked directory holds pwikit, LICENSE and NOTICE, the copyright and licence notices of third-party components.

The macOS packages are not signed. When one is downloaded with a browser, macOS refuses to run it; after unpacking, run once:

sh
xattr -d com.apple.quarantine pwikit

Files downloaded with curl or the install script are not affected.

The executable and its data directory ​

pwikit is a single executable: pwikit on Linux and macOS, pwikit.exe on Windows. Place it in the directory where the instance should keep its data, for example /opt/pwikit or C:\pwikit. The examples in this document run commands from that directory as ./pwikit. On Windows, write .\pwikit.exe where the examples write ./pwikit. Typing pwikit from any directory works only once pwikit is installed as a system service or with pwikit path install; see Running pwikit by name.

By default pwikit keeps all of its data in the directory that holds the executable. When pwikit is started through a symbolic link, the directory of the file the link points to is used. The directory fills up as follows:

EntryContents
pwikit.tomlSettings. Written on the first start as a commented template. See Configuration.
files/Files uploaded to the sites.
archive/Created empty. A place to keep wikitCLI backups before importing them; pwikit import reads it when no other directory is named.
secrets/Keys and certificates pwikit generates. Keep this directory private.
postgres/The bundled PostgreSQL programs, unpacked on the first start.
pgdata/The database of the bundled PostgreSQL.
logs/PostgreSQL logs, and pwikit's own log when it runs as a service on Windows or macOS.
backups/Backups written by pwikit backup create. See Operations.

postgres/ and pgdata/ exist only when the bundled PostgreSQL is used.

To keep the data somewhere else, pass -data-dir <directory> to every command, or set the environment variable PWIKIT_DATA_DIR. The option takes precedence over the variable. Every command must use the same data directory; otherwise it reads different settings and a different database.

Page assets ​

The stylesheets, scripts, fonts and images used by the pages are built into pwikit, so no separate directory is needed. -static-dir <directory> serves them from a directory instead of the built-in copy, which is useful only when changing the web interface. This option exists only on the command line and cannot be set in pwikit.toml.

First start ​

Start the server:

sh
./pwikit serve

On macOS, start pwikit from an ordinary account. The bundled PostgreSQL does not run as root.

Running as root ​

On Linux pwikit also runs as root. PostgreSQL itself still refuses root, so pwikit starts it under another account:

  • the account that owns pgdata/ or the data directory, when that is not root;
  • otherwise a system account named pwikit, created on the first start if it does not exist.

That account owns pgdata/ and the PostgreSQL log files. Everything else in the data directory stays with root. Every directory above the data directory must be open to that account, so a data directory under /root does not work; pwikit stops and says so. Install under /opt or /srv instead.

Running as a dedicated account ​

On Linux you can also create an ordinary account just for pwikit. pwikit and the bundled PostgreSQL both run as that account, the whole data directory belongs to it, and pwikit holds no root rights.

  1. Create the account and the data directory, and fetch pwikit as that account:

    sh
    sudo useradd --system --home-dir /srv/pwikit --shell /usr/sbin/nologin pwikit
    sudo mkdir /srv/pwikit && sudo chown pwikit: /srv/pwikit
    cd /srv/pwikit
    curl -fsSL https://github.com/WikitTeam/ProjectWikit/releases/latest/download/install.sh | sudo -u pwikit sh

    If you unpack a release yourself, put every file into /srv/pwikit and then run sudo chown -R pwikit: /srv/pwikit.

  2. Create the site and the administrator as that account. To import a Wikidot site, import it as that account too, before creating the administrator:

    sh
    sudo -u pwikit ./pwikit createsite -slug main -domain wiki.example.org -title "My Wiki" -headline "A Wikidot-compatible wiki"
    sudo -u pwikit ./pwikit admin create -name "Site Admin"
  3. Install the system service and name the account with -user. The service runs as that account and is allowed to listen on ports 80 and 443:

    sh
    sudo ./pwikit service install -user pwikit

Run later pwikit commands as that account too, for example sudo -u pwikit pwikit backup create. An ordinary account running pwikit serve in a terminal cannot listen on ports 80 and 443; see Cannot listen on port 80 or 443.

On the first start, pwikit writes pwikit.toml and sets up the bundled PostgreSQL, so the first start is noticeably slower than later starts. On every later start, pwikit applies the database changes a newer release brings.

Progress is written to the log, which goes to standard error unless -log-file is given. Until a site exists, every address shows the page No such site, which states that no site is bound to the address.

The bundled PostgreSQL accepts connections only from the same machine. On Linux and macOS it uses a socket file and opens no network port. On Windows it listens only on 127.0.0.1. The bundled PostgreSQL therefore needs no firewall change. It never uses port 5432. If another PostgreSQL already listens on port 5432, pwikit prints a notice explaining how to use that server instead, and leaves it untouched.

To stop pwikit, press Ctrl+C. pwikit stops its PostgreSQL before it exits. If pwikit was terminated abruptly, the next start first stops the PostgreSQL left behind by the earlier run.

Other commands, such as createsite and admin, use the same database. While pwikit serve is running, they connect to its PostgreSQL; otherwise they start the bundled PostgreSQL for as long as they run. On Linux and macOS, run them from the same account as pwikit serve.

Create the first site and administrator ​

createsite creates the database tables if they do not exist yet. If pwikit serve is running, leave it running and open a second terminal.

  1. Create the site:

    sh
    ./pwikit createsite -slug main -title "My Wiki" -headline "A Wikidot-compatible wiki" \
      -domain wiki.example.org -media-domain files.example.org
    OptionMeaning
    -slugSite identifier: letters, digits, - and _. Commands use it to identify the site.
    -titleSite title.
    -headlineSite subtitle.
    -domainHost name the pages are served on, without https:// or a path.
    -media-domainHost name uploaded files are served on. Defaults to -domain. A separate name keeps uploaded HTML files apart from the site's own pages.

    Replace the example names with your own. Names under example.org are reserved and never receive automatic HTTPS. To try pwikit on your own computer, use -domain localhost and open http://localhost:8080.

  2. Add content. Either write the starter pages with pwikit seed (see Command line), or import a Wikidot site as described in Importing from Wikidot. Import before creating the administrator: an imported account can then be taken over together with the pages and posts it wrote.

  3. Create the administrator:

    sh
    ./pwikit admin create -name "YourName"

    If no account has this name, pwikit asks for confirmation before creating a new one. It then asks for the password without displaying it. The account receives every right on every site of the instance.

  4. If the site's domain is a public domain, restart pwikit serve (press Ctrl+C and start it again) so that it switches to HTTPS. createsite prints a reminder in that case. See "Domains and HTTPS" below.

Sign in at /-/login on the site's domain. The admin panel is at /-/admin and is linked as Admin panel among the account links at the top of each page. See Site administration.

Domains and HTTPS ​

Automatic HTTPS ​

If none of the following is configured, pwikit decides at startup whether to serve HTTPS:

  • the HTTPS mode (-tls, PWIKIT_TLS, or mode in [tls])
  • the listen address (-listen, or listen in [server])
  • trusted proxies (-trusted-proxies, or trusted_proxies in [server])

When at least one site has a public domain or media domain, pwikit listens on ports 80 and 443 and obtains certificates from Let's Encrypt. Otherwise it serves plain HTTP on 127.0.0.1:8080.

The following names are not public and never trigger HTTPS:

  • IP addresses, and names that include a port
  • names without a dot, such as wiki
  • localhost, localdomain, local, test, example, invalid, internal, lan, home.arpa, example.com, example.net and example.org, and every name ending in one of them (such as wiki.test or files.example.org)

With automatic HTTPS:

  • Certificates are requested when the first HTTPS request for a name arrives, so the first visit to each name is slower. pwikit renews them before they expire.
  • Certificates are issued only for the domains and media domains of sites on this instance. HTTPS requests for any other name, including the machine's IP address, are refused.
  • Port 80 redirects to HTTPS and answers the certificate authority's validation requests.
  • Certificates are stored in secrets/certs.
  • Using Let's Encrypt means accepting its subscriber agreement.

Before the first start with HTTPS, make sure the DNS records of both the domain and the media domain point at the machine, and that ports 80 and 443 are reachable from the internet.

The choice between HTTP and HTTPS is made at startup. After binding a public domain to an instance that is serving plain HTTP, restart pwikit. Once pwikit serves HTTPS, domains bound later receive certificates without a restart.

To register a contact address with the certificate authority, set acme_email in [tls]. To obtain test certificates first, set acme_directory to the Let's Encrypt staging directory, https://acme-staging-v02.api.letsencrypt.org/directory. Browsers do not trust staging certificates. Before switching back, delete secrets/certs, or the staging certificates remain in use.

Using your own certificate ​

To use a certificate you obtain yourself, set the mode to file:

toml
[tls]
mode = "file"
cert = "/etc/ssl/wiki/fullchain.pem"
key = "/etc/ssl/wiki/privkey.pem"

pwikit listens on port 80, which redirects to HTTPS, and on port 443. The same certificate is presented for every name, so it must cover the domain and media domain of every site. Both files are PEM files; cert holds the full certificate chain.

To renew, replace the files. pwikit notices the change within about a minute, without a restart. If the new files cannot be loaded, pwikit logs an error and keeps using the previous certificate. If the files cannot be loaded at startup, pwikit does not start.

Behind a reverse proxy ​

When another web server such as nginx handles HTTPS in front of pwikit, set the trusted proxies. This turns automatic HTTPS off, and pwikit serves plain HTTP on 127.0.0.1:8080 unless listen says otherwise:

toml
[server]
listen = "127.0.0.1:8080"
trusted_proxies = ["127.0.0.1", "::1"]

The proxy must:

  • pass the original Host header unchanged, because pwikit chooses the site by host name;
  • set X-Forwarded-For and X-Forwarded-Proto.

pwikit accepts X-Forwarded-For and X-Forwarded-Proto only from the addresses in trusted_proxies. If the proxy's address is not listed, every visitor appears to come from the proxy, and links in emails start with http:// even when visitors use HTTPS. A minimal nginx configuration:

nginx
server {
    listen 443 ssl;
    server_name wiki.example.org files.example.org;
    ssl_certificate     /etc/ssl/wiki/fullchain.pem;
    ssl_certificate_key /etc/ssl/wiki/privkey.pem;
    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

client_max_body_size raises nginx's own limit on request size, which otherwise blocks larger uploads.

Using Cloudflare ​

When a DNS record is proxied through Cloudflare (the orange cloud), Cloudflare sits between visitors and pwikit. pwikit can still use automatic HTTPS, with the following points in mind.

The SSL/TLS encryption mode must be Full (strict). In Flexible mode, Cloudflare connects to pwikit's port 80 over HTTP, pwikit redirects that request to HTTPS, and the browser ends up in a loop reporting too many redirects (ERR_TOO_MANY_REDIRECTS). In Full (strict) mode, Cloudflare connects to port 443 and verifies the certificate pwikit obtained from Let's Encrypt.

Set the mode for pwikit's names only. If other websites under the same Cloudflare domain only work in Flexible mode, the zone-wide setting can stay as it is. Add a rule in Cloudflare that sets the encryption mode to Full (strict) for the site's domain and media domain only.

Obtaining the first certificate. The certificate authority validates the domain over port 80, and Cloudflare forwards that request to pwikit, so the proxy can stay on. If pages show error 525 or 526 after switching to Full (strict), pwikit has not obtained a certificate yet. Set the DNS record to DNS only (the grey cloud) for a moment, open the site by its domain once, and turn the proxy back on after pwikit has its certificate.

Visitor addresses. With the proxy on, every request comes from a Cloudflare address. To see the real visitor addresses in logs, bans and sign-in records, list Cloudflare's ranges as trusted proxies and set the HTTPS mode explicitly, because setting trusted proxies otherwise turns automatic HTTPS off:

toml
[tls]
mode = "auto"

[server]
trusted_proxies = [
  "173.245.48.0/20", "103.21.244.0/22", "103.22.200.0/22", "103.31.4.0/22",
  "141.101.64.0/18", "108.162.192.0/18", "190.93.240.0/20", "188.114.96.0/20",
  "197.234.240.0/22", "198.41.128.0/17", "162.158.0.0/15", "104.16.0.0/13",
  "104.24.0.0/14", "172.64.0.0/13", "131.0.72.0/22",
  "2400:cb00::/32", "2606:4700::/32", "2803:f800::/32", "2405:b500::/32",
  "2405:8100::/32", "2a06:98c0::/29", "2c0f:f248::/32",
]

These ranges come from https://www.cloudflare.com/ips/. Cloudflare adds ranges from time to time, so check that page.

Changing a domain later ​

Change the domain and media domain in the admin panel under Site settings, in the fields Domain and Media domain, described in Site administration. If the admin panel cannot be reached at the stored domain, use pwikit site rebind, described in Command line. If -media-domain is omitted, site rebind sets the media domain to the same name as the domain.

Running as a system service ​

pwikit service install registers pwikit to start whenever the machine boots, and starts it immediately. Everything after -- is passed to pwikit serve:

sh
sudo ./pwikit service install -- -upload-limit 20GB
  • The service runs the executable from the location it has when you install. Moving pwikit afterwards needs a new registration; see Moving an instance.
  • Install also makes pwikit runnable by name from any directory; see Running pwikit by name. -no-path skips that.
  • Install also registers the task that looks for and installs new releases; see Updating and rolling back.
  • The data directory in effect at installation is written into the service.
  • Environment variables are not passed to the service. Put settings in pwikit.toml, or after --.
  • Install checks the options after -- and reads pwikit.toml. A mistake in either stops the installation.
  • pwikit service print shows what install would register, without registering anything.
  • To install a second instance on the same machine, give it its own data directory and ports, and a different name with -name.

Starting, stopping, checking and removing the service are described in Operations.

Linux ​

Run install with sudo. The machine must use systemd.

  • The service runs as the account sudo was run from, or as the account named with -user. Installed by root without either, it runs as root, and the bundled PostgreSQL runs as described in Running as root.
  • The data directory, and pgdata/ if it exists, must belong to that account. Every directory above the data directory must be accessible to it, so a data directory under /root does not work. Install stops and explains how to fix either problem, for example with sudo chown -R wiki: /opt/pwikit.
  • The service restarts after a failure and is allowed to listen on ports 80 and 443.
  • Its log goes to the system journal. Follow it with journalctl -u pwikit -f.
  • Run other pwikit commands as the service account, for example sudo -u wiki ./pwikit createsite ....

macOS ​

  • With sudo, pwikit is installed as a launch daemon in /Library/LaunchDaemons. It starts when the machine boots and runs as the account sudo was run from, or as the account named with -user.
  • Without sudo, pwikit is installed as a launch agent in ~/Library/LaunchAgents. It starts when you log in, and cannot start while nobody is logged in.
  • Manage a service installed with sudo using sudo, and one installed without sudo without it.
  • Its log is logs/pwikit.log, and crash output goes to logs/pwikit-stderr.log.

Windows ​

Run install from a terminal opened with Run as administrator:

powershell
.\pwikit.exe service install
  • The service runs under the virtual account NT SERVICE\pwikit, which is given modify access to the data directory.
  • Its log is logs\pwikit.log. If it stops with an error, the error is also recorded in the Windows Event Log.

Firewall changes made by install ​

SystemChange
LinuxIf firewalld or ufw is active, install opens the TCP ports pwikit listens on that are not already open. Uninstall closes only the ports install opened.
macOSIf installed with sudo and the application firewall is on, pwikit is allowed through. Uninstall removes it.
WindowsAn inbound rule named ProjectWikit allows connections to pwikit on all network profiles. Uninstall deletes it. If the rule cannot be added, install prints a warning and continues.

On Linux, the ports are derived from the options after -- and from pwikit.toml. If none of the HTTPS mode, listen address and trusted proxies is set, install opens ports 80 and 443, because it cannot yet tell whether a public domain is bound. Addresses on 127.0.0.1, ::1 or localhost are never opened. After changing the ports, reinstall the service to update the firewall.

Firewalls outside the machine, such as a cloud provider's security groups or a router, are not changed.

Running pwikit by name ​

Typing pwikit from any directory works only after either of the following. Until then, run commands from pwikit's own directory as ./pwikit (.\pwikit.exe on Windows). Linux and macOS look for commands only in the directories on PATH, and the current directory is not one of them.

  • pwikit service install. Installing the service does this as well, unless -no-path is given.
  • pwikit path install, for an instance that does not run as a system service.

On Windows, open a new terminal afterwards. A command run as pwikit still uses the data directory next to the executable, whatever directory it is run from. What changes on each system, and the other path subcommands, are described in Command line.

Moving an instance ​

Everything an instance holds sits in its data directory: the executable, the database, uploaded files, secrets and settings. Moving to another disk, another path or a renamed folder is moving this one directory.

The system service and the pwikit command both record absolute paths, so they must be registered again after a move, or the service does not start.

  1. Stop and unregister the service. This also removes the pwikit command:

    sh
    sudo pwikit service uninstall
  2. Move the data directory. pwikit must be stopped while it moves.

  3. From the new location, register the service again. This also recreates the pwikit command:

    sh
    sudo ./pwikit service install
  4. For an instance that does not run as a system service, run this in the new location instead:

    sh
    ./pwikit path install
  • Options given after -- when the service was installed are not kept. Give them again in step 3.
  • On Linux, the new directory and every directory above it must be reachable by the service account, as for the first installation.
  • If the service was not unregistered before the move, the pwikit command no longer works. From the new location, run sudo ./pwikit service uninstall first and then step 3; the link that leads to the old location is replaced on its own. An instance that does not run as a system service only needs step 4.
  • On Windows, run these commands in a terminal opened with Run as administrator, then open a new terminal.
  • If the data is kept apart from the executable with -data-dir, give the new -data-dir in step 3.

Using Docker ​

ProjectWikit is also published as the container image ghcr.io/wikitteam/pwikit. The image carries no PostgreSQL; docker/compose.yaml in the repository runs the official PostgreSQL image next to it. The first start generates a random database password and keeps it in the secrets volume, so no file needs editing:

sh
curl -fsSLO https://raw.githubusercontent.com/WikitTeam/ProjectWikit/main/docker/compose.yaml
docker compose up -d

pwikit serves plain HTTP on port 8080 of the host. Create the site and the administrator:

sh
docker compose run --rm pwikit createsite -slug main -title "My Wiki" -headline "A Wikidot-compatible wiki" -domain wiki.example.org -media-domain files.example.org
docker compose run --rm pwikit admin create -name "YourName"
docker compose run --rm pwikit seed
docker compose restart pwikit
VolumeHolds
datapwikit's data directory: pwikit.toml, files/, secrets/, logs/, backups/
pgdataThe PostgreSQL database
secretsThe database password
  • Put settings in pwikit.toml in the data volume, or as environment variables under environment in compose.yaml; see Configuration.
  • Change the port with the PWIKIT_PORT environment variable, such as PWIKIT_PORT=9000 docker compose up -d.
  • pwikit in the container does not handle HTTPS. Put a reverse proxy in front and set trusted_proxies as in Behind a reverse proxy.
  • pwikit in the container is not updated automatically. Run docker compose pull and docker compose up -d to update; the new release applies its database migrations on start.
  • Back up with commands such as docker compose run --rm pwikit backup create. Backups go to backups/ in the data volume.

To build the image yourself:

sh
docker build -t pwikit --build-arg VERSION=v1.0.0 .
PWIKIT_IMAGE=pwikit docker compose -f docker/compose.yaml up -d

Using your own PostgreSQL ​

To use a PostgreSQL server you run yourself, give pwikit a connection string in one of these ways (the first one found wins):

  1. the -database option
  2. the DATABASE_URL environment variable
  3. database in pwikit.toml
toml
database = "postgres://pwikit:password@127.0.0.1:5432/pwikit"

Special characters in the password must be percent-encoded. The setting in pwikit.toml also applies to the other commands and to the system service.

Requirements:

  • PostgreSQL 14 or newer. With an older server, pwikit refuses to start and explains how to move the data.
  • The database must exist; pwikit does not create it. On the first start, pwikit creates its tables and the citext and pg_trgm extensions. Both extensions ship with PostgreSQL's standard contrib modules, which some Linux distributions package separately.
  • The account pwikit connects as must be allowed to create tables and those extensions. Making it the owner of the database is sufficient:
sql
CREATE ROLE pwikit LOGIN PASSWORD 'change-me';
CREATE DATABASE pwikit OWNER pwikit ENCODING 'UTF8' TEMPLATE template0;

With your own database, pwikit creates no postgres/ or pgdata/.

To move an existing installation of the Python release of ProjectWikit, see Migrating from the Python release.

Mail ​

pwikit sends mail for email address verification, email address changes, password resets, password change notices and invitations sent from the admin panel. Until a mail server is configured, these messages are written to the log instead of being sent. Links in these messages consist of the site's domain and the scheme of the request that caused the message. They start with https:// when pwikit serves HTTPS, or when a proxy listed in trusted_proxies reports HTTPS in X-Forwarded-Proto; otherwise they start with http://. The sign-in cookie is limited to HTTPS connections under the same condition.

Configure the mail server in the [mail] section of pwikit.toml:

toml
[mail]
host = "smtp.example.net"
port = 587
username = "wiki@example.net"
password = "..."
use_tls = true
from = "wiki@example.net"

All mail settings are described in Configuration.

Development mode ​

To try pwikit on your own computer, start it in development mode:

sh
./pwikit serve -dev

In development mode, pwikit:

  • serves plain HTTP on 127.0.0.1:8080, even when a site is bound to a public domain;
  • ignores the HTTPS mode, listen address and trusted proxies from pwikit.toml and environment variables;
  • applies all other settings, such as the database and mail, as usual.

To use another port, pass it with -listen: -listen 9000 and -listen :9000 both listen on 127.0.0.1:9000. An address other machines can reach, such as 0.0.0.0:9000, is rejected, as is -tls=auto or -tls=file.

pwikit chooses the site by the host name in the browser's address bar, so a site is reachable in development mode only through a name that resolves to this machine, such as localhost.

Troubleshooting ​

Error messages are printed with the prefix pwikit:.

The bundled PostgreSQL will not run as root ​

text
pwikit: the bundled PostgreSQL will not run as root.

This happens on macOS. Start pwikit from an ordinary account. To run it at boot, install it as a service with sudo; the service runs as the account sudo was run from. When a service is installed, run other commands as its account with sudo -u <account>.

The bundled PostgreSQL cannot enter the data directory ​

text
pwikit: the bundled PostgreSQL runs as pwikit, which cannot enter /root.

pwikit runs as root on Linux and starts PostgreSQL under another account, which cannot reach a data directory inside a closed directory such as /root. Move the pwikit directory to /opt or /srv, then start it again. See Running as root.

The data in pgdata/ was written by another PostgreSQL version ​

text
pwikit: the data in pgdata/ was written by PostgreSQL 17, and this pwikit carries PostgreSQL 18.

The pwikit you started carries a different major version of PostgreSQL than the one that created the database. Nothing was started or changed. Follow the three steps in the message: create a backup with the previous pwikit, move pgdata/ aside and start the new pwikit, then restore the backup. See Operations.

Cannot listen on port 80 or 443 ​

text
pwikit: listen on :80 for http: listen tcp :80: bind: permission denied. Grant the binary CAP_NET_BIND_SERVICE, ...

On Linux, ordinary accounts cannot listen on ports below 1024. Use one of these:

  • Install pwikit as a system service, which is allowed to use these ports.
  • Allow the executable to use them: sudo setcap cap_net_bind_service=+ep ./pwikit. Repeat this after replacing the executable.
  • Put pwikit behind a reverse proxy, as described in "Behind a reverse proxy".

A port is already in use ​

text
pwikit: listen on :443 for https: listen tcp :443: bind: address already in use

The rest of the message depends on the operating system. Another program, often a web server or a second pwikit, is using the port. Stop that program, or run pwikit behind it as described in "Behind a reverse proxy".

The bundled PostgreSQL is already in use ​

text
pwikit: pwikit serve, process 1234, is already running the bundled PostgreSQL in this directory
pwikit: a PostgreSQL from /usr/lib/postgresql/18/bin/postgres is running on /opt/pwikit/pgdata as process 1234. Stop it before starting pwikit

Only one program at a time can use the bundled PostgreSQL in a data directory. Stop the running pwikit serve, or the other PostgreSQL using pgdata/, then start pwikit again.

  • If the message says another pwikit command, a command such as backup is still running; wait for it to finish.
  • If the message says pwikit serve holds the bundled PostgreSQL but it is not ready yet, pwikit serve is still starting; run the command again shortly.
  • If the message says that pgdata holds files but no PostgreSQL data, move those files somewhere else and start pwikit again.

pwikit.toml has settings pwikit does not know ​

text
pwikit: /opt/pwikit/pwikit.toml has settings pwikit does not know: server.lisen

A key in pwikit.toml is misspelled or in the wrong section. pwikit does not start until it is corrected. The valid keys are listed in Configuration.

This pwikit was built without a PostgreSQL of its own ​

text
pwikit: this pwikit was built without a PostgreSQL of its own and found none in /opt/pwikit/postgres.

This build of pwikit does not include PostgreSQL. Use your own PostgreSQL as described in "Using your own PostgreSQL", or use a build that includes it.

If the message says the bundled PostgreSQL is incomplete instead, files are missing from postgres/. Delete the postgres directory and start pwikit again; it unpacks PostgreSQL anew. The database in pgdata/ is not affected.

Pages have no styles or scripts ​

text
WARN this build carries no page assets and -static-dir is not set, so pages are served without styles and scripts

This build of pwikit does not include the page assets. Use a build that includes them, or pass -static-dir with the path of ProjectWikit's static directory.

PostgreSQL stopped while pwikit was serving ​

pwikit stops as well and prints the last lines PostgreSQL wrote. The full PostgreSQL logs are in logs/. A system service restarts pwikit, and PostgreSQL with it.

The database has applied a change this build does not carry ​

text
pwikit: the database was upgraded by pwikit v1.1.0, which applied 0011_example.sql; this pwikit (v1.0.0) cannot run on that schema. Run pwikit v1.1.0 or a newer release, or restore a backup taken before the upgrade

A newer pwikit changed this database in a way older releases cannot run on. Run the release the message names, or restore a backup from before the upgrade; see Older releases and the database.

A page says no site is bound to the address ​

The host name in the browser does not match the domain or media domain of any site. List the sites and their domains with pwikit site list, and check that the DNS records point at this machine.

HTTPS does not work ​

  • Check that the name is the domain or media domain of a site on this instance.
  • Check that its DNS record points at this machine and that ports 80 and 443 are reachable from the internet.
  • Open the site by its domain name, not by IP address.
  • Look in pwikit's log for TLS handshake errors, which contain the reason a certificate could not be obtained.

The browser reports too many redirects ​

The domain is proxied through Cloudflare with the SSL/TLS encryption mode set to Flexible. Set the mode for pwikit's names to Full (strict); see Using Cloudflare.