# Running the server

> Run your own routeup server on a domain you control.

The public server is the same `routeup` binary you already have. Self-hosting
means running it with your own domain, DNS, and TLS. The hosted `routeup.dev` is
just one deployment of this code.

## Prerequisites

- A domain (or subdomain) you control, e.g. `tunnel.example.com`.
- DNS for the root wildcard and every enabled nested namespace pointing at the
  server. See [DNS setup](/docs/self-hosting/dns-setup).
- A way to issue TLS. By default that is a Cloudflare API token for ACME DNS-01.
  See [TLS](/docs/self-hosting/tls).

## Start it

```bash
export CLOUDFLARE_API_TOKEN="your-cloudflare-api-token"
routeup server --domain tunnel.example.com \
  --reserved edge \
  --db /var/lib/routeup/server.db
```

This serves HTTPS for root-tier and configured namespace hosts, authenticates
tunnel clients, and forwards public requests down their matching tunnels.
`edge.tunnel.example.com` is the client control host in these examples;
`--reserved edge` prevents a root-tier token from claiming that label.

Configure a client with the control host, not the suffix apex:

```bash
routeup setup --server https://edge.tunnel.example.com --token sk_routeup_xxx
```

Common flags:

```txt
--domain <suffix>           public suffix to serve
--config <path>             server config file
--db <path>                 SQLite database path
--public-namespace <label>  enable token-less claims under one label
--reserved <label>          reserve a root-tier label; repeatable
--tls-mode <acme|cert>      acme auto-issues wildcards; cert uses your files
--tls-cert <path>           PEM certificate for cert mode
--tls-key <path>            PEM private key for cert mode
```

Run `routeup server --help` for listen, ACME, logging, metrics, and rate-limit
options.

The same settings can live in a server config file:

```json title="routeup-server.json"
{
  "domain": "tunnel.example.com",
  "listen": ":443",
  "db": "/var/lib/routeup/server.db",
  "acme_email": "admin@example.com",
  "acme_storage": "/var/lib/routeup/acme",
  "reserved": ["edge"],
  "log_format": "json",
  "log_level": "info"
}
```

## Deployment shape

A single small VM is enough for v1. The server is one binary with a local SQLite
database. Put it behind a stable IP, open 443, and run it under a process
supervisor (systemd, a container restart policy) so it comes back after reboots.

## State and backups

The server keeps tokens and token-backed route holds in SQLite. Public-namespace
holds are session-only and are purged at startup. Back up the SQLite file so you
do not have to re-mint and redistribute tokens after a host loss.

## Operating

- Mint and revoke access with [tokens](/docs/self-hosting/minting-tokens).
- Reserved subdomains (`api`, `admin`, `www`, `try`, …) are refused for claims and
  can be extended in server config.
- Logs are structured; tail them through your supervisor.
