mirror of
https://github.com/RWejlgaard/pez-infra.git
synced 2026-05-06 04:14:43 +00:00
add hetzner servers terraform (#23)
Co-authored-by: Rasmus Wejlgaard <pez@Mac.localdomain>
This commit is contained in:
parent
353c2ad790
commit
4be8f73ffe
6 changed files with 315 additions and 106 deletions
|
|
@ -8,44 +8,22 @@ The setup is entirely self-hosted (with the exception of Hetzner Cloud VPSs and
|
||||||
|
|
||||||
## Network Topology
|
## Network Topology
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
┌──────────────┐
|
graph TD
|
||||||
│ Cloudflare │
|
CF["<b>Cloudflare</b><br/>DNS + CDN<br/>*.pez.sh"]
|
||||||
│ DNS + CDN │
|
CF -->|HTTPS| HEL
|
||||||
│ *.pez.sh │
|
|
||||||
└──────┬───────┘
|
|
||||||
│
|
|
||||||
│ HTTPS
|
|
||||||
│
|
|
||||||
┌────────────▼────────────┐
|
|
||||||
│ helsinki-a │
|
|
||||||
│ Hetzner Cloud VPS │
|
|
||||||
│ │
|
|
||||||
│ Caddy (reverse proxy) │
|
|
||||||
│ Authelia (SSO) │
|
|
||||||
│ Bitwarden │
|
|
||||||
│ LLDAP │
|
|
||||||
└────────────┬────────────┘
|
|
||||||
│
|
|
||||||
┌───────────────┼───────────────┐
|
|
||||||
│ Tailscale Mesh │
|
|
||||||
│ (WireGuard-based VPN) │
|
|
||||||
└───┬───────┬───────┬───────┬───┘
|
|
||||||
│ │ │ │
|
|
||||||
┌────────▼──┐ ┌──▼────────┐ ┌────▼───────┐ ┌──▼──────────┐
|
|
||||||
│ london-b │ │ london-a │ │nuremberg-a │ │copenhagen-a │
|
|
||||||
│ │ │ │ │ │ │ │
|
|
||||||
│ Storage │ │ Monitoring│ │ Mail │ │ Gaming │
|
|
||||||
│ Media │ │ Prometheus│ │ poste.io │ │ Minecraft │
|
|
||||||
│ Docker │ │ Grafana │ │ │ │ WoW/MaNGOS │
|
|
||||||
│ services │ │ │ │ │ │ │
|
|
||||||
│ (46T ZFS) │ │ (FreeBSD) │ │ (Alpine) │ │ (Ubuntu) │
|
|
||||||
└───────────┘ └───────────┘ └────────────┘ └─────────────┘
|
|
||||||
|
|
||||||
┌─────────────┐
|
HEL["<b>helsinki-a</b><br/>Hetzner Cloud VPS<br/><br/>Caddy (reverse proxy)<br/>Authelia (SSO)<br/>Bitwarden<br/>LLDAP"]
|
||||||
│copenhagen-c │
|
|
||||||
│ (idle) │
|
HEL --> TS["<b>Tailscale Mesh</b><br/>WireGuard-based VPN"]
|
||||||
└─────────────┘
|
|
||||||
|
TS --> LB["<b>london-b</b><br/>Storage / Media<br/>Docker services<br/>(46T ZFS)"]
|
||||||
|
TS --> LA["<b>london-a</b><br/>Monitoring<br/>Prometheus / Grafana<br/>(FreeBSD)"]
|
||||||
|
TS --> NA["<b>nuremberg-a</b><br/>Mail<br/>poste.io<br/>(Alpine)"]
|
||||||
|
TS --> CA["<b>copenhagen-a</b><br/>Gaming<br/>Minecraft / WoW/MaNGOS<br/>(Ubuntu)"]
|
||||||
|
TS --> CC["<b>copenhagen-c</b><br/>(idle)"]
|
||||||
|
|
||||||
|
style CC stroke-dasharray: 5 5
|
||||||
```
|
```
|
||||||
|
|
||||||
## Traffic Flow
|
## Traffic Flow
|
||||||
|
|
@ -62,39 +40,27 @@ User → Cloudflare (DNS + TLS) → helsinki-a (Caddy) → Backend (over Tailsca
|
||||||
4. For protected services, Caddy calls Authelia first (`forward_auth`)
|
4. For protected services, Caddy calls Authelia first (`forward_auth`)
|
||||||
5. If authenticated (or no auth required), traffic is proxied over Tailscale to the backend
|
5. If authenticated (or no auth required), traffic is proxied over Tailscale to the backend
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
┌─────────────────────────────────────────────┐
|
graph LR
|
||||||
│ helsinki-a (Caddy) │
|
subgraph "helsinki-a (Caddy)"
|
||||||
│ │
|
A1["forward_auth → Authelia"]
|
||||||
radarr.pez.sh ──► │ forward_auth → Authelia ──► london-b:7878 │
|
A2["(no auth)"]
|
||||||
│ │
|
A3["forward_auth → Authelia"]
|
||||||
jellyfin.pez.sh ─►│ (no auth) ───────────────► london-b:8096 │
|
A4["(local)"]
|
||||||
│ │
|
end
|
||||||
grafana.pez.sh ──►│ forward_auth → Authelia ──► london-a:3000 │
|
|
||||||
│ │
|
R["radarr.pez.sh"] --> A1 --> LB1["london-b:7878"]
|
||||||
auth.pez.sh ─────►│ (local) ────────────────► localhost:9091 │
|
J["jellyfin.pez.sh"] --> A2 --> LB2["london-b:8096"]
|
||||||
└─────────────────────────────────────────────┘
|
G["grafana.pez.sh"] --> A3 --> LA["london-a:3000"]
|
||||||
|
AU["auth.pez.sh"] --> A4 --> LO["localhost:9091"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Auth Architecture
|
## Auth Architecture
|
||||||
|
|
||||||
```
|
```mermaid
|
||||||
┌──────────┐
|
graph TD
|
||||||
│ Caddy │
|
Caddy["<b>Caddy</b><br/>forward_auth"] --> Authelia["<b>Authelia</b><br/>SSO<br/>auth.pez.sh"]
|
||||||
│ │
|
Authelia --> LLDAP["<b>LLDAP</b><br/>User directory"]
|
||||||
│ forward_ │
|
|
||||||
│ auth │
|
|
||||||
└────┬─────┘
|
|
||||||
│
|
|
||||||
┌────▼─────┐
|
|
||||||
│ Authelia │ auth.pez.sh
|
|
||||||
│ (SSO) │
|
|
||||||
└────┬─────┘
|
|
||||||
│
|
|
||||||
┌────▼─────┐
|
|
||||||
│ LLDAP │ User directory
|
|
||||||
│ │
|
|
||||||
└──────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Authelia authenticates against LLDAP (both on helsinki-a). One place to manage users — add or remove someone in LDAP and it propagates to all protected services.
|
Authelia authenticates against LLDAP (both on helsinki-a). One place to manage users — add or remove someone in LDAP and it propagates to all protected services.
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ resource "cloudflare_dns_record" "alertmanager" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "alertmanager"
|
name = "alertmanager"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ resource "cloudflare_dns_record" "apps" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "apps"
|
name = "apps"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +31,7 @@ resource "cloudflare_dns_record" "auth" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "auth"
|
name = "auth"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +40,7 @@ resource "cloudflare_dns_record" "bitwarden" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "bitwarden"
|
name = "bitwarden"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +49,7 @@ resource "cloudflare_dns_record" "cloud" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "cloud"
|
name = "cloud"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +58,7 @@ resource "cloudflare_dns_record" "download" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "download"
|
name = "download"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +67,7 @@ resource "cloudflare_dns_record" "git" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "git"
|
name = "git"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -76,7 +76,7 @@ resource "cloudflare_dns_record" "grafana" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "grafana"
|
name = "grafana"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +85,7 @@ resource "cloudflare_dns_record" "helsinki-a" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "helsinki-a"
|
name = "helsinki-a"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -94,7 +94,7 @@ resource "cloudflare_dns_record" "jellyfin" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "jellyfin"
|
name = "jellyfin"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ resource "cloudflare_dns_record" "jellyfin-requests" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "jellyfin-requests"
|
name = "jellyfin-requests"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +112,7 @@ resource "cloudflare_dns_record" "ldap" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "ldap"
|
name = "ldap"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +121,7 @@ resource "cloudflare_dns_record" "lidarr" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "lidarr"
|
name = "lidarr"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +148,7 @@ resource "cloudflare_dns_record" "music" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "music"
|
name = "music"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ resource "cloudflare_dns_record" "naveen" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "naveen"
|
name = "naveen"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ resource "cloudflare_dns_record" "root" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "@"
|
name = "@"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +175,7 @@ resource "cloudflare_dns_record" "plex" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "plex"
|
name = "plex"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +184,7 @@ resource "cloudflare_dns_record" "prometheus" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "prometheus"
|
name = "prometheus"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +193,7 @@ resource "cloudflare_dns_record" "prowlarr" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "prowlarr"
|
name = "prowlarr"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +202,7 @@ resource "cloudflare_dns_record" "radarr" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "radarr"
|
name = "radarr"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +211,7 @@ resource "cloudflare_dns_record" "readarr" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "readarr"
|
name = "readarr"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +220,7 @@ resource "cloudflare_dns_record" "request" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "request"
|
name = "request"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -229,7 +229,7 @@ resource "cloudflare_dns_record" "rss" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "rss"
|
name = "rss"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = true
|
proxied = true
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +238,7 @@ resource "cloudflare_dns_record" "sonarr" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "sonarr"
|
name = "sonarr"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -247,7 +247,7 @@ resource "cloudflare_dns_record" "soulseek" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "soulseek"
|
name = "soulseek"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -256,7 +256,7 @@ resource "cloudflare_dns_record" "status" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "status"
|
name = "status"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = true
|
proxied = true
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +265,7 @@ resource "cloudflare_dns_record" "thiswebsitedoesnotexist" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "thiswebsitedoesnotexist"
|
name = "thiswebsitedoesnotexist"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = true
|
proxied = true
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +274,7 @@ resource "cloudflare_dns_record" "webdav" {
|
||||||
zone_id = cloudflare_zone.pez-sh.id
|
zone_id = cloudflare_zone.pez-sh.id
|
||||||
name = "webdav"
|
name = "webdav"
|
||||||
type = "A"
|
type = "A"
|
||||||
content = "65.108.48.44"
|
content = hcloud_server.helsinki-a.ipv4_address
|
||||||
proxied = false
|
proxied = false
|
||||||
ttl = 1
|
ttl = 1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
39
terraform/hetzner_compute.tf
Normal file
39
terraform/hetzner_compute.tf
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
resource "hcloud_server" "nuremberg-a" {
|
||||||
|
name = "nuremberg-a"
|
||||||
|
image = "debian-13"
|
||||||
|
server_type = "cx23"
|
||||||
|
|
||||||
|
location = "nbg1"
|
||||||
|
delete_protection = true
|
||||||
|
rebuild_protection = true
|
||||||
|
keep_disk = true
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"role" = "mail"
|
||||||
|
}
|
||||||
|
|
||||||
|
public_net {
|
||||||
|
ipv4_enabled = true
|
||||||
|
ipv6_enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_server" "helsinki-a" {
|
||||||
|
name = "helsinki-a"
|
||||||
|
image = "debian-13"
|
||||||
|
server_type = "cax11"
|
||||||
|
|
||||||
|
location = "hel1"
|
||||||
|
delete_protection = true
|
||||||
|
rebuild_protection = true
|
||||||
|
keep_disk = true
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
"role" = "ingress"
|
||||||
|
}
|
||||||
|
|
||||||
|
public_net {
|
||||||
|
ipv4_enabled = true
|
||||||
|
ipv6_enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
192
terraform/hetzner_firewall.tf
Normal file
192
terraform/hetzner_firewall.tf
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
resource "hcloud_firewall" "nuremberg-a" {
|
||||||
|
name = "nuremberg-a"
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "22"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# poste.io mail server ports
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "25"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "80"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "110"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "143"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "443"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "465"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "587"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "993"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "995"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "out"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "any"
|
||||||
|
destination_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "out"
|
||||||
|
protocol = "udp"
|
||||||
|
port = "any"
|
||||||
|
destination_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_firewall_attachment" "nuremberg-a" {
|
||||||
|
firewall_id = hcloud_firewall.nuremberg-a.id
|
||||||
|
server_ids = [
|
||||||
|
hcloud_server.nuremberg-a.id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_firewall" "helsinki-a" {
|
||||||
|
name = "helsinki-a"
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "22"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "80"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "in"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "443"
|
||||||
|
source_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "out"
|
||||||
|
protocol = "tcp"
|
||||||
|
port = "any"
|
||||||
|
destination_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
direction = "out"
|
||||||
|
protocol = "udp"
|
||||||
|
port = "any"
|
||||||
|
destination_ips = [
|
||||||
|
"0.0.0.0/0",
|
||||||
|
"::/0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "hcloud_firewall_attachment" "helsinki-a" {
|
||||||
|
firewall_id = hcloud_firewall.helsinki-a.id
|
||||||
|
server_ids = [
|
||||||
|
hcloud_server.helsinki-a.id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,13 @@ terraform {
|
||||||
cloudflare = {
|
cloudflare = {
|
||||||
source = "cloudflare/cloudflare"
|
source = "cloudflare/cloudflare"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hcloud = {
|
||||||
|
source = "hetznercloud/hcloud"
|
||||||
|
version = "~> 1.45"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
backend "s3" {
|
backend "s3" {
|
||||||
bucket = "pez-infra-tfstate"
|
bucket = "pez-infra-tfstate"
|
||||||
|
|
@ -22,3 +28,8 @@ provider "cloudflare" {
|
||||||
email = local.secrets["cloudflare_email"]
|
email = local.secrets["cloudflare_email"]
|
||||||
api_token = local.secrets["cloudflare_api_key"]
|
api_token = local.secrets["cloudflare_api_key"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
provider "hcloud" {
|
||||||
|
token = local.secrets["hetzner_token"]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,21 @@
|
||||||
cloudflare_email: ENC[AES256_GCM,data:IOxyqjzQbw+9zg==,iv:bvMQ3JncMf2suPpshwsgtRm5h1UlQ6kAEm7cB/ExM3w=,tag:R9ZcED/RaW16wnqG99ym8A==,type:str]
|
cloudflare_email: ENC[AES256_GCM,data:kzVXRWRT7/RUBg==,iv:g9r2gP1BxrBoAighKUIKgO1ZVgfATywSe8I5CX/SJ3A=,tag:TmWfgAfIuQVoz7ddc/7ykQ==,type:str]
|
||||||
cloudflare_api_key: ENC[AES256_GCM,data:z1NWHsh4jJ+QAGILfJuKgkrBjjGKoEh2mlSER3LL8vnG8gMDbVsm9O3hkuMfsMxPsY+zbXs=,iv:sw1+gfPIf8auqdDZO3VTtSOhoi0XNsSca0EbEFWZJuI=,tag:hT9Wjls99sE2jdNVSNQtkQ==,type:str]
|
cloudflare_api_key: ENC[AES256_GCM,data:E5ZjsAQ0toXauqGkkQDR2/OqOKNaObkTlK8tnGS2nXYX4gQZaDrRhi5ufklxxO0yzZD9qHE=,iv:5JwQOIuhx1cK1jns2eIR+N1tkc4m7Ydeiya4DRoYRVg=,tag:9ojmEiG8Dlxe1EuNiv1A2w==,type:str]
|
||||||
backblaze_keyID: ENC[AES256_GCM,data:YneBYL27E8lmSULI9w/HLtizqMrk5nDu2Q==,iv:/gNeG2yy4Em/SIjh7i2tGV+8+KYk/d4/UHceDBM6II8=,tag:pfN0ghvcUDQxYKZdIrWUfQ==,type:str]
|
backblaze_keyID: ENC[AES256_GCM,data:mwAeG2OuxSZ95jZZ5qhJGjePtNbo5wUa2w==,iv:uRSZQsMA6sUCvaQOnRZxgdQWS/TpyjFC8nBksOH2yQE=,tag:yhjjiivBkJkhb42nfPju1A==,type:str]
|
||||||
backblaze_keyName: ENC[AES256_GCM,data:9tKnmmQWDTO3FHZ3D01Isvo=,iv:wLdbiPj5rgIn9Yeu5w+tOnJ2PdRtCFQLP4rncZHxN6w=,tag:ADwSi5oz613meQjPa3kshw==,type:str]
|
backblaze_keyName: ENC[AES256_GCM,data:HIxN7kPJPnJDp/pR/yWdayU=,iv:fk9lrFJmlZTnb1lk4AdERS+YPics1XXDOq3McBMhSGU=,tag:Sa3Z+qFs8yBmGA5FLRC/xA==,type:str]
|
||||||
backblaze_applicationKey: ENC[AES256_GCM,data:veIMwboFDx414vVp+kKw2uYRraayZ1DUswTKQMjfsg==,iv:dYdDd71uNPURiPGuieastA4/TtskVNq6uwsDM6Dl1JQ=,tag:jMnV0ydgTrq3zl6F6V5PPQ==,type:str]
|
backblaze_applicationKey: ENC[AES256_GCM,data:0J/NTaQe+uvJXc9FgGLN4xl4EHKOxKeSjXya+wC0pA==,iv:f8w7Ir+pVs/0yD/5FFLTnlYFrw95aq73Q+r1eBZedho=,tag:cz9aMPiHWE8iIKBEA3G6xw==,type:str]
|
||||||
|
hetzner_token: ENC[AES256_GCM,data:kUi0EJlK8xuILT7dp8ql2VQCT/t2DJCtQoXrnC52sr2y73uH4QlSGbYwrJbE+0ZgAeB2l43i8cSvW6MWUt/lrA==,iv:zrshjeeb1oQV6OHhLdXQwwhW8ssN0yHvjbjPxgYgOJk=,tag:hOy8bJuDjNJkQ0URfVwoQA==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1r8uh2w2qad2z5sgq9q7l73962q2sp8zz9hdnh6sjuvanxl565vmswn8squ
|
- recipient: age1r8uh2w2qad2z5sgq9q7l73962q2sp8zz9hdnh6sjuvanxl565vmswn8squ
|
||||||
enc: |
|
enc: |
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyOHlsaHZKRzJLUjhTamha
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtWTFiajV2cThSN240YVEr
|
||||||
cmtFN0J3eEFNaERDNDFlbUd0dWIxV25tMVRBClJIZU55N1lLTFYxblRXd3dma0pX
|
SlpOZUV1WVZkeXdOUXJJNnRpOXlOVnNCRGg4Cklxam1uaFgwMy9UU01STlBBSFhT
|
||||||
UnZzeGoyMHR0UWxkM3RaNmloUTBFUHMKLS0tIHB5TmdIWEY4dWJUQWNZcVUwV1or
|
ZXNQSU1jQXJUZW5HWDEvVWdEUnhzS2MKLS0tIHBYMWJFYStyZVpMMXQ5MUowMy80
|
||||||
ekhtYkVLZ1hBbEZEakhXeUh0UW94QTgKdEY6mwWVQpMtaAYn+tnXFUvBk9QvzFX4
|
ZTdhWjkzTzRDZy8rM2J4TzhmRFFnaUkKt50w9Oq2O5qdo2NMlWo9S8V4m3X6MQG6
|
||||||
ai91WDaO/iRtHluOSp5HxRVh2BNO4uH4opXQEthUIkQzLGtDTUN1uw==
|
Jx/Oit+4DOCFHpL7yxggdD83NJw+0c6kMSB968J/M0EmRAzoYHqFBw==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2026-03-22T21:04:06Z"
|
lastmodified: "2026-03-29T18:58:01Z"
|
||||||
mac: ENC[AES256_GCM,data:6nWRb9Ne7YlcgAiJQAPx7zO51Fb2qAIup5qUG72b3s+XHbutTO5KGefWEx4/flmQx+ctbQ8fRWPOxBHECnB2xVkU0OgehGWAxKXpalnDSMp3cSjXE/Zjisd6H3U5gm8ilRysfCQE1SL8RvZCWWsKI3v89acP+ADYcU9NNOHswbc=,iv:qiWX7JFgsNgwjRPTYNNORDRUj96HRaVopN69qTAD+pM=,tag:qHw27PIvY2hhcYTLY4VPnQ==,type:str]
|
mac: ENC[AES256_GCM,data:q9lEwaxcWAquQP+Dzg1J5WqM2cwcync9EUSVHxtc0peGAxJzg4afHlJi35mC5PZbzv/4wOpdxFR89r9jF3isvvZ6icHcRKmWmlNEl2YCI7VAKIZXZHPx56xXZoj1pOQwNNmEZgAwcreskAINjNIkP6+eIzUDCZ2QRMEK3ok9cHE=,iv:LxtYfXnwfrLmH5w7N36GGRvy1+MpgcoEzm8+KA+QjjI=,tag:/2fIIlNmJcBAXJOyZuotug==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.12.2
|
version: 3.12.2
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue