# Troubleshooting

> Diagnose common Fleetdock problems — agent connectivity, tokens, TLS and DNS, Docker permissions, port conflicts, disk space, and stuck operations.

Source: https://fleetdock.dev/docs/troubleshooting


This page uses only commands that exist in the current release. On an installed Manager,
start with `fleetdock doctor` — it checks versions, container health, DNS, reachability and
disk in one pass. Beyond that, diagnose with the health endpoints, the systemd journal, and
standard Docker and Linux tools.

<Callout type="info">
  Start with two signals: the Manager's `GET /readyz`, and the agent's journal
  (`journalctl -u fleetdock-agent`). Most issues surface in one of them.
</Callout>

## Installing Fleetdock [#installing-fleetdock]

| Symptom                                           | Fix                                                                                                                                                 |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `error: a server install must run as root`        | Run `curl -sSL https://fleetdock.dev/install.sh \| sudo sh` — `sudo` after the pipe. Or add `--local` to install only for yourself on this computer |
| `port 80 is already in use`                       | Stop what is bound there (often nginx or apache). For a [local install](/docs/local), pick another port with `--port 8090`                          |
| The installer asked no questions                  | No terminal was available (CI, cloud-init, `ssh` without `-t`), so it used the flags and defaults. Pass `--domain` and `--admin-email`              |
| `Windows is supported through WSL2`               | You ran it from Git Bash or MSYS. Use the Ubuntu (WSL) terminal — see [Install on your computer](/docs/local)                                       |
| `Docker is installed but not running`             | Start Docker Desktop (macOS, Windows) or `sudo systemctl start docker`, then re-run                                                                 |
| A database on the same computer cannot be reached | Use `host.docker.internal` as its host, not `localhost`, and make sure it listens on more than `127.0.0.1`                                          |

## Agent cannot connect [#agent-cannot-connect]

Check the agent's logs on the server:

```bash
systemctl status fleetdock-agent
journalctl -u fleetdock-agent --since "10 min ago"
```

Confirm the server can reach the Manager on the API port:

```bash
curl -fsS "$FLEETDOCK_URL/healthz"
```

If this fails, the problem is network reachability or `FLEETDOCK_PUBLIC_URL` — see the
sections below.

## Invalid registration token [#invalid-registration-token]

Registration tokens are **single-use and short-lived**. If enrollment fails with a token
error, generate a fresh token in **Servers → Connect server** and re-run the install command.
A token that has already enrolled a server cannot be reused.

## Manager URL is unreachable [#manager-url-is-unreachable]

The value baked into the install command (`FLEETDOCK_PUBLIC_URL`) must be reachable from the
server. From the server:

```bash
curl -fsS https://your-control-plane/healthz
```

Common causes: `localhost` used from a remote VM (see [Networking](/docs/networking)), a
firewall blocking `443`, or DNS not resolving.

## TLS certificate error [#tls-certificate-error]

If the agent or `curl` reports a certificate error, the reverse proxy's certificate is
invalid, self-signed, or for the wrong hostname. Verify:

```bash
curl -vI https://your-control-plane/healthz
```

Use a valid certificate for the exact hostname in `FLEETDOCK_PUBLIC_URL` (Let's Encrypt via
Caddy is the simplest path — see [Manager installation](/docs/manager)).

## DNS resolution failure [#dns-resolution-failure]

```bash
getent hosts your-control-plane   # or: nslookup your-control-plane
```

If the name does not resolve from the server, fix DNS or use an IP address the server can
reach in `FLEETDOCK_PUBLIC_URL`.

## Docker permission denied [#docker-permission-denied]

Provisioning requires Docker on the node. The agent runs as root, so check Docker is
installed and running:

```bash
docker ps
systemctl status docker
```

If Docker is missing, re-run the agent installer (it installs Docker) or install it manually,
then `systemctl enable --now docker`.

## Database port conflict [#database-port-conflict]

If provisioning fails because a port is in use, choose a different published port for the
instance, or find what holds it:

```bash
ss -ltnp | grep :<port>
```

## Insufficient disk space [#insufficient-disk-space]

Backups, restores, and metrics accumulate. Check space on the affected host:

```bash
df -h
```

Free space (or prune old backups via retention) and retry the operation. On the Manager
host, a full disk can also cause `/readyz` failures.

## Backup failure [#backup-failure]

Open the **Operations** page and read the failed operation's error. Common causes: the
destination bucket is unreachable or misconfigured (re-run **Test bucket** on the
**Destinations** page), or the instance is unreachable from the executing side. Configure
notification channels to be alerted automatically.

## Restore failure [#restore-failure]

A restore aborts **before** touching the target if the backup checksum does not match. Other
causes are an unreachable target, insufficient disk, or bad credentials. See
[Restore failure scenarios](/docs/restores#failure-scenarios).

## Migration failure [#migration-failure]

A migration is a backup → restore → verify saga. If it fails before the drop step, the source
is left intact — fix the cause (capacity, connectivity, credentials) and retry. See
[Migration failure recovery](/docs/migrations#failure-recovery).

## Database instance remains unhealthy [#database-instance-remains-unhealthy]

Inspect the container on the node and the operation history:

```bash
docker ps -a
docker logs <container-name>
```

Confirm the instance's published port is reachable from the control plane (required for live
administration) — see [Networking](/docs/networking).

## Gateway and external access [#gateway-and-external-access]

If public access is enabled for a database, external applications connect through the
**Fleetdock Gateway** instead of the instance's published port directly.

| Symptom                                             | Check                                                                                                              |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Endpoint stuck `pending`                            | `last_error` on the endpoint; the `reconcile_gateway` operation; whether the gateway container is healthy          |
| Endpoint shows `error`                              | `last_error` names the unreachable `host:port` — can the **gateway container** reach it?                           |
| Connection closes immediately after connecting      | The CIDR allowlist. This is what a rejection looks like — the gateway accepts the TCP connection, then drops it.   |
| Connection refused from an allowed IP               | The address the gateway *observes* is probably not the address you allowlisted — see below                         |
| `server does not support SSL, but SSL was required` | The database does not accept TLS — enable it, or recreate the endpoint with `tls_mode=preferred`                   |
| Cannot connect externally                           | DNS for `FLEETDOCK_GATEWAY_PUBLIC_HOST`, host firewall on the port range, and that the range is actually published |

```bash
# From the machine that will connect — what source address does the gateway see?
# Allowlist exactly what this prints.
curl http://gateway.example.com:15431

# Then test reachability of the database's assigned port:
nc -vz gateway.example.com 15432

# On the Manager host — confirm the gateway is up:
docker compose ps gateway
docker compose logs gateway --tail 50
```

<Callout type="warn">
  Behind NAT (including Docker Desktop) or an L4 load balancer, the gateway sees the proxy's
  address rather than your client's, so an otherwise-correct allowlist rejects everyone. The
  connectivity panel reports rejected-connection counts when this is happening.
</Callout>

See [External database access](/docs/external-access) for full setup and troubleshooting.

## Node remains offline [#node-remains-offline]

A node is marked `offline` after `FLEETDOCK_HEARTBEAT_TIMEOUT` (default `2m`) without a
heartbeat. Check the agent service and its connectivity to the Manager:

```bash
systemctl status fleetdock-agent
journalctl -u fleetdock-agent -f
```

## System clock mismatch [#system-clock-mismatch]

A significantly skewed clock can break TLS validation and token handling. Check and correct
time sync on the server:

```bash
timedatectl
```

Enable NTP (`timedatectl set-ntp true`) if the clock is drifting.

## Firewall blocks connection [#firewall-blocks-connection]

Two paths must be open: the agent's **outbound** access to `FLEETDOCK_PUBLIC_URL`, and the
Manager's access to any **database port** it administers. Test reachability:

```bash
curl -fsS https://your-control-plane/healthz     # from the server → Manager
nc -vz <server-address> <instance-port>          # from the Manager → instance
```

## Agent service does not start [#agent-service-does-not-start]

```bash
systemctl status fleetdock-agent
journalctl -u fleetdock-agent -n 100 --no-pager
```

Verify the config file exists and is readable, and that the binary is present:

```bash
cat /etc/fleetdock-agent/agent.env      # FLEETDOCK_URL, FLEETDOCK_TOKEN, FLEETDOCK_STATE_DIR
ls -l /usr/local/bin/fleetdock-agent
```

<Callout type="info">
  Missing first-class diagnostic commands (for example a bundled `doctor` / preflight check)
  are noted as a product gap. Until they exist, the commands on this page are the supported
  way to diagnose issues.
</Callout>
