From 674ce6957cd04efb96899bb0a8475ce5426136df Mon Sep 17 00:00:00 2001 From: m3tm3re
Date: Sat, 28 Feb 2026 10:06:42 +0100
Subject: [PATCH] feat: authentik
---
hosts/common/ports.nix | 4 +-
hosts/m3-atlas/secrets.nix | 5 +-
.../services/containers/authentik.nix | 67 ++++++
.../m3-atlas/services/containers/default.nix | 1 +
.../m3-atlas/services/containers/netbird.nix | 3 +-
.../m3-atlas/services/containers/pangolin.nix | 211 ------------------
hosts/m3-atlas/services/default.nix | 1 +
hosts/m3-atlas/services/netbird.nix | 3 +
hosts/m3-atlas/services/postgres.nix | 3 +-
hosts/m3-kratos/services/default.nix | 1 +
hosts/m3-kratos/services/netbird.nix | 5 +
secrets.nix | 1 +
secrets/authentik-env.age | Bin 0 -> 1230 bytes
13 files changed, 84 insertions(+), 221 deletions(-)
create mode 100644 hosts/m3-atlas/services/containers/authentik.nix
delete mode 100644 hosts/m3-atlas/services/containers/pangolin.nix
create mode 100644 hosts/m3-atlas/services/netbird.nix
create mode 100644 hosts/m3-kratos/services/netbird.nix
create mode 100644 secrets/authentik-env.age
diff --git a/hosts/common/ports.nix b/hosts/common/ports.nix
index a288156..b8e0715 100644
--- a/hosts/common/ports.nix
+++ b/hosts/common/ports.nix
@@ -37,9 +37,7 @@
slash-nemoti = 3016;
kestra = 3018;
outline = 3019;
- pangolin = 3020;
- pangolin-api = 3021;
- pangolin-ws = 3022;
+ authentik = 3023;
# Home automation
homarr = 7575;
diff --git a/hosts/m3-atlas/secrets.nix b/hosts/m3-atlas/secrets.nix
index adaf06d..330fa31 100644
--- a/hosts/m3-atlas/secrets.nix
+++ b/hosts/m3-atlas/secrets.nix
@@ -56,10 +56,6 @@
file = ../../secrets/exa-key.age;
owner = "m3tam3re";
};
- outline-key = {
- file = ../../secrets/outline-key.age;
- owner = "m3tam3re";
- };
basecamp-client-id = {
file = ../../secrets/basecamp-client-id.age;
owner = "m3tam3re";
@@ -68,6 +64,7 @@
file = ../../secrets/basecamp-client-secret.age;
owner = "m3tam3re";
};
+ authentik-env = {file = ../../secrets/authentik-env.age;};
};
};
}
diff --git a/hosts/m3-atlas/services/containers/authentik.nix b/hosts/m3-atlas/services/containers/authentik.nix
new file mode 100644
index 0000000..6712066
--- /dev/null
+++ b/hosts/m3-atlas/services/containers/authentik.nix
@@ -0,0 +1,67 @@
+{config, ...}: let
+ image = "ghcr.io/goauthentik/server:2026.2.0";
+
+ serverIp = "10.89.0.22";
+ workerIp = "10.89.0.23";
+
+ postgresHost = "10.89.0.1";
+ postgresPort = config.m3ta.ports.get "postgres";
+ authentikPort = config.m3ta.ports.get "authentik";
+
+ sharedEnv = {
+ AUTHENTIK_POSTGRESQL__HOST = postgresHost;
+ AUTHENTIK_POSTGRESQL__PORT = toString postgresPort;
+ AUTHENTIK_POSTGRESQL__USER = "authentik";
+ AUTHENTIK_POSTGRESQL__NAME = "authentik";
+ };
+in {
+ virtualisation.oci-containers.containers = {
+ "authentik-server" = {
+ inherit image;
+ cmd = ["server"];
+ environment = sharedEnv;
+ environmentFiles = [config.age.secrets.authentik-env.path];
+ ports = ["127.0.0.1:${toString authentikPort}:9000"];
+ volumes = [
+ "authentik_media:/media"
+ "authentik_templates:/templates"
+ ];
+ extraOptions = [
+ "--add-host=postgres:${postgresHost}"
+ "--ip=${serverIp}"
+ "--network=web"
+ ];
+ };
+
+ "authentik-worker" = {
+ inherit image;
+ cmd = ["worker"];
+ user = "root";
+ environment = sharedEnv;
+ environmentFiles = [config.age.secrets.authentik-env.path];
+ volumes = [
+ "authentik_media:/media"
+ "authentik_certs:/certs"
+ "authentik_templates:/templates"
+ ];
+ extraOptions = [
+ "--add-host=postgres:${postgresHost}"
+ "--ip=${workerIp}"
+ "--network=web"
+ ];
+ };
+ };
+
+ services.traefik.dynamicConfigOptions.http = {
+ services.authentik.loadBalancer.servers = [
+ {url = "http://localhost:${toString authentikPort}/";}
+ ];
+
+ routers.authentik = {
+ rule = "Host(`auth.m3ta.dev`)";
+ tls = {certResolver = "godaddy";};
+ service = "authentik";
+ entrypoints = "websecure";
+ };
+ };
+}
diff --git a/hosts/m3-atlas/services/containers/default.nix b/hosts/m3-atlas/services/containers/default.nix
index f3399fd..2579a67 100644
--- a/hosts/m3-atlas/services/containers/default.nix
+++ b/hosts/m3-atlas/services/containers/default.nix
@@ -11,6 +11,7 @@
./restreamer.nix
./slash.nix
./slash-nemoti.nix
+ ./authentik.nix
];
system.activationScripts.createPodmanNetworkWeb = lib.mkAfter ''
if ! /run/current-system/sw/bin/podman network exists web; then
diff --git a/hosts/m3-atlas/services/containers/netbird.nix b/hosts/m3-atlas/services/containers/netbird.nix
index 605cc70..2b67dba 100644
--- a/hosts/m3-atlas/services/containers/netbird.nix
+++ b/hosts/m3-atlas/services/containers/netbird.nix
@@ -1,6 +1,5 @@
{
config,
- lib,
pkgs,
...
}: let
@@ -42,7 +41,7 @@
auth = {
issuer = "https://${domain}/oauth2";
- # localAuthDisabled = true;
+ localAuthDisabled = true;
signKeyRefreshEnabled = true;
dashboardRedirectURIs = [
"https://${domain}/nb-auth"
diff --git a/hosts/m3-atlas/services/containers/pangolin.nix b/hosts/m3-atlas/services/containers/pangolin.nix
deleted file mode 100644
index 0bf5a34..0000000
--- a/hosts/m3-atlas/services/containers/pangolin.nix
+++ /dev/null
@@ -1,211 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}: let
- # Define the Pangolin configuration as a Nix attribute set
- pangolinConfig = {
- app = {
- dashboard_url = "https://vpn.m3tam3re.com";
- log_level = "info";
- save_logs = false;
- };
-
- domains = {
- vpn = {
- base_domain = "m3tam3re.com";
- cert_resolver = "godaddy";
- prefer_wildcard_cert = false;
- };
- };
-
- server = {
- external_port = 3000;
- internal_port = 3001;
- next_port = 3002;
- internal_hostname = "pangolin";
- session_cookie_name = "p_session_token";
- resource_access_token_param = "p_token";
- resource_session_request_param = "p_session_request";
- };
-
- traefik = {
- cert_resolver = "godaddy";
- http_entrypoint = "web";
- https_entrypoint = "websecure";
- };
-
- gerbil = {
- start_port = 51820;
- base_endpoint = "vpn.m3tam3re.com";
- use_subdomain = false;
- block_size = 24;
- site_block_size = 30;
- subnet_group = "100.89.137.0/20";
- };
-
- rate_limits = {
- global = {
- window_minutes = 1;
- max_requests = 100;
- };
- };
-
- email = {
- smtp_host = config.age.secrets.smtp-host.path;
- smtp_port = 587;
- smtp_user = config.age.secrets.smtp-user.path;
- smtp_pass = config.age.secrets.smtp-pass.path;
- no_reply = config.age.secrets.smtp-user.path;
- };
-
- users = {
- server_admin = {
- email = "admin@m3tam3re.com";
- password = config.age.secrets.pangolin-admin-password.path;
- };
- };
-
- flags = {
- require_email_verification = true;
- disable_signup_without_invite = true;
- disable_user_create_org = true;
- allow_raw_resources = true;
- allow_base_domain_resources = true;
- };
- };
-
- # Convert Nix attribute set to YAML using a simpler approach
- pangolinConfigYaml = pkgs.writeTextFile {
- name = "config.yml";
- text = lib.generators.toYAML {} pangolinConfig;
- };
-in {
- # Define the containers
- virtualisation.oci-containers.containers = {
- "pangolin" = {
- image = "fosrl/pangolin:1.1.0";
- autoStart = true;
- volumes = [
- "${pangolinConfigYaml}:/app/config/config.yml:ro" # Mount the config file directly
- "pangolin_config:/app/config/data" # Volume for persistent data
- ];
- ports = [
- "127.0.0.1:3020:3001" # API server
- "127.0.0.1:3021:3002" # Next.js server
- "127.0.0.1:3022:3000" # API/WebSocket server
- ];
- extraOptions = ["--ip=10.89.0.20" "--network=web"];
- };
-
- "gerbil" = {
- image = "fosrl/gerbil:1.0.0";
- autoStart = true;
- volumes = [
- "pangolin_config:/var/config" # Share the volume for persistent data
- ];
- cmd = [
- "--reachableAt=http://gerbil:3003"
- "--generateAndSaveKeyTo=/var/config/key"
- "--remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config"
- "--reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth"
- ];
- ports = [
- "51820:51820/udp" # WireGuard port
- ];
- extraOptions = [
- "--ip=10.89.0.21"
- "--network=web"
- "--cap-add=NET_ADMIN"
- "--cap-add=SYS_MODULE"
- ];
- };
- };
-
- # Secrets for Pangolin
- # age.secrets = {
- # "smtp-host" = {
- # file = ../secrets/smtp-host.age;
- # owner = "root";
- # group = "root";
- # mode = "0400";
- # };
- # "smtp-user" = {
- # file = ../secrets/smtp-user.age;
- # owner = "root";
- # group = "root";
- # mode = "0400";
- # };
- # "smtp-pass" = {
- # file = ../secrets/smtp-pass.age;
- # owner = "root";
- # group = "root";
- # mode = "0400";
- # };
- # "pangolin-admin-password" = {
- # file = ../secrets/pangolin-admin-password.age;
- # owner = "root";
- # group = "root";
- # mode = "0400";
- # };
- # };
-
- # Traefik configuration for Pangolin
- services.traefik.dynamicConfigOptions = {
- http = {
- # Next.js service (front-end)
- services.pangolin-next-service.loadBalancer.servers = [
- {url = "http://localhost:3021";}
- ];
-
- # API service
- services.pangolin-api-service.loadBalancer.servers = [
- {url = "http://localhost:3022";}
- ];
-
- # Routers
- routers = {
- # Next.js router (handles everything except API paths)
- "pangolin-next" = {
- rule = "Host(`vpn.m3tam3re.com`) && !PathPrefix(`/api/v1`)";
- service = "pangolin-next-service";
- entrypoints = ["websecure"];
- tls = {
- certResolver = "godaddy";
- };
- };
-
- # API router
- "pangolin-api" = {
- rule = "Host(`vpn.m3tam3re.com`) && PathPrefix(`/api/v1`)";
- service = "pangolin-api-service";
- entrypoints = ["websecure"];
- tls = {
- certResolver = "godaddy";
- };
- };
- };
- };
- };
-
- # Add HTTP provider to Traefik for dynamic configuration from Pangolin
- services.traefik.staticConfigOptions.providers.http = {
- endpoint = "http://localhost:3020/api/v1/traefik-config";
- pollInterval = "5s";
- };
-
- # Add experimental section for Badger plugin
- services.traefik.staticConfigOptions.experimental = {
- plugins = {
- #TODO create an overlay for the plugin
- badger = {
- moduleName = "github.com/fosrl/badger";
- version = "v1.0.0";
- };
- };
- };
-
- # Firewall configuration for WireGuard
- networking.firewall.allowedUDPPorts = [51820]; # WireGuard port
-}
diff --git a/hosts/m3-atlas/services/default.nix b/hosts/m3-atlas/services/default.nix
index 6a49f8d..5a7b668 100644
--- a/hosts/m3-atlas/services/default.nix
+++ b/hosts/m3-atlas/services/default.nix
@@ -5,6 +5,7 @@
./gitea-actions-runner.nix
./minio.nix
./mysql.nix
+ ./netbird.nix
./n8n.nix
./paperless.nix
./postgres.nix
diff --git a/hosts/m3-atlas/services/netbird.nix b/hosts/m3-atlas/services/netbird.nix
new file mode 100644
index 0000000..580d4fa
--- /dev/null
+++ b/hosts/m3-atlas/services/netbird.nix
@@ -0,0 +1,3 @@
+{
+ services.netbird.enable = true;
+}
diff --git a/hosts/m3-atlas/services/postgres.nix b/hosts/m3-atlas/services/postgres.nix
index ee7de06..85658d2 100644
--- a/hosts/m3-atlas/services/postgres.nix
+++ b/hosts/m3-atlas/services/postgres.nix
@@ -27,6 +27,7 @@
host baserow baserow 10.89.0.0/24 scram-sha-256
host kestra kestra 10.89.0.0/24 scram-sha-256
host netbird netbird 10.89.0.0/24 scram-sha-256
+ host authentik authentik 10.89.0.0/24 scram-sha-256
# Deny all other connections
local all all reject
@@ -37,7 +38,7 @@
services.postgresqlBackup = {
enable = true;
startAt = "03:10:00";
- databases = ["baserow" "paperless" "kestra"];
+ databases = ["baserow" "paperless" "kestra" "authentik" "netbird"];
};
networking.firewall = {
extraCommands = ''
diff --git a/hosts/m3-kratos/services/default.nix b/hosts/m3-kratos/services/default.nix
index dc1d637..f29e14d 100644
--- a/hosts/m3-kratos/services/default.nix
+++ b/hosts/m3-kratos/services/default.nix
@@ -3,6 +3,7 @@
./containers
./mem0.nix
./n8n.nix
+ ./netbird.nix
./postgres.nix
./sound.nix
./udev.nix
diff --git a/hosts/m3-kratos/services/netbird.nix b/hosts/m3-kratos/services/netbird.nix
new file mode 100644
index 0000000..8a73d6e
--- /dev/null
+++ b/hosts/m3-kratos/services/netbird.nix
@@ -0,0 +1,5 @@
+{pkgs, ...}: {
+ services.netbird.enable = true;
+ environment.systemPackages = [pkgs.netbird-ui];
+ networking.firewall.checkReversePath = "loose";
+}
diff --git a/secrets.nix b/secrets.nix
index 4d8e9d2..a578235 100644
--- a/secrets.nix
+++ b/secrets.nix
@@ -13,6 +13,7 @@ let
in {
"secrets/anytype-key.age".publicKeys = systems ++ users;
"secrets/anytype-key-ares.age".publicKeys = systems ++ users;
+ "secrets/authentik-env.age".publicKeys = systems ++ users;
"secrets/baserow-env.age".publicKeys = systems ++ users;
"secrets/ghost-env.age".publicKeys = systems ++ users;
"secrets/littlelink-m3tam3re.age".publicKeys = systems ++ users;
diff --git a/secrets/authentik-env.age b/secrets/authentik-env.age
new file mode 100644
index 0000000000000000000000000000000000000000..1de2de45597bf384d51aa3bafd26742e8424c684
GIT binary patch
literal 1230
zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCSP@$>O6DpyGIN{