diff --git a/modules/k3s/k3s.nix b/modules/k3s/k3s.nix new file mode 100644 index 0000000..6c86640 --- /dev/null +++ b/modules/k3s/k3s.nix @@ -0,0 +1,26 @@ +{ + networking.firewall.allowedTCPPorts = [ 6443 80 443 10000 33073 ]; + networking.firewall.allowedUDPPorts = [ 3478 ]; + networking.firewall.allowedUDPPortRanges = [ + { from = 49152; to = 65535; } + ]; + + services.k3s = { + enable = true; + role = "server"; + manifests = { + traefik-namespace = { source = ./traefik/namespace.yaml; }; + traefik-rbac = { source = ./traefik/rbac.yaml; }; + traefik-pvc = { source = ./traefik/pvc.yaml; }; + traefik-deployment = { source = ./traefik/deployment.yaml; }; + traefik-service = { source = ./traefik/service.yaml; }; + netbird-namespace = { source = ./netbird/namespace.yaml; }; + netbird-secrets = { source = ./netbird/secrets.yaml; }; + netbird-coturn = { source = ./netbird/coturn.yaml; }; + netbird-signal = { source = ./netbird/signal.yaml; }; + netbird-management = { source = ./netbird/management.yaml; }; + netbird-relay = { source = ./netbird/relay.yaml; }; + netbird-ingress = { source = ./netbird/ingress.yaml; }; + }; + }; +} diff --git a/modules/k3s/netbird/coturn.yaml b/modules/k3s/netbird/coturn.yaml new file mode 100644 index 0000000..fa1ae0f --- /dev/null +++ b/modules/k3s/netbird/coturn.yaml @@ -0,0 +1,31 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: coturn + namespace: netbird +spec: + selector: + matchLabels: + app: coturn + template: + metadata: + labels: + app: coturn + spec: + hostNetwork: true + containers: + - name: coturn + image: coturn/coturn + args: + - --log-file=stdout + - --external-ip=archfox.org + - --listening-port=3478 + - --min-port=49152 + - --max-port=65535 + - --tls-listening-port=5349 + - --no-tls + - --no-dtls + - --realm=netbird.archfox.org + securityContext: + capabilities: + add: ["NET_BIND_SERVICE"] diff --git a/modules/k3s/netbird/ingress.yaml b/modules/k3s/netbird/ingress.yaml new file mode 100644 index 0000000..2f007a4 --- /dev/null +++ b/modules/k3s/netbird/ingress.yaml @@ -0,0 +1,33 @@ +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: netbird-management + namespace: netbird +spec: + entryPoints: + - websecure + routes: + - match: Host(`netbird.archfox.org`) && PathPrefix(`/management.ManagementService/`) + kind: Rule + services: + - name: management + port: 80 + scheme: h2c + - match: Host(`netbird.archfox.org`) && PathPrefix(`/api/`) + kind: Rule + services: + - name: management + port: 80 + - match: Host(`netbird.archfox.org`) && PathPrefix(`/signalexchange.SignalExchange/`) + kind: Rule + services: + - name: signal + port: 10000 + scheme: h2c + - match: Host(`netbird.archfox.org`) && PathPrefix(`/relay`) + kind: Rule + services: + - name: relay + port: 33073 + tls: + certResolver: letsencrypt diff --git a/modules/k3s/netbird/management.yaml b/modules/k3s/netbird/management.yaml new file mode 100644 index 0000000..be1617f --- /dev/null +++ b/modules/k3s/netbird/management.yaml @@ -0,0 +1,62 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: management + namespace: netbird +spec: + replicas: 1 + selector: + matchLabels: + app: management + template: + metadata: + labels: + app: management + spec: + containers: + - name: management + image: netbirdio/management:latest + args: + - --port=80 + - --log-file=stdout + - --log-level=info + - --disable-anonymous-metrics=false + - --single-account-mode-domain=netbird.archfox.org + - --dns-domain=netbird.archfox.org + env: + - name: NETBIRD_STORE_ENGINE + value: "sqlite" + ports: + - containerPort: 80 + volumeMounts: + - name: mgmt-data + mountPath: /var/lib/netbird + volumes: + - name: mgmt-data + persistentVolumeClaim: + claimName: mgmt-data +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mgmt-data + namespace: netbird +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 2Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: management + namespace: netbird +spec: + selector: + app: management + ports: + - name: http + port: 80 + targetPort: 80 diff --git a/modules/k3s/netbird/namespace.yaml b/modules/k3s/netbird/namespace.yaml new file mode 100644 index 0000000..db05a13 --- /dev/null +++ b/modules/k3s/netbird/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: netbird diff --git a/modules/k3s/netbird/relay.yaml b/modules/k3s/netbird/relay.yaml new file mode 100644 index 0000000..ad8f51c --- /dev/null +++ b/modules/k3s/netbird/relay.yaml @@ -0,0 +1,45 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: relay + namespace: netbird +spec: + replicas: 1 + selector: + matchLabels: + app: relay + template: + metadata: + labels: + app: relay + spec: + containers: + - name: relay + image: netbirdio/relay:latest + env: + - name: NB_LOG_LEVEL + value: "info" + - name: NB_LISTEN_ADDRESS + value: ":33073" + - name: NB_EXPOSED_ADDRESS + value: "rels://netbird.archfox.org:443/relay" + - name: NB_AUTH_SECRET + valueFrom: + secretKeyRef: + name: netbird-secrets + key: relay-auth-secret + ports: + - containerPort: 33073 +--- +apiVersion: v1 +kind: Service +metadata: + name: relay + namespace: netbird +spec: + selector: + app: relay + ports: + - name: relay + port: 33073 + targetPort: 33073 diff --git a/modules/k3s/netbird/secrets.yaml b/modules/k3s/netbird/secrets.yaml new file mode 100644 index 0000000..7553639 --- /dev/null +++ b/modules/k3s/netbird/secrets.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: netbird-secrets + namespace: netbird +type: Opaque +stringData: + # Generate with: openssl rand -base64 32 + relay-auth-secret: "CHANGE_ME_openssl_rand_-base64_32" diff --git a/modules/k3s/netbird/signal.yaml b/modules/k3s/netbird/signal.yaml new file mode 100644 index 0000000..f6db99b --- /dev/null +++ b/modules/k3s/netbird/signal.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: signal + namespace: netbird +spec: + replicas: 1 + selector: + matchLabels: + app: signal + template: + metadata: + labels: + app: signal + spec: + containers: + - name: signal + image: netbirdio/signal:latest + env: + - name: COALESCE_INTERVAL + value: "5s" + ports: + - containerPort: 10000 + volumeMounts: + - name: signal-data + mountPath: /var/lib/netbird + volumes: + - name: signal-data + persistentVolumeClaim: + claimName: signal-data +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: signal-data + namespace: netbird +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: signal + namespace: netbird +spec: + selector: + app: signal + ports: + - name: grpc + port: 10000 + targetPort: 10000 diff --git a/modules/k3s/traefik/deployment.yaml b/modules/k3s/traefik/deployment.yaml new file mode 100644 index 0000000..4cca7be --- /dev/null +++ b/modules/k3s/traefik/deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: traefik + namespace: traefik +spec: + replicas: 1 + selector: + matchLabels: + app: traefik + template: + metadata: + labels: + app: traefik + spec: + serviceAccountName: traefik + containers: + - name: traefik + image: traefik:v3.4 + args: + - --log.level=INFO + - --api.dashboard=true + - --entrypoints.web.address=:80 + - --entrypoints.websecure.address=:443 + - --entrypoints.web.http.redirections.entrypoint.to=websecure + - --entrypoints.web.http.redirections.entrypoint.scheme=https + - --providers.kubernetescrd=true + - --providers.kubernetesingress=true + - --certificatesresolvers.letsencrypt.acme.email=poslop@archfox.org + - --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json + - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web + ports: + - name: web + containerPort: 80 + - name: websecure + containerPort: 443 + volumeMounts: + - name: acme-storage + mountPath: /data + volumes: + - name: acme-storage + persistentVolumeClaim: + claimName: traefik-acme diff --git a/modules/k3s/traefik/namespace.yaml b/modules/k3s/traefik/namespace.yaml new file mode 100644 index 0000000..c088a91 --- /dev/null +++ b/modules/k3s/traefik/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: traefik diff --git a/modules/k3s/traefik/pvc.yaml b/modules/k3s/traefik/pvc.yaml new file mode 100644 index 0000000..46187de --- /dev/null +++ b/modules/k3s/traefik/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: traefik-acme + namespace: traefik +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 128Mi diff --git a/modules/k3s/traefik/rbac.yaml b/modules/k3s/traefik/rbac.yaml new file mode 100644 index 0000000..4d937e8 --- /dev/null +++ b/modules/k3s/traefik/rbac.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: traefik + namespace: traefik +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: traefik +rules: + - apiGroups: [""] + resources: ["services", "endpoints", "secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["extensions", "networking.k8s.io"] + resources: ["ingresses", "ingressclasses"] + verbs: ["get", "list", "watch"] + - apiGroups: ["extensions", "networking.k8s.io"] + resources: ["ingresses/status"] + verbs: ["update"] + - apiGroups: ["traefik.io"] + resources: ["ingressroutes", "ingressroutetcps", "ingressrouteudps", "middlewares", + "middlewaretcps", "tlsoptions", "tlsstores", "traefikservices", + "serverstransports", "serverstransporttcps"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: traefik +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: traefik +subjects: + - kind: ServiceAccount + name: traefik + namespace: traefik diff --git a/modules/k3s/traefik/service.yaml b/modules/k3s/traefik/service.yaml new file mode 100644 index 0000000..04377c8 --- /dev/null +++ b/modules/k3s/traefik/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: traefik + namespace: traefik +spec: + type: LoadBalancer + selector: + app: traefik + ports: + - name: web + port: 80 + targetPort: 80 + - name: websecure + port: 443 + targetPort: 443