From 74f191b42a536114c527fcfec58fbf0b37698d66 Mon Sep 17 00:00:00 2001 From: Jakub Dorfman Date: Sun, 26 Apr 2026 15:12:42 +0200 Subject: [PATCH] Add Authelia configuration and secrets management --- .gitignore | 1 + authelia.nix | 84 ++++++++++++++++++++++++++++ caddy.nix | 15 ++++- flake.nix | 1 + secrets.nix | 9 ++- secrets/authelia-jwt-secret.age | 11 ++++ secrets/authelia-session-secret.age | 11 ++++ secrets/authelia-storage-key.age | Bin 0 -> 630 bytes secrets/authelia-users.age | Bin 0 -> 843 bytes 9 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 authelia.nix create mode 100644 secrets/authelia-jwt-secret.age create mode 100644 secrets/authelia-session-secret.age create mode 100644 secrets/authelia-storage-key.age create mode 100644 secrets/authelia-users.age diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3fb0379 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +users.yml diff --git a/authelia.nix b/authelia.nix new file mode 100644 index 0000000..d5b49c0 --- /dev/null +++ b/authelia.nix @@ -0,0 +1,84 @@ +{ config, ... }: +{ + # Give authelia-main user access to its agenix secrets + age.secrets."authelia-jwt-secret" = { + file = ./secrets/authelia-jwt-secret.age; + owner = "authelia-main"; + group = "authelia-main"; + }; + age.secrets."authelia-storage-key" = { + file = ./secrets/authelia-storage-key.age; + owner = "authelia-main"; + group = "authelia-main"; + }; + age.secrets."authelia-session-secret" = { + file = ./secrets/authelia-session-secret.age; + owner = "authelia-main"; + group = "authelia-main"; + }; + age.secrets."authelia-users" = { + file = ./secrets/authelia-users.age; + owner = "authelia-main"; + group = "authelia-main"; + }; + + services.authelia.instances.main = { + enable = true; + + secrets = { + jwtSecretFile = config.age.secrets."authelia-jwt-secret".path; + storageEncryptionKeyFile = config.age.secrets."authelia-storage-key".path; + sessionSecretFile = config.age.secrets."authelia-session-secret".path; + }; + + settings = { + theme = "auto"; + default_2fa_method = "totp"; + + server.address = "tcp://127.0.0.1:9091"; + + log.level = "info"; + + totp = { + issuer = "srazka.com"; + period = 30; + }; + + # File-based user database (simplest, no LDAP needed) + authentication_backend.file = { + path = config.age.secrets."authelia-users".path; + # Periodically re-reads the file; useful for adding users without restart + watch = true; + }; + + # SQLite is the simplest storage - fine for a single VPS + storage.local.path = "/var/lib/authelia-main/db.sqlite3"; + + # No email server needed for a homelab — disable email notifications + notifier.filesystem.filename = "/var/lib/authelia-main/notifications.txt"; + + session = { + expiration = "1h"; + inactivity = "5m"; + remember_me = "1d"; + + cookies = [ + { + domain = "srazka.com"; + authelia_url = "https://auth.srazka.com"; + default_redirection_url = "https://hello.srazka.com"; + } + ]; + }; + + access_control = { + # Every request requires two-factor by default + default_policy = "two_factor"; + # You can add per-domain rules here later, e.g.: + # rules = [ + # { domain = "hello.srazka.com"; policy = "two_factor"; } + # ]; + }; + }; + }; +} diff --git a/caddy.nix b/caddy.nix index c4eafed..2cc1e95 100755 --- a/caddy.nix +++ b/caddy.nix @@ -2,11 +2,20 @@ { services.caddy = { enable = true; - email = "admin@srazka.com"; # Replace with your actual email + email = "admin@srazka.com"; - # The new hello container + # Authelia's own login portal + virtualHosts."auth.srazka.com".extraConfig = '' + reverse_proxy 127.0.0.1:9091 + ''; + + # Every protected site uses this snippet virtualHosts."hello.srazka.com".extraConfig = '' + forward_auth 127.0.0.1:9091 { + uri /api/authz/forward-auth + copy_headers Remote-User Remote-Groups Remote-Email Remote-Name + } reverse_proxy 192.168.100.11:80 ''; }; -} \ No newline at end of file +} diff --git a/flake.nix b/flake.nix index 1f21a5c..f2587f9 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,7 @@ vpsadminos.nixosModules.container_25_11 ./configuration.nix ./caddy.nix + ./authelia.nix ./containers/hello.nix agenix.nixosModules.default ]; diff --git a/secrets.nix b/secrets.nix index 2c98fbd..0141976 100644 --- a/secrets.nix +++ b/secrets.nix @@ -9,4 +9,11 @@ let in { "secrets/lilsecret.age".publicKeys = users ++ systems; -} \ No newline at end of file + + # Authelia secrets - all three are required + "secrets/authelia-jwt-secret.age".publicKeys = users ++ systems; + "secrets/authelia-storage-key.age".publicKeys = users ++ systems; + "secrets/authelia-session-secret.age".publicKeys = users ++ systems; + # The hashed users database (contains bcrypt-hashed passwords) + "secrets/authelia-users.age".publicKeys = users ++ systems; +} diff --git a/secrets/authelia-jwt-secret.age b/secrets/authelia-jwt-secret.age new file mode 100644 index 0000000..57e4a1c --- /dev/null +++ b/secrets/authelia-jwt-secret.age @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 Ol8kbg zksXMifeU7LyTKz1oQ1Qj+/U8FJUrvuRKqpQIK82TGo +GCsLKn6A2exjSLRLsUmF6+Loa7IGvTLnPG9Jr/A0yM8 +-> ssh-ed25519 QGvsHg MzWMzGsdlyvdAKkXHPesGT+H5C2sCXokpQyIvr4xrHc +LhGNtbBQNVWyz4WAIEYIw8J812me7qBE0xjlWk8N58k +-> ssh-ed25519 yjVKVA 5rTOZYgaA/MMuoFmiLJo2dbuw2ZdRkrJ2fYXHjd0xQI +M0NEgt9CwRQDWQgXSU7Ef4UP2wLoe/RAu1uJxQGH1ws +-> ssh-ed25519 4XPa+g hLGxBVCTB/je9yQrjPNZaJYRqlJrabsFQT8BQzw8d3Q +qpyMa38v48SzATy1vUVzccKPhPcqV6BgnkyiwBDOiEI +--- 6Ft39sS5aV9B5pyMX7yr6FH19M2uW8j3AcN86LsVztg +Ïe„ÖÂÍÑ?CkgÛ—BÜu¼ið"úò§‹;.뜰.:§GÓJB/¡aŽàY©aïêb=…]°U(=|S×ððY¥Ä×ìfV7GùB¤zÁ 7ñ®÷FšJÔGK«ƒÎg_î_ËC­´¿{•Ën²U¨}n· \ No newline at end of file diff --git a/secrets/authelia-session-secret.age b/secrets/authelia-session-secret.age new file mode 100644 index 0000000..8ee810b --- /dev/null +++ b/secrets/authelia-session-secret.age @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 Ol8kbg PME/VhYsgR6BmtBkayWFiQenodqfOjMGzuLk8UK1RFQ +zprwLWBvcXwc6mvSiOYDYz0UvCi6V7u7Wfmh6eQ2AlY +-> ssh-ed25519 QGvsHg HR7vnqTjsb46efZd00s7cDlhWz4xe+bpvBEOrAY0o0I +2T4h8K93osNlOR+4pqSa42LqjTvnNSiJC532Lh2oZI0 +-> ssh-ed25519 yjVKVA tcXgP7+G6bfLj85Zx8wpGHD5UqtH9LcV56fHdLA2Ak8 +BZTIikJmI0Qu6MYxM8EiGXFu+MSGC2ZGfhqNf4j0jVc +-> ssh-ed25519 4XPa+g PdwyAoUViWkBiQ4l8mUWH7Elw/KdI2Torjgm72pvWzk +XanrDZ2NNiU7bBvz3OQdHRh66WAwT0U81QmEXjX9QT8 +--- OTl/rm+mZy0LF+O7ff8AeseeacGhRGX+NitEMX7nYDA +{±v™i»’«¥Óáèž¾et¬Jx ¯b€B03jW_K¢|EB7’^ò§ÿ_½Ÿà,Âöû"s”r GÀ56Q½¤§Úv_¨!$ö®ŸE�:ö?ŸC+h¥Öø…šµyÕ¥º“…oÙ›&ýGšH—ÀÆuãX‡å \ No newline at end of file diff --git a/secrets/authelia-storage-key.age b/secrets/authelia-storage-key.age new file mode 100644 index 0000000000000000000000000000000000000000..a5101b1e27b72f75e20e71bc04737cfe5c21594b GIT binary patch literal 630 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCUl&#}l(N>|8nEeJHo z3G>Q#&q@kU$#U1v$*syOEb}i6aWgE)s0ep+i7d=ANOa3D&*#dD3d%~U2+6eYHVxKx z$uM*(a5OYFa*uE`b@TN$^3irmEYAxlOil?c4@9>u(7mkKBV8dRF|V*VGcheEG9tn# zEzCJFDY3}W#VIJ~N0 zeGdcAv~u$br{d(wBG2S7ql)sPjBGA5UxT!$?4kxQzL?nN*x`&i!#Eq{Zc~QjMK~0s){TllM~Cr z^G&!KZIWWcId)Bd)eyKd*K&E7Tx*%8>?z#tyIr(oqUTJ9dUHoH^Tbr!jGJ$^6!vT)*yA=ts^Y%FoYQ d&Xh8$ezPJ@lNGcyiP zt}6Bm@X9x_EOOL#Eiy{XiAV~__H#_jF3T}4^)3obF|$l_&*pM3GfT_!^9wO`^3OEU zuF7=Fs0uGCsq!}SuP6v~$}4e7Dord-GcnGMG(op5(7mkKBV8e=A~7VtAi`1KFxVu` z($~?Tsyx>~+alY<(=^4v$s;qw+}u5{z%V2t!jsEVyU4}G%P=C{Albb#EXmi?&o!~k zG)3RnJKV!D*ux;P+~1<0$Ur~Sr5xS1%B(Q&Fh_+f*ZiXJkaBHH!$PCfRM*G=_lgqJ zRM)U@ukfV2phVvw=TLW_umb07V*{=#-xL>9qeRCl^FaUNf(*y9v_SnZkFqK+v#4BC zGea|v;Hn5mm!N_Ga}3)|A_5Y%(-pMMT%1bX%S(L2eKUK0QeA5cE zEZnnQ%>&YtJktU^BDqq7om0aKilRItJd>SWEKAGG(#<@xiYknqjV!XmwG9K^%ANB| zk_xN*lDTwsbrlMN%?un}1I)eh6N}tawF^y?%C-Ic+{}yp3roV1Jp^rO;T z9l0LX~V_*Jk2V2i+U0dDnhS4wC!DuzAtU zqj#?)&lPGs+19Dwpvdd@qW(AAo<{G-3q2#{CValzIW_9|{&Y?4g?7Aw+pSGL^qsZp z=kqKSS^UUzvyDto(#@aiq<&0e-Fd<&u5xyv8@se~zF@+KnmLQfS^T$Zx z=RALAm38N?{A1&)uS~vK&CtE8;m7;v#T;B-lFED9mPWqgIyl|z!{k#zc6<>f{4?bv z59IIG^(*5N(vAzh|0Oc=&f2HWvyx_*J5H+zS#O>8DUNCBVXX_chJPz;Y8RO8xH$EQ s!t(`+q9^4(-F;np)=^j4w56iWsb61qV%oO%KYqI?U7GN;KYhh*02o6)vH$=8 literal 0 HcmV?d00001