NarraLeaf

Deploying a server

Running a NarraLeaf Team server in a container or from npm, and the two ports it needs.

A NarraLeaf Team server runs on one machine and keeps everything it owns under one directory. The container image is the shorter path and carries everything it needs.

With Docker

Write a compose.yaml. The one value to change is the name people will reach the server by.

services:
  team:
    image: ghcr.io/narraleaf/team:0.1.0
    restart: unless-stopped
    environment:
      NLTEAM_HOSTNAME: team.example.com
    ports:
      - "41402:41402"
      - "41337:41337/tcp"
      - "41337:41337/udp"
    volumes:
      - team:/var/lib/nlteam
volumes:
  team:

Start the server

docker compose up -d

Nothing is downloaded on first start. The image carries the version-control server already unpacked.

Create the first account

Write the password to a file first, holding that password and nothing else. It must be ten characters or more.

printf '%s' 'a password of your own' > admin-password
docker compose exec -T team nlteam init ada < admin-password
rm admin-password

init runs once. It creates the first account, puts it in the admin group, and is refused from the moment the server has an account. It reads the password from a file rather than from an argument, which would appear in the process list and in the shell history.

Read the address and the fingerprint

docker compose exec team nlteam status

The sign in line carries the address, and the line below it the server's certificate fingerprint. Each person who connects compares that fingerprint once, so send it over something other than the connection they are about to trust.

Three things now reach the people who will use the server: the address, an account, and that fingerprint. Everything else is done from Studio.

The address is a host and a port, written nlteam://team.example.com:41402. status prints it as an https:// URL, which is the endpoint Studio signs in at rather than the address to hand out; Studio does not accept that spelling.

Without Docker

The package is not published yet. Build nlteam from a checkout:

git clone https://github.com/NarraLeaf/NarraLeaf-Team.git
cd NarraLeaf-Team
npm install && npm run build && npm link
nlteam up --root /srv/team --hostname team.example.com

up installs the version-control server, configures it, starts it, and runs until it is interrupted. Run the rest in a second terminal.

printf '%s' 'a password of your own' | nlteam init ada --root /srv/team
nlteam status --root /srv/team

Node.js 24 or newer is required, on 64-bit Linux, Windows, or Apple silicon.

Ports

PortReachable from an author's machineCarries
41402YesSign-in, and the session Studio holds
41337Yes, TCP and UDPProject data
41339NoThe version-control server's health check
41400NoThe server's signing keys

Publish both halves of 41337. A connection that settles on QUIC uses UDP, and a deployment that opens TCP alone leaves such a client waiting.

The other two listeners are bound to the loopback and are unreachable from another machine whatever a firewall allows.

A certificate you already hold

An organization that holds a certificate for the name people use gives it to the server, and nobody compares a fingerprint: the issuer is already trusted on each machine.

    environment:
      NLTEAM_HOSTNAME: team.example.com
      NLTEAM_TLS_CERT: /etc/nlteam/tls/fullchain.pem
      NLTEAM_TLS_KEY: /etc/nlteam/tls/privkey.pem
    volumes:
      - team:/var/lib/nlteam
      - ./tls:/etc/nlteam/tls:ro

Both values or neither, and the key without a passphrase. Renewal is a restart.

Backups

/var/lib/nlteam, or the directory --root names, holds the accounts, the projects, the signing keys, the certificate authority, and the repository store. Back up that directory and the server is backed up.

Losing it means every machine that trusted this server has to be told to trust its replacement.

Full reference

The repository's deployment documentation covers every command and every setting.

On this page