Skip to content
Select theme
  • Auto
  • Dark
  • Light

Run the server

This page is for the server admin. It takes a server from nothing to production, in order. To try Telesphorepo on your own computer, Start the server and Sign in are enough.

For production, you need a host with Docker, Docker Compose or Podman, a DNS name that points at it, such as repo.example.com, and ports 80 and 443 open on its firewall.

Docker

  1. Start the server.

    Terminal window
    docker run -d --name telesphorepo -p 8080:8080 -v telesphorepo-data:/data -v telesphorepo-backups:/backups ghcr.io/telesphorepo/telesphorepo:latest
  2. Copy the admin password from the log.

    Terminal window
    docker logs telesphorepo

Docker Compose

  1. Save this as compose.yaml in a folder of its own.

    compose.yaml
    services:
    telesphorepo:
    image: ghcr.io/telesphorepo/telesphorepo:latest
    restart: unless-stopped
    ports:
    - "8080:8080"
    volumes:
    - telesphorepo-data:/data
    - telesphorepo-backups:/backups
    volumes:
    telesphorepo-data:
    name: telesphorepo-data
    telesphorepo-backups:
    name: telesphorepo-backups
  2. Start the server.

    Terminal window
    docker compose up -d
  3. Copy the admin password from the log.

    Terminal window
    docker compose logs telesphorepo

For production, Serve over HTTPS has a Compose file with Caddy in it.

Podman

  1. Start the server.

    Terminal window
    podman run -d --name telesphorepo -p 8080:8080 -v telesphorepo-data:/data -v telesphorepo-backups:/backups ghcr.io/telesphorepo/telesphorepo:latest
  2. Copy the admin password from the log.

    Terminal window
    podman logs telesphorepo

Download the program

  1. Download the telesphorepo-server file for your system from GitHub Releases.

  2. Unpack the file.

  3. Start the server, and copy the admin password that it shows.

    Terminal window
    ./telesphorepo-server serve

The data is in ./data, next to where you started it. Check a downloaded program against SHA256SUMS on the release page.

The server prints the password of the user admin once, on its first start. To pick the first admin yourself, set TR_BOOTSTRAP_ADMIN_USER and TR_BOOTSTRAP_ADMIN_PASSWORD on the first start. The server reads them only while it has no users.

Always keep the telesphorepo-data volume. It holds the database, the files and the key for your secret settings.

The server speaks plain HTTP on port 8080. Put a reverse proxy in front of it for HTTPS. Caddy gets a certificate from Let’s Encrypt and renews it for you.

Before you start, point a DNS name (repo.example.com below) at the host, and open ports 80 and 443 on its firewall: Caddy needs both to get the certificate. With Podman, write podman in place of docker in the commands.

  1. Install Caddy from its package repository. On Debian and Ubuntu:

    Terminal window
    sudo apt install --yes debian-keyring debian-archive-keyring apt-transport-https curl
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
    sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg /etc/apt/sources.list.d/caddy-stable.list
    sudo apt update
    sudo apt install caddy

    For other systems, see Install Caddy. The package runs Caddy as the service caddy.

  2. Start the server on the host’s loopback address only, so that it is reachable through Caddy and not from outside:

    Terminal window
    docker run -d --name telesphorepo -p 127.0.0.1:8080:8080 -v telesphorepo-data:/data -v telesphorepo-backups:/backups ghcr.io/telesphorepo/telesphorepo:latest

    With the program, set the listen address instead: TR_LISTEN=127.0.0.1:8080 ./telesphorepo-server serve.

    Copy the admin password from the log:

    Terminal window
    docker logs telesphorepo 2>&1 | grep 'password:'
  3. Put this in /etc/caddy/Caddyfile, in place of what is there:

    /etc/caddy/Caddyfile
    repo.example.com {
    reverse_proxy localhost:8080
    }
  4. Reload Caddy:

    Terminal window
    sudo systemctl reload caddy
Other proxies
  • Let the proxy accept request bodies up to the Max upload size of the server (Settings › General). The default is 2 GiB. Some proxies stop at 1 MiB.
  • Without a proxy, on plain HTTP and a host that is not localhost, the browser drops the session cookie. Start the server with -e TR_COOKIE_SECURE=false. Maven also refuses plain HTTP, and pip, Yarn, dotnet and Docker each need a setting for it, so use HTTPS for real use.
HTTP/2, and TLS in the server itself

The server speaks HTTP/1.1 and HTTP/2. Behind a reverse proxy, the server also takes HTTP/2 without TLS, for a proxy that sends it. A proxy that sends HTTP/1.1 works too, so you need no change.

To let the server do TLS itself, set TR_TLS_CERT_FILE and TR_TLS_KEY_FILE to a certificate and a key (PEM files). Both are needed. The server loads a renewed certificate without a restart. Turning TLS on or off needs a restart.

  1. Open your address, such as https://repo.example.com. Without HTTPS, on your own computer, open http://localhost:8080.

  2. Sign in as admin, with the password from the log.

  3. Add your authenticator app when the page asks.

    Authenticator app › Add. Scan the code, then type the code from your phone.

The server asks for this second step from everyone who manages it. See Two-step verification.

Do this when a reverse proxy, such as Caddy, sits in front of the server.

  1. Open Settings › Network and proxy.

  2. Under Detected proxies, click Trust on the row of Caddy.

  3. Click Save, then Save changes.

The server then sees the real address of each client. Rate limits, the audit log and the network rules need it.

Cloudflare in front

On the Network and proxy page, under Where your proxy is, tick Cloudflare. If Caddy sits between Cloudflare and the server, also tick Other addresses and add the address of Caddy.

  1. Open Settings › General.

  2. Set Public base URL to the address that people use.

    https://repo.example.com
  3. Click Save.

The addresses in the snippets, the setup lines and the CLI downloads then use your public address. CI jobs cannot publish without it, and passkeys need it: set it before anyone adds a passkey.

The server keeps files on its local disk by default. Cloudflare R2 is the usual choice for a bucket: R2 charges nothing for downloads. Any S3-compatible bucket works too, such as AWS S3 or SeaweedFS.

  1. In Cloudflare, create the bucket. Then create an R2 API token with Object Read & Write on it, and copy its Access Key ID and Secret Access Key: Cloudflare shows them once.

  2. Open Settings › Storage. Under Storage type, choose A Cloudflare R2 bucket, or another S3-compatible bucket, and enter:

    • Address: https://<account id>.r2.cloudflarestorage.com, with nothing after the host. The bucket’s Settings page shows it under S3 API.
    • Region: leave it empty.
    • Bucket: the bucket’s name.
    • Access key ID and Secret access key: from the token.
    • Path-style addresses: off.

    A custom domain of the bucket does not work here: it serves public downloads only, and the server writes and signs links through the S3 API.

  3. Click Test connection. The server writes, reads and deletes one test file.

  4. Click Save and confirm. If the server has files, it copies them to the bucket in the background, 16 at a time. Downloads and uploads keep working during the copy.

The old files stay where they were. Delete them yourself when the new storage works.

Setup Who answers a download Who sends the bytes
Local disk your server your server
R2 (default, Download from the bucket on) your server: it checks the account and the rules of the repository, then sends the build to a signed link that lasts a few minutes R2, straight to the build
R2 and edge delivery a Cloudflare Worker near the build, with the rules of the repository at the edge R2, from the bucket nearest the build

With R2, each download still makes one trip to your server first. Edge delivery takes that trip away, and keeps copies in buckets in several regions. If the builds cannot reach the bucket, turn off Download from the bucket: then your server sends the bytes.

AWS S3 and SeaweedFS
Setting AWS S3 SeaweedFS
Address leave it empty http://seaweedfs:8333
Region the bucket’s region, for example us-east-1 any name, for example us-east-1
Path-style addresses off on

The server encrypts secret settings with a master key. By default it writes the key to master.key in the data volume. Without the key, the server cannot read the S3 secret, the single sign-on secret, the signing keys and the authenticator apps.

To keep the key out of the volume, create one before the first start and pass it in:

Terminal window
openssl rand -base64 32
Terminal window
docker run -d --name telesphorepo -p 8080:8080 -v telesphorepo-data:/data -v telesphorepo-backups:/backups \
-e TR_MASTER_KEY="$(cat /run/secrets/tr_master_key)" \
ghcr.io/telesphorepo/telesphorepo:latest

Do not change TR_MASTER_KEY later.

The server backs itself up into /backups every 24 hours and keeps the newest 7. Mount a volume there, as the commands on this page do, best on another disk. The folder, the schedule and the number to keep are under Settings › Server › Backups, next to Back up now.

A backup is a folder with a copy of the database, the master key and, with local disk storage, the stored files. Files in an S3 bucket stay in the bucket, so back up the bucket too, with its versioning or replication. A master key in TR_MASTER_KEY is not written into the backup; keep it with the backups.

To back up from the command line, run this. It works while the server runs:

Terminal window
docker run --rm -v telesphorepo-data:/data -v telesphorepo-backups:/backups \
ghcr.io/telesphorepo/telesphorepo:latest backup /backups

Restore a backup folder into an empty volume, then start the server on that volume:

Terminal window
docker run --rm -v telesphorepo-backups:/backups -v telesphorepo-restored:/data \
ghcr.io/telesphorepo/telesphorepo:latest restore /backups/20261020T201500.123Z

The restore checks the database against its checksum, refuses a volume that is not empty, and says whether the backup is from the same version of Telesphorepo as the image.

The image ghcr.io/telesphorepo/telesphorepo has these tags, for linux/amd64 and linux/arm64:

Tag Is
latest The newest release
0.1.0, 0.1 One release, or the newest of a minor version
main The newest build of the main branch that passed its tests, between releases
sha-<commit> One build of the main branch, by its commit

Use latest or a version in production. Pin a version, such as 0.1, to choose when you upgrade.

  1. Back up: click Back up now under Settings › Server › Backups.

  2. Pull the new image and start a new container on the same volume:

    Terminal window
    docker compose pull
    docker compose up -d
  3. Check that it runs:

    Terminal window
    curl https://repo.example.com/healthz

    The answer is ok.

Pass the same -e variables as before. On its first start, a new version updates the database to its own structure, one step at a time, and the log names each step. The server refuses to start on a database from a newer version. To go back to an older version, restore the backup you made in step 1.

Behind Cloudflare (Free and Pro plans), each image layer must be under 100 MB. Pulls have no limit. Not behind Cloudflare? You have nothing to do.

To push larger layers, let the layers skip Cloudflare. People still push to the main address. The server tells the client to send the layers to a second address: the upload address. Nobody changes a command.

  1. In Cloudflare, add a second name for your server, for example upload.example.com. Make the record DNS only. Serve it over HTTPS, as in Serve over HTTPS.

  2. Open the port of that name in the firewall of your server, for the computers that push.

  3. Open Settings › General. Under Docker, set Docker upload address to https://upload.example.com. Turn on Expose the origin IP for Docker uploads. Click Save.

Pulls, logins and the credential helper keep the main address.

ORAS and Helm 4 send layers only to the address in the command. Push with them to the upload address:

Terminal window
helm push mychart-0.1.0.tgz oci://upload.example.com/docker
oras push upload.example.com/docker/team/art:1.0 file.txt
The log shows no password

Wait a few seconds, then run the log command again.

You lost the admin password, or the log no longer has it

Set a new one, and type it at the prompt:

Terminal window
docker exec -it telesphorepo /telesphorepo-server user passwd admin
Your data is gone after you removed the container

The data lives in the telesphorepo-data volume, not in the container. Always keep the volume: it holds the database, the files and the key for your secret settings. To get data back, restore a backup.

You run the program and cannot find the data

It is in ./data, next to where you started it. TR_DATA_DIR sets another folder.

The browser signs you out at once on plain HTTP

On plain HTTP and a host that is not localhost, the browser drops the session cookie. Serve the server over HTTPS, or start it with -e TR_COOKIE_SECURE=false.

Uploads through the proxy stop at 1 MiB

Let the proxy accept request bodies up to the Max upload size of the server (Settings › General), 2 GiB by default.

A Docker push stops with 413 behind Cloudflare

Each layer must be under 100 MB behind Cloudflare Free and Pro. See Push large images.

The server refuses to start after a downgrade

The server refuses to start on a database from a newer version. Restore the backup that you made before the upgrade.