Skip to content
runlot

Install with packages

The control plane and each data node as apt or dnf packages, from the files we send you or from the signed repository.

Two packages, runlot-cp and runlot-node, and a third, runlot-eval, that pulls both onto one machine with PostgreSQL and MinIO beside them. Every package carries the same install core, runlot-admin, which checks the machine, writes the configuration, and starts the services. The postinstall is that command; nothing happens in shell that you could not run yourself.

The repository

Debian, Ubuntu
curl -fsSL https://packages.runlot.io/gpg/runlot-archive-keyring.gpg \
  | sudo tee /usr/share/keyrings/runlot.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/runlot.gpg] https://<token>@packages.runlot.io/deb stable main" \
  | sudo tee /etc/apt/sources.list.d/runlot.list
sudo apt update
RHEL, Rocky
sudo tee /etc/yum.repos.d/runlot.repo <<'EOF'
[runlot]
name=Runlot
baseurl=https://<token>@packages.runlot.io/rpm/el/x86_64
gpgcheck=1
gpgkey=https://packages.runlot.io/gpg/runlot-archive-keyring.gpg
EOF

<token> comes with your licence. It decides who may download and nothing else: a package copied to a machine with no token installs the same way. Until the repository host is in service, we send the packages as a signed bundle instead, and the steps below are the same from the install line on. See Air-gap for checking the bundle.

The control plane

Put your values in site.env

Terminal
sudo mkdir -p /etc/runlot/license
sudo cp license /etc/runlot/license/license
sudo apt download runlot-cp && sudo dpkg --unpack runlot-cp_*.deb    # unpacks the example without configuring
sudo cp /usr/share/runlot/site.env.cp-example /etc/runlot/site.env
sudo chmod 0640 /etc/runlot/site.env
sudoedit /etc/runlot/site.env

The example is annotated. These are the keys with no default, and the only ones you must set:

KeyWhat it is
RUNLOT_MASTER_KEYopenssl rand -hex 32. We have no copy.
RUNLOT_DATABASE_URLyour PostgreSQL 18, as the role that owns the database
RUNLOT_OBJSTORE_ENDPOINT, _BUCKET, _ACCESS_KEY_ID, _SECRET_ACCESS_KEYyour object store
RUNLOT_CP_PRIVATE_ADDRthe private address the nodes reach the control plane at
RUNLOT_PUBLIC_URL, RUNLOT_ADMIN_HOSTthe dashboard's origin and host
RUNLOT_ADMIN_EMAILSthe platform operators. The first address is also the only one allowed to sign up without an invitation.
RUNLOT_APP_DOMAIN, RUNLOT_WIRE_DOMAIN, RUNLOT_GIT_DOMAINyour names from Requirements

Install

Debian, Ubuntu
sudo apt install runlot-cp
RHEL, Rocky
sudo dnf install runlot-cp

The postinstall runs runlot-admin preflight cp, then runlot-admin install cp, then starts the services. It prints the dashboard URL and the join token for the nodes.

If a check fails, it fails before anything is changed and names the value. Fix site.env and resume:

Debian, Ubuntu
sudo dpkg --configure -a
RHEL, Rocky
sudo /opt/runlot/bin/runlot-admin install cp --etc /etc/runlot --state /var/lib/runlot

The two differ because a failing rpm postinstall does not abort the transaction. On RHEL the package is installed and nothing is running, and the install core is run again by hand.

Each data node

Put your values in site.env

Terminal
sudo cp /usr/share/runlot/site.env.node-example /etc/runlot/site.env
sudoedit /etc/runlot/site.env
KeyWhat it is
RUNLOT_NODE_IDunique in the installation; the certificate and the lease carry it
RUNLOT_CP_PRIVATE_ADDRthe control plane's private address
RUNLOT_NODE_JOIN_TOKENprinted by the control plane's postinstall
RUNLOT_PRIVATE_ADDRthis machine's private address
RUNLOT_FRONT_TLS_CERT, _KEYyour *.apps certificate, or leave RUNLOT_FRONT_TLS_ADDR empty and terminate in your own proxy
RUNLOT_WIRE_HOSTSthe names on the wire certificate: *.wire.acme.example,*.apps.acme.example

Install

Terminal
sudo apt install runlot-node      # or: sudo dnf install runlot-node

The join token authenticates exactly two calls: one that fetches the CA certificate and the shared values a node cannot derive, and one that enrols the node's own certificate from a key generated on the node. The CA private key never leaves the control plane, and nothing is copied between machines by hand.

The runtime artifact, the sandbox every project runs in, is inside the package. It is about 1 GB, which is why the node package is large.

Declare where the node is

A node never asserts its own region or country: registration is authenticated by the node, so a node declaring its own jurisdiction would be asserting the fact that constrains it. You declare it from the control plane once the node has registered:

On the control plane
sudo /opt/runlot/bin/runlot-admin bootstrap --nodes node-1=icn/KR/do,node-2=fsn/DE

do marks a node able to hold Durable Objects. A project's first Durable Object deploy is refused until every active node is declared.

The eval machine

Terminal
sudo cp /usr/share/runlot/eval-site.env /etc/runlot/site.env
sudoedit /etc/runlot/site.env          # the master key; the join token after the control-plane half installs
sudo apt install runlot-eval

It depends on runlot-cp, runlot-node and the distribution's postgresql-18, and ships a MinIO unit. The MinIO binary is not redistributed: it is AGPL and the download is yours. Put it at /opt/runlot/bin/minio and systemctl enable --now minio; the postinstall says this when the file is absent.

One machine, one disk, loopback everything. It is not a production shape.

First login

  1. An address in RUNLOT_ADMIN_EMAILS signs up with email and password at the dashboard URL. Under the default RUNLOT_SIGNUP=invite, that is the only sign-up allowed; everyone else is invited from the dashboard.
  2. The operations console is the same origin split by Host, RUNLOT_ADMIN_HOST. There is no second address.
  3. Point the CLI at your installation and deploy something:
Terminal
runlot login --api https://runlot.acme.example
npm create runlot@latest hello && cd hello && runlot deploy

The project limits of the public plans do not apply. The only project ceiling on a self-hosted installation is the licence's max_projects, and the default is none.

On this page