Skip to content

Requirements

Badlen is under active development: what you install from these pages is built from the current sources and moves as they do.

Docker with Docker Compose, and a few minutes for the first build. There is no runtime to install, no database to set up by hand and no web server to configure; what the machine itself has to be is the section below.

Any 64-bit Linux host that runs Docker. The two images the stack is built on, node:24-alpine and postgres:18-alpine, are both published for amd64 and arm64, so an ordinary x86 server and a 64-bit ARM board (a Raspberry Pi on a 64-bit system, an ARM NAS) each qualify. A 32-bit ARM system does not: the application’s base image has no build for it.

Memory is asked for by the build rather than by the running stack. Measured on a two-core machine: compiling the interface peaked near 800 MB in one process and compiling the API near 660 MB, while the application afterwards sits around 225 MB and an idle PostgreSQL around 50 MB. Those are figures from one machine rather than a certified minimum, and what they settle is the order of magnitude: hundreds of megabytes to run, close to a gigabyte to build. The build is the floor, not the service.

The stack is two containers. One is PostgreSQL 18. The other is the application, which serves the compiled interface and its API from the same origin, so there is one image, one process and one address to put behind a reverse proxy, with no CORS arrangement to make, since the session cookie never crosses an origin.

The application applies its own pending migrations before it accepts a single request. Nothing else has to be run against the database, on the first start or on any later one.

The first docker compose up -d --build builds the image from the sources, which on a small home machine is minutes rather than seconds, most of it the interface being compiled. Every start after that answers in about fifteen seconds.

The built image is close to 800 MB, and every later update builds another one beside it. Updating says what becomes of the one it replaced.

There is no published image: the stack builds from a clone of the repository, which Docker Compose takes as its first step along with the four commands that follow it. That page is the one procedure; nothing here has to be run.

A source archive downloaded without git history works too: the version the instance reports comes from the VERSION file committed in the repository, which the image carries, rather than from a tag.

Running the self-hosted stack next to a development checkout of the same repository is safe. Both compose files declare a service called db, but each one pins its own project name (badlen for the self-hosted stack, badlen-dev for the development one), so compose tells the two apart by project plus service and neither replaces the other’s containers or volume.

No service pins a container_name, which is deliberate: that name is global to the Docker daemon rather than scoped to a project, so one pinned here would cap the machine at a single stack whatever -p said.

Next: Configuration, the three secrets that have to be set before the first start.

Privacy