Files
ntbops-ansible/docs/topology.md
T

132 lines
3.4 KiB
Markdown

# Topology
Every VM is a Docker host. Proxmox and Cloud-Init only create the machine and
bootstrap Ansible; service placement is controlled by inventory.
## Edge VM
The edge VM runs:
- Docker
- Traefik
- authentik IAM
It publishes Traefik entrypoints on host ports `80` and `443`. authentik can run
behind the same local Traefik instance by setting:
```yaml
nbops_service_routing_mode: traefik
authentik_domain: auth.example.invalid
```
## Downstream VMs
Downstream VMs also run Docker and normally run an internal Traefik instance.
Application containers route through that local Traefik using Docker labels and
the shared Docker proxy network.
```yaml
nbops_roles:
- base
- ssh
- ufw
- updates
- docker
- traefik
- gitea
- immich
nbops_service_routing_mode: traefik
nbops_traefik_entrypoint: web
nbops_traefik_tls: false
```
In this mode application roles do not publish their HTTP ports. They render
Traefik labels and join `nbops_proxy_network`, which defaults to `proxy`.
Only Traefik entrypoints should be exposed on the downstream host firewall. Use
`traefik_bind_address` to bind those entrypoints to the VM's internal address.
For central edge routing, the edge Traefik uses the file provider to route
machine-to-machine traffic to each downstream VM's internal Traefik entrypoint.
The internal Traefik then routes to applications using Docker labels. This keeps
container discovery local to the VM and gives the edge-to-internal leg a stable
place for future mTLS.
Edge VM:
```yaml
nbops_roles:
- base
- ssh
- ufw
- updates
- docker
- traefik
traefik_docker_provider_enabled: false
traefik_file_provider_enabled: true
traefik_dynamic_inventory_group: nbops
```
Downstream VM:
```yaml
nbops_service_routing_mode: traefik
nbops_traefik_entrypoint: web
nbops_traefik_tls: false
traefik_bind_address: "10.0.10.25"
traefik_publish_entrypoints: true
nbops_traefik_file_routes:
- name: jellyfin
domain: jellyfin.example.invalid
scheme: http
port: 80
- name: gitea
domain: git.example.invalid
scheme: http
port: 80
```
When the play runs against the edge VM, Traefik renders
`dynamic/http-services.yml` from `nbops_traefik_file_routes` declared across the
inventory group. Each route targets `ansible_host` for that inventory host by
default. Set `target_host` for a different VM address, or set `url` to provide
the complete upstream URL.
For future mTLS between edge Traefik and internal Traefik, routes can reference a
Traefik `serversTransport`:
```yaml
nbops_traefik_file_routes:
- name: jellyfin
domain: jellyfin.example.invalid
scheme: https
port: 443
servers_transport: internal-mtls
traefik_dynamic_servers_transports:
- name: internal-mtls
server_name: apps-01.example.internal
root_cas:
- /etc/pki/internal/certs/ca.crt
certificates:
- cert_file: /etc/pki/internal/certs/edge.crt
key_file: /etc/pki/internal/private/edge.key
```
## Routing Modes
Application roles support:
- `host`: publish application ports directly and open those ports in UFW.
- `traefik`: do not publish HTTP ports; attach to Traefik and render labels.
- `traefik_file`: publish a service port without labels. This is available for
exceptional direct edge-to-app routes, but the preferred multi-VM topology is
edge Traefik -> internal Traefik -> application.
Gitea is special: HTTP can be routed through Traefik while SSH remains published
with `gitea_publish_ssh: true`.