Install the server
Complete the requirements and version selection first. Choose one deployment method below. Both start a single server with persistent storage, HTTPS on port 8080, and embedded NATS TLS on port 4222.
Replace pyplines.example.com with your actual server DNS name throughout. Provision a certificate covering that name, its private key, and the public CA certificate. The examples assume these files are available as tls/server.crt, tls/server.key, and tls/ca.crt in your installation directory.
Option A: Docker Compose
For guided setup of this deployment, see the installer. The instructions below describe manual provisioning.
On the server host, create a private installation directory, enter it, and place your provisioned TLS files in tls/. Create .env using the plain platform version selected in the overview:
mkdir -p pyplines-server/tls
chmod 700 pyplines-server pyplines-server/tls
cd pyplines-server
printf 'PLATFORM_VERSION=%s\n' "$PLATFORM_VERSION" > .env
The following complete Compose file runs only the server. It does not mount the Docker socket or start a runner:
name: pyplines-server
services:
server:
image: ghcr.io/pyplines/pyplines-server:${PLATFORM_VERSION:?Set PLATFORM_VERSION in .env}
command:
- start
- --data
- /data
- --listen
- :8080
- --tls-cert
- /certs/server.crt
- --tls-key
- /certs/server.key
- --nats-listen
- :4222
- --nats-url
- tls://pyplines.example.com:4222
ports:
- "8080:8080"
- "4222:4222"
volumes:
- server-data:/data
- ./tls:/certs:ro
restart: on-failure
stop_grace_period: 60s
volumes:
server-data:
name: pyplines-server-data
These port mappings listen on the host's interfaces. Restrict access through your host/network firewall as described in the network plan. Bind to a specific host address if your network layout requires it.
Create a bootstrap password file with at least 12 characters. This example generates one without placing the password in command arguments:
umask 077
openssl rand -base64 24 > bootstrap-password
test -s tls/server.crt && test -s tls/server.key
docker compose config --quiet
docker compose pull server
docker compose run --rm --no-deps \
-v "$PWD/bootstrap-password:/run/secrets/bootstrap-password:ro" \
server bootstrap --data /data --username admin \
--password-file /run/secrets/bootstrap-password
docker compose up -d server
docker compose ps
docker compose logs --tail 100 server
Bootstrap and the running server use the same server-data volume. Bootstrap creates the initial administrator only on an uninitialized installation. Do not run another server against that volume. After successful login, retain the password in your credential manager and remove the bootstrap file; the running service does not need it.
Use docker compose stop server during planned maintenance and docker compose start server to restart it. The data survives container replacement. Do not use down --volumes or prune this volume on an installation you intend to retain.
Option B: Linux service
These commands target a Linux systemd host with sudo, GitHub CLI, and GNU checksum tools. Set PLATFORM_TAG and PLATFORM_VERSION from the overview, and select amd64 for x86-64 or arm64 for AArch64:
export ARCH=amd64
mkdir -p download/binaries
gh release download "$PLATFORM_TAG" --repo pyplines/pyplines \
--pattern "pyplines-server-linux-$ARCH" --dir download/binaries
gh release download "$PLATFORM_TAG" --repo pyplines/pyplines \
--pattern SHA256SUMS --dir download
(cd download && sha256sum --check --ignore-missing SHA256SUMS)
sudo install -m 0755 "download/binaries/pyplines-server-linux-$ARCH" /usr/local/bin/pyplines-server
pyplines-server version
The checksum file uses binaries/ paths, hence the download layout above. Confirm the reported version matches the selected platform release. Use a new download directory for a different release.
Create a dedicated account and install your TLS material:
sudo useradd --system --home-dir /var/lib/pyplines --shell /usr/sbin/nologin pyplines-server
sudo install -d -o pyplines-server -g pyplines-server -m 0700 /var/lib/pyplines
sudo install -d -o root -g pyplines-server -m 0750 /etc/pyplines
sudo install -o root -g pyplines-server -m 0640 tls/server.crt /etc/pyplines/server.crt
sudo install -o root -g pyplines-server -m 0640 tls/server.key /etc/pyplines/server.key
Create and provision the administrator password before starting the service:
umask 077
openssl rand -base64 24 > bootstrap-password
sudo install -o pyplines-server -g pyplines-server -m 0600 bootstrap-password /etc/pyplines/bootstrap-password
sudo -u pyplines-server /usr/local/bin/pyplines-server bootstrap \
--data /var/lib/pyplines --username admin \
--password-file /etc/pyplines/bootstrap-password
Save this unit as /etc/systemd/system/pyplines-server.service:
[Unit]
Description=Pyplines server
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=pyplines-server
Group=pyplines-server
StateDirectory=pyplines
StateDirectoryMode=0700
UMask=0077
ExecStart=/usr/local/bin/pyplines-server start \
--data /var/lib/pyplines \
--listen :8080 \
--tls-cert /etc/pyplines/server.crt \
--tls-key /etc/pyplines/server.key \
--nats-listen :4222 \
--nats-url tls://pyplines.example.com:4222
Restart=on-failure
RestartSec=5s
TimeoutStopSec=60s
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now pyplines-server
sudo systemctl status pyplines-server
sudo journalctl -u pyplines-server -n 100 --no-pager
After successful login, store the password in your credential manager and remove both bootstrap password files. Use sudo systemctl stop pyplines-server for planned maintenance. The service's data remains in /var/lib/pyplines.
Check HTTPS and log in
From a workstation that can reach the server:
curl --fail --cacert ./tls/ca.crt https://pyplines.example.com:8080/health
python3 -m venv .venv
source .venv/bin/activate
python -m pip install "pyplines-cli==$TOOLING_VERSION"
pyplines config set tls.ca_file "$PWD/tls/ca.crt"
pyplines login https://pyplines.example.com:8080 --username admin
Copy only the public CA certificate to that workstation. Omit --cacert and the extra CLI CA setting when system trust already covers your certificate. Login prompts for the bootstrap password. /health confirms that the HTTP service responds; it does not prove that a runner can execute an Action.
If startup fails, check certificate/key readability, hostname coverage, the data directory's ownership, and port availability. A lock error means another server process may already own that data directory. The HTTPS service will not start if embedded NATS fails to start.
Continue with Install a runner. Full flags, environment variables, and persistence details are in Server configuration.

