---
url: /guide/managing-servers.md
description: Operate and troubleshoot your DockIY server.
---

# Managing servers

The server stack is the shared infrastructure that applications depend on. It
provides HTTPS routing, analytics, logs, monitoring, and a private image
registry.

## Set up the services

Run this from the directory where you want DockIY to keep its infrastructure
repository:

```bash
dockiy server init --sops "$SOPS_RECIPIENT"
```

Choose a recipient using [SOPS identity setup](/guide/installation#sops-identity),
or use `--sops-config /path/to/.sops.yaml` for other SOPS backends. Omit these
options when reusing an existing infrastructure repository.

The initializer asks for an ACME email, the public hostnames for the three
dashboards, and their login details. Those hostnames DNS must already resolve to
the server. It stores the environment as SOPS-encrypted `.enc.env`; the
decrypted `.env` is uploaded to the server but is not kept in the repository.
Keep the [SOPS identity](https://getsops.io/docs/usage/identities/) private and
back it up securely.

::: warning Don't forget DNS

Make sure the hostnames' DNS point to your server's public IP first. See the [installation guide](installation#_1-set-up-dns) for more details.

:::

The infrastructure repository contains `docker-compose.yml`,
`dockiy.manifest.yml`, `.sops.yaml`, `.enc.env`, and the Dozzle users file.
`dockiy.manifest.yml` says which non-secret files are synchronized:

```yaml
server:
  compose_file: docker-compose.yml
  files:
    - docker-compose.yml
    - dozzle_data/users.yml
```

The runtime `.env` is managed separately by the CLI and must not be added to
`files`.

## Manage multiple servers

Keep one profile per server in the global config and select the usual target
with `default_server`:

```yaml
default_server: personal

servers:
  personal:
    ssh: dockiy@personal.example.com
  experiments:
    ssh: dockiy@my-experiments.com
```

To deploy a particular app to `experiments`, create `dockiy.config.yml` in that app
repository:

```yaml
default_server: experiments
```

Run DockIY from that repository directory. This local file overrides the global
default for commands run there; it is not searched for in parent directories.
See the [configuration reference](/config/) for profile fields and precedence.

## The Compose file

The [Docker Compose file reference](https://docs.docker.com/compose/compose-file/)
explains the underlying format. In DockIY, the important parts are:

| Part | Purpose |
| --- | --- |
| `name` and service keys | Identify the infrastructure Compose project and the services expected by `server status`. Keep them stable. |
| `traefik` | Terminates HTTP/HTTPS, obtains Let's Encrypt certificates, and routes requests from Docker labels. See [Traefik's Docker provider docs](https://doc.traefik.io/traefik/reference/install-configuration/providers/docker/). |
| `registry` | Stores application images on the VPS. It binds to `127.0.0.1`, so it is reachable through DockIY's SSH tunnel, not publicly. |
| `umami` and `umami-db` | Run analytics and its PostgreSQL database. |
| `dozzle` | Provide a web UI for live Docker logs, using the Docker socket and `dozzle_data/users.yml` for file authentication. |
| `beszel` and `beszel-agent` | Provide a monitoring Hub and the agent that reports this server. |
| `volumes` | Persist registry images and the Umami database. Never remove or rename these without a data migration. |
| `networks` | `reverse_proxy` is the stable external network that deployed applications join. `umami_db` keeps the database private to Umami. |
| environment variables and labels | `.env` supplies hosts and secrets. Traefik labels publish Umami, Dozzle, and Beszel on their configured hostnames. |

The comments marked `DOCKIY DISRUPTIVE` or `DOCKIY MIGRATION REQUIRED` are part
of the contract. Review them before changing image major versions, service
keys, the Compose project name, ports, volume mounts, the `dockiy` certificate
resolver, or network names.

### Service dashboards

* **[Umami](https://docs.umami.is/docs/about)** is your self-hosted analytics dashboard. For every app you want to track, create a website
  in Umami, copy its tracking script, and add it to your app.
* **[Dozzle](https://dozzle.dev/guide/what-is-dozzle)** is a lightweight,
  browser-based viewer for live Docker container logs. DockIY protects it with
  Dozzle's [file authentication](https://dozzle.dev/guide/authentication).
* **[Beszel](https://beszel.dev/guide/what-is-beszel)** is lightweight server
  monitoring with Docker statistics, history, and alerts. Its Hub runs on the
  VPS and its agent reports the VPS metrics to that Hub. We recommend you setup notifications in the dashboard.

### The private registry

The registry is a small [OCI/Docker registry](https://distribution.github.io/distribution/)
for images built by DockIY applications.

During `dockiy app deploy`, the CLI pushes the locally built image through an
SSH tunnel, and the server's Docker daemon pulls it from its own loopback
address.

#### Why even host a registry?

* Your Docker images are fully self-hosted, no external DockerHub or Github dependency.
* Keeping images history makes rollbacks safer and faster.
* Images are a rather efficient way to store builds thanks to [image layers](https://docs.docker.com/get-started/docker-concepts/building-images/understanding-image-layers/).

## What does the CLI actually do?

`server init` is a local orchestration command. it essentially does:

1. Resolves the selected server profile and runs preflight checks.
2. Clones the DockIY base stack into `./dockiy` (if not already done), then makes it your working repository.
3. Recovers existing server values when possible, applies defaults, and stages
   the Compose environment and Dozzle credentials locally.
4. Encrypts the environment with SOPS, prepares the remote directories, and
   synchronizes the manifest-listed files plus the temporary decrypted `.env`
   over SSH/rsync.
5. Starts Traefik, the registry, Umami/PostgreSQL, Dozzle, and Beszel with
   `docker compose up`, waiting for them to become ready.
6. Bootstraps the Umami administrator and Beszel Hub, retrieves the Beszel
   agent credentials, writes those credentials back to `.enc.env`, starts the
   agent, and checks the public endpoints.

Repeating `server init` should be safe for an existing setup: it reuses persisted data
and existing credentials instead of generating replacements. Review and commit
infrastructure changes in the repository as you would any other Git project.

## Update the server

Run updates from the infrastructure repository:

```bash
dockiy server update
```

This essentially re-uploads your `docker-compose.yml` and runs `docker compose up` again. It's useful to add or modify services.

This requires `.enc.env`, decrypts it locally, restores a missing Dozzle users
file from the server when possible, synchronizes the manifest-listed files and
`.env`, then runs Compose to reconcile the stack and remove orphaned
containers. It waits for service and endpoint readiness. It does not regenerate
secrets or change Umami, Beszel, or Dozzle administrator accounts.

To fetch newer image tags before reconciling the stack, use:

```bash
dockiy server update --pull
```

`--pull` runs `docker compose pull` on the server first. It pulls the image
versions currently written in your local Compose file; it does not fetch Git
changes from the upstream DockIY repository. There is no separate
`dockiy server pull` command.

Use these commands to inspect the result:

```bash
dockiy server doctor
dockiy server status
```
