diff --git a/nix/homelab/config.toml b/nix/homelab/config.toml index c90c5b2..5f26a4e 100644 --- a/nix/homelab/config.toml +++ b/nix/homelab/config.toml @@ -7,9 +7,22 @@ routes = [ port = 3000, private = false }, + { + kind = "TCP", + name = "gitea-ssh", + namespace = "git", + service = "gitea-ssh", + port = 22, + private = false + }, + { + name = "home-assistant", + namespace = "home", + port = 8123, + private = true + }, { name = "sonarr", - hostname = "sonarr", namespace = "media", port = 8787, private = true @@ -24,10 +37,51 @@ routes = [ }, { name = "pihole", - hostname = "pihole", namespace = "pihole-system", service = "pihole-web", port = 80, private = true - } + }, + { + kind = "TCP", + name = "minecraft-router", + hostname = "minecraft", + namespace = "minecraft", + service = "minecraft-router-mc-router", + port = 25565, + private = false + }, + { + name = "prowlarr", + namespace = "media", + port = 9696, + private = true + }, + { + name = "radarr", + namespace = "media", + port = 7878, + private = true + }, + { + name = "qbittorrent", + hostname = "qbit", + namespace = "media", + port = 8090, + private = true + }, + { + name = "flaresolverr", + hostname = "flare", + namespace = "media", + port = 8191, + private = true + }, + { + name = "jellyfin", + hostname = "media", + namespace = "media", + port = 8096, + private = true + }, ] diff --git a/nix/homelab/kustomize/kustomization.yaml b/nix/homelab/kustomize/kustomization.yaml index dd46872..83e6c2f 100644 --- a/nix/homelab/kustomize/kustomization.yaml +++ b/nix/homelab/kustomize/kustomization.yaml @@ -7,13 +7,5 @@ resources: - ./traefik/private-networks.yaml - ./traefik/chains.yaml - ./cert-manager/config.yaml - - ./routes/minecraft.yaml - - ./routes/gitea/ssh.yaml - - ./routes/gitea/http.yaml - - ./routes/longhorn.yaml - - ./routes/home-assistant.yaml - - ./routes/consul-media.yaml - - ./routes/consul-vaultwarden.yaml - - ./routes/pihole.yaml - - ./routes/media/sonarr.yaml + - ./routes.yaml - ./media/sonarr.yaml diff --git a/nix/homelab/kustomize/routes.yaml b/nix/homelab/kustomize/routes.yaml index 5b1cf7c..4f80444 100644 --- a/nix/homelab/kustomize/routes.yaml +++ b/nix/homelab/kustomize/routes.yaml @@ -14,6 +14,42 @@ spec: - name: gitea-http port: 3000 --- +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: gitea-ssh + namespace: git +spec: + entryPoints: + - gitea-ssh + routes: + - match: HostSNI(`*`) + services: + - name: gitea-ssh + port: 22 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: home-assistant + namespace: home +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - home-assistant.lucalise.ca + rules: + - backendRefs: + - name: home-assistant + port: 8123 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: @@ -73,6 +109,130 @@ spec: - backendRefs: - name: pihole-web port: 80 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: minecraft-router + namespace: minecraft +spec: + entryPoints: + - minecraft-router + routes: + - match: HostSNI(`*`) + services: + - name: minecraft-router-mc-router + port: 25565 +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: prowlarr + namespace: media +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - prowlarr.lucalise.ca + rules: + - backendRefs: + - name: prowlarr + port: 9696 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: radarr + namespace: media +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - radarr.lucalise.ca + rules: + - backendRefs: + - name: radarr + port: 7878 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: qbittorrent + namespace: media +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - qbit.lucalise.ca + rules: + - backendRefs: + - name: qbittorrent + port: 8090 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: flaresolverr + namespace: media +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - flare.lucalise.ca + rules: + - backendRefs: + - name: flaresolverr + port: 8191 + filters: + - type: ExtensionRef + extensionRef: + group: traefik.io + kind: Middleware + name: private-networks +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: jellyfin + namespace: media +spec: + parentRefs: + - name: traefik-gateway + namespace: kube-system + hostnames: + - media.lucalise.ca + rules: + - backendRefs: + - name: jellyfin + port: 8096 filters: - type: ExtensionRef extensionRef: diff --git a/nix/homelab/kustomize/routes/consul-media.yaml b/nix/homelab/kustomize/routes/consul-media.yaml deleted file mode 100644 index 28a675d..0000000 --- a/nix/homelab/kustomize/routes/consul-media.yaml +++ /dev/null @@ -1,233 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: bazarr - namespace: media -spec: - ports: - - port: 6767 - targetPort: 6767 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: bazarr - namespace: media -subsets: - - addresses: - - ip: 192.168.20.20 - ports: - - port: 6767 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: bazarr - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "bazarr.lucalise.ca" - rules: - - backendRefs: - - name: bazarr - port: 6767 ---- -apiVersion: v1 -kind: Service -metadata: - name: prowlarr - namespace: media -spec: - ports: - - port: 9696 - targetPort: 9696 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: prowlarr - namespace: media -subsets: - - addresses: - - ip: 192.168.20.17 - ports: - - port: 9696 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: prowlarr - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "prowlarr.lucalise.ca" - rules: - - backendRefs: - - name: prowlarr - port: 9696 ---- -apiVersion: v1 -kind: Service -metadata: - name: radarr - namespace: media -spec: - ports: - - port: 7878 - targetPort: 7878 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: radarr - namespace: media -subsets: - - addresses: - - ip: 192.168.20.15 - ports: - - port: 7878 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: radarr - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "radarr.lucalise.ca" - rules: - - backendRefs: - - name: radarr - port: 7878 ---- -apiVersion: v1 -kind: Service -metadata: - name: qbittorrent - namespace: media -spec: - ports: - - port: 8090 - targetPort: 8090 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: qbittorrent - namespace: media -subsets: - - addresses: - - ip: 192.168.20.6 - ports: - - port: 8090 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: qbittorrent - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "qbit.lucalise.ca" - rules: - - backendRefs: - - name: qbittorrent - port: 8090 ---- -apiVersion: v1 -kind: Service -metadata: - name: flaresolverr - namespace: media -spec: - ports: - - port: 8191 - targetPort: 8191 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: flaresolverr - namespace: media -subsets: - - addresses: - - ip: 192.168.20.4 - ports: - - port: 8191 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: flaresolverr - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "flare.lucalise.ca" - rules: - - backendRefs: - - name: flaresolverr - port: 8191 ---- -apiVersion: v1 -kind: Service -metadata: - name: jellyfin - namespace: media -spec: - ports: - - port: 8096 - targetPort: 8096 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: jellyfin - namespace: media -subsets: - - addresses: - - ip: 192.168.20.2 - ports: - - port: 8096 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: jellyfin - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "media.lucalise.ca" - rules: - - backendRefs: - - name: jellyfin - port: 8096 diff --git a/nix/homelab/kustomize/routes/consul-vaultwarden.yaml b/nix/homelab/kustomize/routes/consul-vaultwarden.yaml deleted file mode 100644 index 7cefad6..0000000 --- a/nix/homelab/kustomize/routes/consul-vaultwarden.yaml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: vaultwarden ---- -apiVersion: v1 -kind: Service -metadata: - name: vaultwarden - namespace: vaultwarden -spec: - ports: - - port: 8000 - targetPort: 8000 - protocol: TCP ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: vaultwarden - namespace: vaultwarden -subsets: - - addresses: - - ip: 192.168.20.22 - ports: - - port: 8000 - protocol: TCP ---- -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: vaultwarden - namespace: vaultwarden -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "vault.lucalise.ca" - rules: - - backendRefs: - - name: vaultwarden - port: 8000 diff --git a/nix/homelab/kustomize/routes/gitea/http.yaml b/nix/homelab/kustomize/routes/gitea/http.yaml deleted file mode 100644 index abc688b..0000000 --- a/nix/homelab/kustomize/routes/gitea/http.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: gitea - namespace: git -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "git.lucalise.ca" - rules: - - backendRefs: - - name: gitea-http - port: 3000 diff --git a/nix/homelab/kustomize/routes/gitea/ssh.yaml b/nix/homelab/kustomize/routes/gitea/ssh.yaml deleted file mode 100644 index f4984a3..0000000 --- a/nix/homelab/kustomize/routes/gitea/ssh.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: traefik.io/v1alpha1 -kind: IngressRouteTCP -metadata: - name: gitea-ssh - namespace: git -spec: - entryPoints: - - ssh - routes: - - match: HostSNI(`*`) - services: - - name: gitea-ssh - port: 22 diff --git a/nix/homelab/kustomize/routes/home-assistant.yaml b/nix/homelab/kustomize/routes/home-assistant.yaml deleted file mode 100644 index 20e1956..0000000 --- a/nix/homelab/kustomize/routes/home-assistant.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: home-assistant - namespace: media -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "home-assistant.lucalise.ca" - rules: - - filters: - - type: ExtensionRef - extensionRef: - group: traefik.io - kind: Middleware - name: private-networks - backendRefs: - - name: home-assistant - port: 8123 diff --git a/nix/homelab/kustomize/routes/longhorn.yaml b/nix/homelab/kustomize/routes/longhorn.yaml deleted file mode 100644 index b984455..0000000 --- a/nix/homelab/kustomize/routes/longhorn.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: longhorn - namespace: longhorn-system -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "storage.lucalise.ca" - rules: - - filters: - - type: ExtensionRef - extensionRef: - group: traefik.io - kind: Middleware - name: private-networks - backendRefs: - - name: longhorn-frontend - port: 80 diff --git a/nix/homelab/kustomize/routes/minecraft.yaml b/nix/homelab/kustomize/routes/minecraft.yaml deleted file mode 100644 index ea3858b..0000000 --- a/nix/homelab/kustomize/routes/minecraft.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: traefik.io/v1alpha1 -kind: IngressRouteTCP -metadata: - name: minecraft-router - namespace: minecraft -spec: - entryPoints: - - minecraft - routes: - - match: HostSNI(`*`) - services: - - name: minecraft-router-mc-router - port: 25565 diff --git a/nix/homelab/kustomize/routes/pihole.yaml b/nix/homelab/kustomize/routes/pihole.yaml deleted file mode 100644 index 67505f2..0000000 --- a/nix/homelab/kustomize/routes/pihole.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: gateway.networking.k8s.io/v1 -kind: HTTPRoute -metadata: - name: pihole - namespace: pihole-system -spec: - parentRefs: - - name: traefik-gateway - namespace: kube-system - hostnames: - - "pihole.lucalise.ca" - rules: - - filters: - - type: ExtensionRef - extensionRef: - group: traefik.io - kind: Middleware - name: private-networks - backendRefs: - - name: pihole-web - port: 80 diff --git a/nix/homelab/kustomize/traefik/chains.yaml b/nix/homelab/kustomize/traefik/chains.yaml index 6f05fd8..b0e863c 100644 --- a/nix/homelab/kustomize/traefik/chains.yaml +++ b/nix/homelab/kustomize/traefik/chains.yaml @@ -24,7 +24,7 @@ apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: private-networks - namespace: pihole-system + namespace: media spec: chain: middlewares: @@ -35,9 +35,9 @@ apiVersion: traefik.io/v1alpha1 kind: Middleware metadata: name: private-networks - namespace: media + namespace: pihole-system spec: chain: middlewares: - name: private-networks - namespace: kube-system + namespace: kube-system \ No newline at end of file diff --git a/nix/homelab/src/commands/generate_routes.rs b/nix/homelab/src/commands/generate_routes.rs index 9c52206..0f0e7c6 100644 --- a/nix/homelab/src/commands/generate_routes.rs +++ b/nix/homelab/src/commands/generate_routes.rs @@ -1,19 +1,31 @@ +use std::collections::BTreeSet; + use serde::{Deserialize, Serialize}; use crate::{Config, HelperError}; #[derive(Serialize, Deserialize, Default)] pub struct Route { + #[serde(default)] kind: RouteKind, name: String, - hostname: String, + hostname: Option, + entrypoint: Option, namespace: String, service: Option, port: i16, private: bool, } +impl Route { + fn hostname(&self) -> &str { + self.hostname.as_ref().unwrap_or(&self.name) + } +} + +#[derive(Serialize, Deserialize, Default)] enum RouteKind { + #[default] HTTP, TCP, } @@ -30,17 +42,62 @@ pub fn generate_routes(config: &Config) -> Result<(), HelperError> { acc.push_str(&generate_route(r)); acc }); + let chains = generate_chains(&config.routes); std::fs::write("kustomize/routes.yaml", &routes)?; + std::fs::write("kustomize/traefik/chains.yaml", &chains)?; println!("Wrote: {}", routes); Ok(()) } fn generate_route(route: &Route) -> String { + match route.kind { + RouteKind::HTTP => generate_http_route(route), + RouteKind::TCP => generate_tcp_route(route), + } +} + +fn generate_chains(routes: &[Route]) -> String { + let namespaces = routes + .iter() + .filter_map(|r| { + if !r.private { + return None; + } + Some(r.namespace.as_str()) + }) + .collect::>(); + + namespaces + .iter() + .enumerate() + .fold(String::new(), |mut acc, (i, n)| { + if i > 0 { + acc.push_str("\n---\n"); + } + acc.push_str(&format!( + r#"apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: private-networks + namespace: {} +spec: + chain: + middlewares: + - name: private-networks + namespace: kube-system"#, + n + )); + acc + }) +} + +fn generate_http_route(route: &Route) -> String { let mut filters_section = String::new(); if route.private { filters_section = format!( - r#"filters: + r#" + filters: - type: ExtensionRef extensionRef: group: traefik.io @@ -51,7 +108,7 @@ fn generate_route(route: &Route) -> String { format!( r#"apiVersion: gateway.networking.k8s.io/v1 -kind: {} +kind: HTTPRoute metadata: name: {} namespace: {} @@ -64,15 +121,49 @@ spec: rules: - backendRefs: - name: {} - port: {} - {}"#, + port: {}{}"#, route.name, route.namespace, - route.hostname, - route.service.clone().unwrap_or_else(|| route.name.clone()), + route.hostname(), + route.service.as_ref().unwrap_or_else(|| &route.name), route.port, filters_section ) .trim_end() .to_string() } + +fn generate_tcp_route(route: &Route) -> String { + let mut middlewares_section = String::new(); + if route.private { + middlewares_section = format!( + r#" + middlewares: + - name: private-networks"# + ); + } + + format!( + r#"apiVersion: traefik.io/v1alpha1 +kind: IngressRouteTCP +metadata: + name: {} + namespace: {} +spec: + entryPoints: + - {} + routes: + - match: HostSNI(`*`){} + services: + - name: {} + port: {}"#, + route.name, + route.namespace, + route.entrypoint, + middlewares_section, + route.service.as_ref().unwrap_or_else(|| &route.name), + route.port + ) + .trim_end() + .to_string() +}