> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hill90.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Network topology, isolation boundaries, and service responsibilities.

# Architecture

Five layers on one host: edge, observability, secrets, identity and data, and the
infrastructure automation underneath them.

* **Edge** — Traefik reverse proxy with automatic HTTPS, Portainer, and the DNS-01
  challenge webhook
* **Observability** — the LGTM stack (Loki, Grafana, Tempo, Prometheus) with collectors
* **Secrets** — OpenBao, with SOPS/age as bootstrap and disaster-recovery backup
* **Identity and data** — Keycloak and the Postgres instance behind it
* **Infrastructure** — Docker Compose orchestration, Tailscale VPN for admin access,
  Ansible playbooks for host provisioning

## Network topology

```
Internet                         Tailscale Network (100.64.0.0/10)
   ↓                                     ↓
Traefik (edge network)           ┌──────────────────────────┐
   ↓                             │ Admin Services           │
┌─────────────────────────────┐  │ - Traefik Dashboard      │
│ Public entrypoints          │  │ - Portainer UI           │
│ - :80  (HTTP-01 validation, │  │ - Grafana                │
│         redirect to :443)   │  │ - OpenBao UI             │
│ - :443 (TLS termination)    │  └──────────────────────────┘
└─────────────────────────────┘           ↓ (DNS-01 certs)
                                 ┌──────────────────────────┐
   ↓                             │ DNS Manager              │
┌─────────────────────────────┐  │ (Webhook for ACME)       │
│ Internal (hill90_internal)  │  └──────────────────────────┘
│ - Loki (logs)               │           ↓
│ - Tempo (traces)            │  Hostinger DNS API
│ - Promtail (log collector)  │  (TXT record management)
│ - Node Exporter (host)      │
│ - cAdvisor (containers)     │
│ - Postgres (platform db)    │
└─────────────────────────────┘
   ↓
┌─────────────────────────────┐
│ Edge + internal             │
│ - Prometheus (metrics)      │
│ - Grafana (dashboards)      │
│ - OpenBao (secrets)         │
│ - Keycloak (identity —      │
│   the only publicly routed  │
│   service, no allowlist)    │
└─────────────────────────────┘
```

## Network isolation

| Network                 | Property         | Purpose                                                                          |
| ----------------------- | ---------------- | -------------------------------------------------------------------------------- |
| `hill90_edge`           | ingress-facing   | Traefik and the services it routes                                               |
| `hill90_internal`       | `internal: true` | Private service-to-service traffic, unreachable from outside the host            |
| `hill90_agent_internal` | `internal: true` | Retained from the shelved application, currently unused by any running container |

`docker-compose.infra.yml` is the sole owner of all three networks. Every other stack —
observability, vault, database and identity — declares the networks it needs as
`external: true` rather than creating them, which is why the edge stack must deploy first
on a fresh host. Nothing declares `hill90_agent_internal`; it is created and then unused.

Admin surfaces are additionally restricted to the Tailscale CGNAT range
(`100.64.0.0/10`) by a Traefik IP-allowlist middleware, and SSH is restricted to the same
range at the firewall.

## Service responsibilities

| Service                               | Responsibility                                                                                                                                                                                                                |
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Traefik**                           | Reverse proxy and TLS termination. HTTP-01 for public hostnames, DNS-01 for Tailscale-only ones. Dashboard at `traefik.hill90.com`, behind basic auth plus the Tailscale allowlist.                                           |
| **dns-manager**                       | HTTP webhook for Let's Encrypt DNS-01 challenges. Translates the Lego `httpreq` format to the Hostinger DNS API, creating and deleting TXT records.                                                                           |
| **Portainer**                         | Docker container management UI at `portainer.hill90.com`.                                                                                                                                                                     |
| **Keycloak**                          | Identity provider at `auth.hill90.com`, serving the `platform` realm. Publicly routed, unlike every other dashboard. Nothing signs in through it yet — see [Overview](/homelab/overview#single-sign-on-is-not-available-yet). |
| **Postgres**                          | Platform database on the internal network only, with no Traefik route. Its init script creates one database, `keycloak`, beyond the instance's own default; application databases belong with the applications that own them. |
| **OpenBao**                           | Secrets management at `vault.hill90.com`. Admin access is by token and services authenticate by AppRole; no OIDC auth method is enabled — see [Secrets](/homelab/secrets).                                                    |
| **Prometheus, Grafana, Loki, Tempo**  | Metrics, dashboards, logs and traces.                                                                                                                                                                                         |
| **Promtail, node-exporter, cAdvisor** | Log and metric collectors.                                                                                                                                                                                                    |

## Security posture

* Public internet access is limited to ports 80 and 443, handled by Traefik. Every
  administrative surface is reachable only through Tailscale, with one deliberate
  exception: Keycloak is publicly routed, including its admin console. See
  [Surfaces](/homelab/overview#surfaces).
* SSH uses key-based authentication only; password auth and root login are disabled, and
  fail2ban is enabled.
* The Traefik dashboard password hash is generated at deploy time from encrypted secrets
  into a gitignored `.htpasswd`.
* ACME state is persisted in mounted Traefik storage so renewals survive restarts.
* CI blocks destructive Docker commands (`down -v`, `volume rm`, `system prune`,
  `--remove-orphans`) from entering scripts or workflows.
* Outbound email is configured but not functional. The `platform` realm carries SMTP
  settings for `smtp.hostinger.com`, but the password is empty, so authenticated delivery
  cannot succeed as configured. No mail flow has been tested, and no other service in the
  stack sends email.

The verification checklist for the posture above — `make health`, public-versus-Tailscale
SSH, `make dns-verify`, ACME issuance in the Traefik logs, and the expected containers in
`docker ps` — lives in the security architecture doc linked below.

## Source documents

These are maintained beside the code and are the authority. This page summarises them.

* [`docs/architecture/overview.md`](https://github.com/jonhill90/Hill90/blob/main/docs/architecture/overview.md)
  — the full architecture record
* [`docs/architecture/security.md`](https://github.com/jonhill90/Hill90/blob/main/docs/architecture/security.md)
  — access boundaries, hardening, verification checklist
* [`docs/architecture/certificates.md`](https://github.com/jonhill90/Hill90/blob/main/docs/architecture/certificates.md)
  — certificate management in depth
* [`docs/reference/deployment.md`](https://github.com/jonhill90/Hill90/blob/main/docs/reference/deployment.md)
  — compose files, project names, deploy safety policy
