# Installing the server

The reference deployment is a single Docker container fronted by
your existing reverse proxy. The image bundles the server binary,
the cross-compiled agent binaries, and the install scripts.

## Prerequisites

- A Linux host with Docker and Docker Compose.
- A reverse proxy in front (Caddy, nginx, Traefik) terminating
  TLS on a public hostname. The server itself is HTTP-only by
  design — see [Reverse proxy](./reverse-proxy.md) for why.
- A persistent volume for the server's data directory.

## Quick start

The reference compose file lives at
[`deploy/docker-compose.yml`](https://gitea.dcglab.co.uk/steve/restic-manager/src/branch/main/deploy/docker-compose.yml):

```yaml
services:
  restic-manager:
    image: gitea.dcglab.co.uk/steve/restic-manager:${RM_VERSION:-latest}
    restart: unless-stopped
    environment:
      RM_LISTEN: ":8080"
      RM_DATA_DIR: "/data"
      RM_BASE_URL: "https://restic.example.com"
      # Trust your reverse proxy's CIDR so X-Forwarded-* are honoured.
      RM_TRUSTED_PROXY: "10.0.0.0/8"
    volumes:
      - rm-data:/data
    ports:
      # Bind localhost only — your reverse proxy is the public face.
      - "127.0.0.1:8080:8080"

volumes:
  rm-data:
```

Bring it up:

```sh
docker compose up -d
docker compose logs -f restic-manager
```

The first run prints a one-time **bootstrap token** to the log. Use
it within an hour or it expires; if you miss the window the
container print it again on next start as long as no admin user
exists.

## First-run admin setup

Open `https://restic.example.com/bootstrap` (or whatever your
public URL is). Paste the bootstrap token, pick a username and a
password (≥ 12 characters), and submit. You'll land in the
dashboard logged in as the new admin.

If you'd rather curl it, the equivalent is:

```sh
curl -X POST https://restic.example.com/api/bootstrap \
     -H 'Content-Type: application/json' \
     -d '{"token":"<token-from-log>","username":"admin","password":"<≥12 chars>"}'
```

## Backing up the secret key

Inside the data volume, `secret.key` holds the AEAD key used to
encrypt every credential at rest. **Back it up separately from
the database.** Without it, encrypted credentials in the database
are unrecoverable; you'd have to re-enrol every host.

A simple working approach: copy `secret.key` to your password
manager or to a separately-backed-up secrets vault the day you
install. It doesn't change.

## Updating the server

```sh
# Pin a new version in your compose file (.env or docker-compose.yml),
# then:
docker compose pull
docker compose up -d
```

Migrations run automatically on startup; the server will refuse to
start if a migration fails (better to bail than to half-migrate).

For the agent self-update story, see
[Updating agents](../operations/updates.md).
