Skip to content
How to install

How WPL7 works

WPL7 is a set of containers on each server, and a panel that manages them. This page explains the parts and how they fit, so the rest of the docs make sense.

Each site runs in a container of its own, named wp-<slug> after the site’s slug. Its image is the official WordPress image with Apache, plus WP-CLI and a mail client. Each site picks a PHP version, 8.2 to 8.5 by default, and can switch later.

The site’s files are in /srv/sites/<slug>/wordpress on its server. Its database and database user live on the server’s shared MariaDB, one pair per site.

Each site also has a Docker network of its own. Its only other members are Traefik, the mail relay and MariaDB, so a site cannot reach another site or the panel. A second, shared network gives sites a way out to the internet for updates, with traffic between containers dropped. Every site container runs with Linux capabilities removed, without privilege escalation, and under the CPU, memory and process limits set in Settings → Sites.

WordPress’s own cron is switched off. The panel runs each site’s due cron events every five minutes instead. Mail from wp_mail() goes to the server’s relay with the site’s own login, so a site cannot send as another site’s domain.

Traefik answers on ports 80 and 443 and sends each request to the right site container. It finds the containers by their labels, so adding a site regenerates nothing. Certificates come from Let’s Encrypt. Each hostname gets one on its first request, unless the server holds a wildcard certificate for its dev sites.

Every site starts on its dev domain, such as northwind-bakery.dev.example.com. It works at once, because a wildcard DNS record points the whole dev domain at the server. Going live adds the customer’s domains and makes the first one the site’s address. The others redirect to it, and so does the dev address if you keep it.

The panel is one Node process in a container on the first server. It keeps its state in a SQLite database, /srv/panel/panel.db. It drives Docker through the Docker socket, and other servers over SSH with a key of its own. That makes the panel root-equivalent on every server it manages. Protect its accounts and API keys like a root password.

Work that changes a site runs as a job with a log: creating a site, going live, a move, a backup, an update. Each server runs one job at a time, and the rest wait their turn. A job that fails part-way undoes what it can and says what went wrong. Some work runs in a lane of its own, such as offsite uploads, so it does not hold up the server’s sites.

The first server runs the panel and hosts sites. Each further server is a worker: the same stack without the panel, driven over SSH. Every site lives entirely on one server, with its files, database, mail and certificates. A server that goes down takes only its own sites with it. The panel going down stops management, and the sites keep serving.

An install follows a channel, set as WPL7_CHANNEL in deploy/.env. Stable follows releases. Edge follows the rolling build of main, which gets every change first. The panel checks GitHub once an hour and offers a new version under Settings → Updates. An update replaces the panel container and rolls back if the new panel does not come up. Site containers keep running throughout.

Path What it holds
/opt/wpl7 The release bundle: compose files, scripts and deploy/.env.
/srv/sites/<slug> A site’s WordPress files and the configuration its container mounts.
/srv/backups Backups, unless a server keeps them somewhere else.
/srv/mysql MariaDB’s data.
/srv/panel The panel’s database and SSH key.
/srv/traefik Certificates and Traefik’s dynamic configuration.

Architecture has the full layout, the networks and the names.