N Nightship
Guides / Running a server
// running a server

Run nightshipd with Docker

The recommended way to run a shared server. The official image is published on the GitHub Container Registry, so the host needs nothing but Docker. Use Compose for a real deployment behind HTTPS, or the Docker Desktop GUI to evaluate on a single machine.

The official image is ghcr.io/nightship-io/nightshipd.

It runs --data-dir /data --port 8080 on its own, so the only thing you must provide is a persistent volume for /data. A Docker Hub mirror is published as nightshipio/nightshipd for Docker Desktop’s search bar.

This is the same server Drydock runs for its nightshipd part — Drydock just wires it up automatically (and adds bundled storage) for a one-click local demo. Here you set it up yourself, for a real deployment.

Compose (a real shared server, behind HTTPS)

This is the recommended setup for a server other people use. It runs nightshipd behind Caddy, which fetches and renews a Let’s Encrypt certificate automatically. Caddy is just a sensible default — swap it for nginx, Traefik, or your existing ingress; nightshipd only speaks plain HTTP and doesn’t care what is in front of it. (More in Terminate TLS with a reverse proxy (Caddy).)

1. Compose file

Save this as docker-compose.yml:

services:
  nightshipd:
    image: ghcr.io/nightship-io/nightshipd:latest
    restart: unless-stopped
    volumes:
      - nightship-data:/data      # persistent: users, tokens, builds

  caddy:
    image: caddy:2
    restart: unless-stopped
    ports: ["80:80", "443:443"]
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    depends_on: [nightshipd]

volumes:
  nightship-data:
  caddy-data:
  caddy-config:

And a Caddyfile next to it — point the domain’s DNS record at this host first:

builds.example.com {
    reverse_proxy nightshipd:8080
}

2. Bootstrap the first admin

A fresh server has no accounts. Mint an admin token before starting the stack — these one-shot commands write into the same data volume the server uses:

docker compose run --rm nightshipd user create admin --role admin --data-dir /data
docker compose run --rm nightshipd token create my-laptop --user admin --data-dir /data

The second command prints a token once — copy it. Full detail, and the other ways to bootstrap, are in Bootstrap the first admin.

3. Bring it up

docker compose up -d

Then in the desktop app: Servers → Add server → https://builds.example.com, and Set token with the value from above. To update later: docker compose pull && docker compose up -d (see Upgrade nightshipd).

Prefer not to use containers? The bare-metal systemd setup runs the same server straight from the binary.

Docker Desktop (GUI, no terminal)

Prefer not to touch a command line? You can run the same official image entirely through the Docker Desktop interface. This is ideal for evaluating on a single machine; for a shared, internet-facing server use the Compose setup above so you get HTTPS in front.

Nearly everything happens in Docker Desktop’s own windows. The one exception is minting the first admin token — that has no button anywhere (local access to the data directory is the root of trust, by design), but Docker Desktop’s built-in Exec tab runs it without you opening a separate terminal.

1. Find and pull the image

Use Docker Desktop’s search bar (it searches Docker Hub) for nightshipio/nightshipd — the Docker Hub mirror of the canonical ghcr.io/nightship-io/nightshipd — and pull the latest tag.

2. Run it

On the image, click Run → Optional settings and set:

Click Run. The container should report healthy within a few seconds and show its port as <your-port>:8080.

3. Confirm it’s up

Open http://localhost:<your-port>/api/version in a browser — you should see a small JSON response with the version.

4. Bootstrap the first admin

Click the running nightshipd container, open its Exec tab (labelled Terminal in some versions), and run these two lines. Because this shell is inside the running server, it writes straight into the same /data the server reads — there is no separate volume to get wrong:

nightshipd user create admin --role admin --data-dir /data
nightshipd token create my-laptop --user admin --data-dir /data

The second command prints a token once — copy it.

5. Connect the app

In the desktop app: Servers → Add server → http://localhost:<your-port>, then Set token with the value from step 4. The Admin page loads and you are running a Docker-hosted server from the UI.

Two things to keep straight, both easy to trip over. The token must land in the volume the server actually reads — minting it from the container’s Exec tab guarantees that. If you instead bootstrap with a separate docker run one-shot, it must mount the exact same named volume (nightship-data): a bare docker run -v nightship-data:/data and a Compose-managed volume (<project>_nightship-data) are different volumes, and a token written to the wrong one produces 401 even though it reported “created”. And inside the Exec tab the server is on 8080 — the container’s own port, not the host port you published; use the host port only from your browser and the app.

← All guides