parent
c46903e3a0
commit
032072374b
35 changed files with 511 additions and 324 deletions
121
flake.lock
generated
121
flake.lock
generated
|
|
@ -1,5 +1,21 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"blobs": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1604995301,
|
||||||
|
"narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=",
|
||||||
|
"owner": "simple-nixos-mailserver",
|
||||||
|
"repo": "blobs",
|
||||||
|
"rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265",
|
||||||
|
"type": "gitlab"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "simple-nixos-mailserver",
|
||||||
|
"repo": "blobs",
|
||||||
|
"type": "gitlab"
|
||||||
|
}
|
||||||
|
},
|
||||||
"colmena": {
|
"colmena": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-compat": "flake-compat",
|
"flake-compat": "flake-compat",
|
||||||
|
|
@ -38,6 +54,22 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flake-compat_2": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1747046372,
|
||||||
|
"narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=",
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"flake-utils": {
|
"flake-utils": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1659877975,
|
"lastModified": 1659877975,
|
||||||
|
|
@ -53,6 +85,54 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"git-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": [
|
||||||
|
"simple-nixos-mailserver",
|
||||||
|
"flake-compat"
|
||||||
|
],
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"simple-nixos-mailserver",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1750779888,
|
||||||
|
"narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"simple-nixos-mailserver",
|
||||||
|
"git-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nix-github-actions": {
|
"nix-github-actions": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
@ -90,6 +170,22 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-25_05": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1751741127,
|
||||||
|
"narHash": "sha256-t75Shs76NgxjZSgvvZZ9qOmz5zuBE8buUaYD28BMTxg=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "29e290002bfff26af1db6f64d070698019460302",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-25.05",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs_2": {
|
"nixpkgs_2": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1752624097,
|
"lastModified": 1752624097,
|
||||||
|
|
@ -109,9 +205,34 @@
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"colmena": "colmena",
|
"colmena": "colmena",
|
||||||
"nixpkgs": "nixpkgs_2",
|
"nixpkgs": "nixpkgs_2",
|
||||||
|
"simple-nixos-mailserver": "simple-nixos-mailserver",
|
||||||
"sops-nix": "sops-nix"
|
"sops-nix": "sops-nix"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"simple-nixos-mailserver": {
|
||||||
|
"inputs": {
|
||||||
|
"blobs": "blobs",
|
||||||
|
"flake-compat": "flake-compat_2",
|
||||||
|
"git-hooks": "git-hooks",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"nixpkgs-25_05": "nixpkgs-25_05"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1752060039,
|
||||||
|
"narHash": "sha256-MqcbN/PgfXOv8S4q6GcmlORd6kJZ3UlFNhzCvLOEe4I=",
|
||||||
|
"owner": "simple-nixos-mailserver",
|
||||||
|
"repo": "nixos-mailserver",
|
||||||
|
"rev": "80d21ed7a1ab8007597f7cd9adc26ebc98b9611f",
|
||||||
|
"type": "gitlab"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "simple-nixos-mailserver",
|
||||||
|
"repo": "nixos-mailserver",
|
||||||
|
"type": "gitlab"
|
||||||
|
}
|
||||||
|
},
|
||||||
"sops-nix": {
|
"sops-nix": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
url = "github:Mic92/sops-nix";
|
url = "github:Mic92/sops-nix";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
simple-nixos-mailserver = {
|
||||||
|
url = "gitlab:simple-nixos-mailserver/nixos-mailserver";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
# home-manager = {
|
# home-manager = {
|
||||||
# url = "home-manager";
|
# url = "home-manager";
|
||||||
# inputs.nixpkgs.follows = "nixpkgs";
|
# inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
@ -22,6 +27,7 @@
|
||||||
sops-nix,
|
sops-nix,
|
||||||
# home-manager,
|
# home-manager,
|
||||||
colmena,
|
colmena,
|
||||||
|
simple-nixos-mailserver,
|
||||||
...
|
...
|
||||||
} @ inputs: let
|
} @ inputs: let
|
||||||
overlays = [
|
overlays = [
|
||||||
|
|
|
||||||
12
hive.nix
12
hive.nix
|
|
@ -2,6 +2,7 @@ inputs @ {
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
sops-nix,
|
sops-nix,
|
||||||
|
simple-nixos-mailserver,
|
||||||
# home-manager,
|
# home-manager,
|
||||||
overlays,
|
overlays,
|
||||||
...
|
...
|
||||||
|
|
@ -14,11 +15,8 @@ inputs @ {
|
||||||
};
|
};
|
||||||
|
|
||||||
defaults = {
|
defaults = {
|
||||||
pkgs,
|
|
||||||
lib,
|
lib,
|
||||||
name,
|
name,
|
||||||
nodes,
|
|
||||||
meta,
|
|
||||||
config,
|
config,
|
||||||
...
|
...
|
||||||
}: {
|
}: {
|
||||||
|
|
@ -50,4 +48,12 @@ inputs @ {
|
||||||
imports = [./machines/${name}/definition.nix];
|
imports = [./machines/${name}/definition.nix];
|
||||||
deployment.tags = ["zitadel" "sso" "ldap"];
|
deployment.tags = ["zitadel" "sso" "ldap"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mail = {name, ...}: {
|
||||||
|
imports = [
|
||||||
|
./machines/${name}/definition.nix
|
||||||
|
simple-nixos-mailserver.nixosModule
|
||||||
|
];
|
||||||
|
deployment.tags = ["mail"];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,91 @@ in {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
theme = "auto";
|
theme = "auto";
|
||||||
|
server = {
|
||||||
|
buffers = {
|
||||||
|
read = 16384;
|
||||||
|
write = 16384;
|
||||||
|
};
|
||||||
|
};
|
||||||
authentication_backend.ldap = {
|
authentication_backend.ldap = {
|
||||||
|
implementation = "lldap";
|
||||||
address = "ldap://localhost:3890";
|
address = "ldap://localhost:3890";
|
||||||
base_dn = "dc=procopius,dc=dk";
|
base_dn = "dc=procopius,dc=dk";
|
||||||
users_filter = "(&({username_attribute}={input})(objectClass=person))";
|
|
||||||
groups_filter = "(member={dn})";
|
|
||||||
user = "uid=authelia,ou=people,dc=procopius,dc=dk";
|
user = "uid=authelia,ou=people,dc=procopius,dc=dk";
|
||||||
};
|
};
|
||||||
|
definitions = {
|
||||||
|
network = {
|
||||||
|
internal = [
|
||||||
|
"192.168.1.0/24"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
access_control = {
|
access_control = {
|
||||||
default_policy = "deny";
|
default_policy = "deny";
|
||||||
# We want this rule to be low priority so it doesn't override the others
|
# We want this rule to be low priority so it doesn't override the others
|
||||||
rules = lib.mkAfter [
|
rules = lib.mkAfter [
|
||||||
{
|
{
|
||||||
domain = "*.procopius.dk";
|
domain = [
|
||||||
|
"proxmox.procopius.dk"
|
||||||
|
"traefik.procopius.dk"
|
||||||
|
"prometheus.procopius.dk"
|
||||||
|
"alertmanager.procopius.dk"
|
||||||
|
];
|
||||||
|
policy = "one_factor";
|
||||||
|
subject = [
|
||||||
|
["group:server-admin"]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
# bypass /api and /ping
|
||||||
|
{
|
||||||
|
domain = ["*.procopius.dk"];
|
||||||
|
policy = "bypass";
|
||||||
|
resources = [
|
||||||
|
"^/api$"
|
||||||
|
"^/api/"
|
||||||
|
"^/ping$"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
# media
|
||||||
|
{
|
||||||
|
domain = [
|
||||||
|
"sonarr.procopius.dk"
|
||||||
|
"radarr.procopius.dk"
|
||||||
|
"readarr.procopius.dk"
|
||||||
|
"lidarr.procopius.dk"
|
||||||
|
"bazarr.procopius.dk"
|
||||||
|
"prowlarr.procopius.dk"
|
||||||
|
];
|
||||||
|
policy = "one_factor";
|
||||||
|
subject = [
|
||||||
|
["group:media-admin"]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
# authenticated
|
||||||
|
{
|
||||||
|
domain = [
|
||||||
|
"gatus.procopius.dk"
|
||||||
|
];
|
||||||
policy = "one_factor";
|
policy = "one_factor";
|
||||||
}
|
}
|
||||||
|
# bypass auth internally
|
||||||
|
# {
|
||||||
|
# domain = [
|
||||||
|
# "gatus.procopius.dk"
|
||||||
|
# "prometheus.procopius.dk"
|
||||||
|
# "alertmanager.procopius.dk"
|
||||||
|
# "sonarr.procopius.dk"
|
||||||
|
# "radarr.procopius.dk"
|
||||||
|
# "readarr.procopius.dk"
|
||||||
|
# "lidarr.procopius.dk"
|
||||||
|
# "bazarr.procopius.dk"
|
||||||
|
# "prowlarr.procopius.dk"
|
||||||
|
# ];
|
||||||
|
# policy = "bypass";
|
||||||
|
# networks = [
|
||||||
|
# "internal"
|
||||||
|
# ];
|
||||||
|
# }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
storage.postgres = {
|
storage.postgres = {
|
||||||
|
|
@ -58,8 +128,8 @@ in {
|
||||||
};
|
};
|
||||||
notifier.smtp = {
|
notifier.smtp = {
|
||||||
address = "smtp://mail.procopius.dk";
|
address = "smtp://mail.procopius.dk";
|
||||||
username = "admin@procopius.dk";
|
username = "authelia@procopius.dk";
|
||||||
sender = "auth@procopius.dk";
|
sender = "authelia@procopius.dk";
|
||||||
};
|
};
|
||||||
log.level = "info";
|
log.level = "info";
|
||||||
# identity_providers.oidc = {
|
# identity_providers.oidc = {
|
||||||
|
|
@ -97,24 +167,9 @@ in {
|
||||||
environmentVariables = with config.sops; {
|
environmentVariables = with config.sops; {
|
||||||
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE =
|
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE =
|
||||||
secrets."authelia/lldap_authelia_password".path;
|
secrets."authelia/lldap_authelia_password".path;
|
||||||
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = secrets."authelia/smtp_authelia_password".path;
|
AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = secrets.smtp-password_authelia.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# caddy = {
|
|
||||||
# virtualHosts."auth.procopius.cc".extraConfig = ''
|
|
||||||
# reverse_proxy :9091
|
|
||||||
# '';
|
|
||||||
# # A Caddy snippet that can be imported to enable Authelia in front of a service
|
|
||||||
# # Taken from https://www.authelia.com/integration/proxies/caddy/#subdomain
|
|
||||||
# extraConfig = ''
|
|
||||||
# (auth) {
|
|
||||||
# forward_auth :9091 {
|
|
||||||
# uri /api/authz/forward-auth
|
|
||||||
# copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Give Authelia access to the Redis socket
|
# Give Authelia access to the Redis socket
|
||||||
|
|
@ -142,7 +197,6 @@ in {
|
||||||
"authelia/storage_encryption_key".owner = authelia;
|
"authelia/storage_encryption_key".owner = authelia;
|
||||||
# The password for the `authelia` LLDAP user
|
# The password for the `authelia` LLDAP user
|
||||||
"authelia/lldap_authelia_password".owner = authelia;
|
"authelia/lldap_authelia_password".owner = authelia;
|
||||||
"authelia/smtp_authelia_password".owner = authelia;
|
|
||||||
smtp-password_authelia = {
|
smtp-password_authelia = {
|
||||||
owner = authelia;
|
owner = authelia;
|
||||||
key = "service_accounts/authelia/password";
|
key = "service_accounts/authelia/password";
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
systemd.services.lldap-bootstrap = {
|
|
||||||
description = "Bootstraps LLDAP users";
|
|
||||||
requires = ["lldap.service"];
|
|
||||||
serviceConfig = {
|
|
||||||
DynamicUser = true;
|
|
||||||
Type = "oneshot";
|
|
||||||
ProtectSystem = "strict";
|
|
||||||
ProtectHome = true;
|
|
||||||
PrivateUsers = true;
|
|
||||||
PrivateTmp = true;
|
|
||||||
LoadCredential = "inadyn.conf:${config.sops.templates."inadyn.conf".path}";
|
|
||||||
CacheDirectory = "inadyn";
|
|
||||||
ExecStart = ''
|
|
||||||
export LLDAP_URL=http://localhost:8080
|
|
||||||
export LLDAP_ADMIN_USERNAME=admin
|
|
||||||
export LLDAP_ADMIN_PASSWORD=changeme
|
|
||||||
export USER_CONFIGS_DIR="$(realpath ./configs/user)"
|
|
||||||
export GROUP_CONFIGS_DIR="$(realpath ./configs/group)"
|
|
||||||
export USER_SCHEMAS_DIR="$(realpath ./configs/user-schema)"
|
|
||||||
export GROUP_SCHEMAS_DIR="$(realpath ./configs/group-schema)"
|
|
||||||
export LLDAP_SET_PASSWORD_PATH="$(realpath ./lldap_set_password)"
|
|
||||||
export DO_CLEANUP=false
|
|
||||||
./bootstrap.sh
|
|
||||||
|
|
||||||
${pkgs.inadyn}/bin/inadyn \
|
|
||||||
--foreground \
|
|
||||||
--syslog \
|
|
||||||
--once \
|
|
||||||
--cache-dir ''${CACHE_DIRECTORY} \
|
|
||||||
--config ''${CREDENTIALS_DIRECTORY}/inadyn.conf
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,24 @@
|
||||||
{config, ...}: {
|
{
|
||||||
sops.templates."default-groups.json" = {
|
sops.templates."default-groups.json" = {
|
||||||
content = ''
|
content = ''
|
||||||
|
{
|
||||||
|
"name": "mail"
|
||||||
|
}
|
||||||
{
|
{
|
||||||
"name": "git-user"
|
"name": "git-user"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
"name": "git-admin"
|
"name": "git-admin"
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
"name": "media-user"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"name": "media-admin"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"name": "server-admin"
|
||||||
|
}
|
||||||
'';
|
'';
|
||||||
path = "/bootstrap/group-configs/default-groups.json";
|
path = "/bootstrap/group-configs/default-groups.json";
|
||||||
owner = "lldap";
|
owner = "lldap";
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
cfg = config.services.lldapBootstrap;
|
cfg = config.services.lldapBootstrap;
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
|
./service-accounts.nix
|
||||||
./user-configs.nix
|
./user-configs.nix
|
||||||
./group-configs.nix
|
./group-configs.nix
|
||||||
];
|
];
|
||||||
|
|
|
||||||
51
machines/auth/bootstrap/service-accounts.nix
Normal file
51
machines/auth/bootstrap/service-accounts.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{config, ...}: {
|
||||||
|
sops.secrets."service_accounts/authelia/password" = {};
|
||||||
|
sops.secrets."service_accounts/forgejo/password" = {};
|
||||||
|
sops.secrets."service_accounts/jellyfin/password" = {};
|
||||||
|
sops.secrets."service_accounts/mail/password" = {};
|
||||||
|
sops.templates."service-accounts.json" = {
|
||||||
|
content = ''
|
||||||
|
{
|
||||||
|
"id": "authelia",
|
||||||
|
"email": "authelia@procopius.dk",
|
||||||
|
"password": "${config.sops.placeholder."service_accounts/authelia/password"}",
|
||||||
|
"displayName": "Authelia",
|
||||||
|
"groups": [
|
||||||
|
"lldap_password_manager",
|
||||||
|
"mail"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"id": "forgejo",
|
||||||
|
"email": "forgejo@procopius.dk",
|
||||||
|
"password": "${config.sops.placeholder."service_accounts/forgejo/password"}",
|
||||||
|
"displayName": "Forgejo",
|
||||||
|
"groups": [
|
||||||
|
"lldap_password_manager",
|
||||||
|
"mail"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"id": "jellyfin",
|
||||||
|
"email": "jellyfin@procopius.dk",
|
||||||
|
"password": "${config.sops.placeholder."service_accounts/jellyfin/password"}",
|
||||||
|
"displayName": "Jellyfin",
|
||||||
|
"groups": [
|
||||||
|
"lldap_password_manager"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"id": "mail",
|
||||||
|
"email": "mail@procopius.dk",
|
||||||
|
"password": "${config.sops.placeholder."service_accounts/mail/password"}",
|
||||||
|
"displayName": "NixOS Mailserver",
|
||||||
|
"groups": [
|
||||||
|
"lldap_password_manager",
|
||||||
|
"mail"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
path = "/bootstrap/user-configs/service-accounts.json";
|
||||||
|
owner = "lldap";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,28 +1,47 @@
|
||||||
{config, ...}: {
|
{
|
||||||
sops.secrets."service_accounts/authelia/password" = {};
|
sops.templates."user-configs.json" = {
|
||||||
sops.secrets."service_accounts/forgejo/password" = {};
|
|
||||||
sops.templates."service-accounts.json" = {
|
|
||||||
content = ''
|
content = ''
|
||||||
{
|
{
|
||||||
"id": "authelia",
|
"id": "plasmagoat",
|
||||||
"email": "authelia@procopius.dk",
|
"email": "david.mikael@proton.me",
|
||||||
"password": "${config.sops.placeholder."service_accounts/authelia/password"}",
|
"displayName": "David",
|
||||||
"displayName": "Authelia",
|
|
||||||
"groups": [
|
"groups": [
|
||||||
"lldap_password_manager"
|
"media-user",
|
||||||
|
"media-admin",
|
||||||
|
"git-user",
|
||||||
|
"git-admin",
|
||||||
|
"server-admin"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
"id": "forgejo",
|
"id": "kurisudanoda",
|
||||||
"email": "forgejo@procopius.dk",
|
"email": "iluvmizuki@gmail.com",
|
||||||
"password": "${config.sops.placeholder."service_accounts/forgejo/password"}",
|
"displayName": "Noda",
|
||||||
"displayName": "Forgejo",
|
|
||||||
"groups": [
|
"groups": [
|
||||||
"lldap_password_manager"
|
"media-user",
|
||||||
|
"git-user"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"id": "dannydannydanny",
|
||||||
|
"email": "powerhouseplayer@gmail.com",
|
||||||
|
"displayName": "Danny",
|
||||||
|
"groups": [
|
||||||
|
"media-user",
|
||||||
|
"git-user"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"id": "stocksking",
|
||||||
|
"email": "ethanstocks9@gmail.com",
|
||||||
|
"displayName": "Ethan",
|
||||||
|
"groups": [
|
||||||
|
"media-user",
|
||||||
|
"git-user"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
path = "/bootstrap/user-configs/service-accounts.json";
|
path = "/bootstrap/user-configs/user-configs.json";
|
||||||
owner = "lldap";
|
owner = "lldap";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
machines/mail/definition.nix
Normal file
19
machines/mail/definition.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./mailserver.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
networking = {
|
||||||
|
interfaces.eth0.ipv4.addresses = [
|
||||||
|
{
|
||||||
|
address = "192.168.1.25";
|
||||||
|
prefixLength = 24;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
nameservers = ["192.168.1.53"];
|
||||||
|
defaultGateway = "192.168.1.1";
|
||||||
|
};
|
||||||
|
deployment.targetHost = "192.168.1.25";
|
||||||
|
|
||||||
|
system.stateVersion = "25.05";
|
||||||
|
}
|
||||||
37
machines/mail/mailserver.nix
Normal file
37
machines/mail/mailserver.nix
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{config, ...}: {
|
||||||
|
sops.secrets."service_accounts/mail/password" = {};
|
||||||
|
mailserver = {
|
||||||
|
enable = true;
|
||||||
|
stateVersion = 3;
|
||||||
|
fqdn = "mail.procopius.dk";
|
||||||
|
domains = ["procopius.dk"];
|
||||||
|
localDnsResolver = false;
|
||||||
|
ldap = {
|
||||||
|
enable = true;
|
||||||
|
uris = [
|
||||||
|
"ldap://auth.lab:3890"
|
||||||
|
];
|
||||||
|
bind = {
|
||||||
|
dn = "cn=mail,ou=people,dc=procopius,dc=dk";
|
||||||
|
passwordFile = config.sops.secrets."service_accounts/mail/password".path;
|
||||||
|
};
|
||||||
|
postfix = {
|
||||||
|
filter = "(&(objectClass=person)(memberOf=cn=mail,ou=groups,dc=procopius,dc=dk)(|(mail=%s)(mail-alias=%s)))"; # Will require MR!351 for aliases to work properly
|
||||||
|
mailAttribute = "mail";
|
||||||
|
};
|
||||||
|
|
||||||
|
dovecot = {
|
||||||
|
userFilter = "(&(objectClass=person)(memberOf=cn=mail,ou=groups,dc=procopius,dc=dk)(mail=%u))";
|
||||||
|
passFilter = "(&(objectClass=person)(memberOf=cn=mail,ou=groups,dc=procopius,dc=dk)(mail=%u))";
|
||||||
|
};
|
||||||
|
|
||||||
|
searchBase = "ou=people,dc=procopius,dc=dk";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
||||||
|
# down nginx and opens port 80.
|
||||||
|
certificateScheme = "acme-nginx";
|
||||||
|
};
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "david.mikael@proton.me";
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
config,
|
config,
|
||||||
nodes,
|
# nodes,
|
||||||
# name,
|
# name,
|
||||||
# meta,
|
# meta,
|
||||||
...
|
...
|
||||||
|
|
@ -21,7 +21,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
clientUrl = mkOption {
|
clientUrl = mkOption {
|
||||||
type = types.string;
|
type = types.str;
|
||||||
default = "http://monitor.lab:3100/loki/api/v1/push";
|
default = "http://monitor.lab:3100/loki/api/v1/push";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,51 @@
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
name = "sonarr";
|
name = "sonarr";
|
||||||
url = "https://sonarr.procopius.dk/health";
|
url = "https://sonarr.procopius.dk/ping";
|
||||||
interval = "5m";
|
interval = "5m";
|
||||||
conditions = [
|
conditions = [
|
||||||
"[STATUS] == 200"
|
"[STATUS] == 200"
|
||||||
"[BODY] == Healthy"
|
"[BODY].status == OK"
|
||||||
|
"[RESPONSE_TIME] < 300"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "radarr";
|
||||||
|
url = "https://radarr.procopius.dk/ping";
|
||||||
|
interval = "5m";
|
||||||
|
conditions = [
|
||||||
|
"[STATUS] == 200"
|
||||||
|
"[BODY].status == OK"
|
||||||
|
"[RESPONSE_TIME] < 300"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "lidarr";
|
||||||
|
url = "https://lidarr.procopius.dk/ping";
|
||||||
|
interval = "5m";
|
||||||
|
conditions = [
|
||||||
|
"[STATUS] == 200"
|
||||||
|
"[BODY].status == OK"
|
||||||
|
"[RESPONSE_TIME] < 300"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "readarr";
|
||||||
|
url = "https://readarr.procopius.dk/ping";
|
||||||
|
interval = "5m";
|
||||||
|
conditions = [
|
||||||
|
"[STATUS] == 200"
|
||||||
|
"[BODY].status == OK"
|
||||||
|
"[RESPONSE_TIME] < 300"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "prowlarr";
|
||||||
|
url = "https://prowlarr.procopius.dk/ping";
|
||||||
|
interval = "5m";
|
||||||
|
conditions = [
|
||||||
|
"[STATUS] == 200"
|
||||||
|
"[BODY].status == OK"
|
||||||
"[RESPONSE_TIME] < 300"
|
"[RESPONSE_TIME] < 300"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
{
|
{config, ...}: {
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
# Add grafana user to the inlfuxdb2 group (for secret)
|
# Add grafana user to the inlfuxdb2 group (for secret)
|
||||||
users.users.grafana.extraGroups = ["influxdb2"];
|
users.users.grafana.extraGroups = ["influxdb2"];
|
||||||
services.grafana.enable = true;
|
services.grafana.enable = true;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
{
|
{config, ...}: let
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
influxdbPassword = config.sops.secrets."influxdb/password".path;
|
influxdbPassword = config.sops.secrets."influxdb/password".path;
|
||||||
influxdbToken = config.sops.secrets."influxdb/token".path;
|
influxdbToken = config.sops.secrets."influxdb/token".path;
|
||||||
in {
|
in {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
{
|
{pkgs, ...}: let
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
monitor_hostname = "monitor.lab";
|
monitor_hostname = "monitor.lab";
|
||||||
traefik_hostname = "traefik.lab";
|
traefik_hostname = "traefik.lab";
|
||||||
sandbox_hostname = "sandbox.lab";
|
sandbox_hostname = "sandbox.lab";
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,4 @@
|
||||||
{
|
{config, ...}: let
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
promtail_port = 9080;
|
promtail_port = 9080;
|
||||||
in {
|
in {
|
||||||
networking.firewall.allowedTCPPorts = [promtail_port];
|
networking.firewall.allowedTCPPorts = [promtail_port];
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
nixos-rebuild switch --flake .#traefik --target-host root@192.168.1.171 --verbose
|
nixos-rebuild switch --flake .#traefik --target-host root@traefik.lab --verbose
|
||||||
nixos-rebuild switch --flake .#proxmox --target-host root@192.168.1.205 --verbose
|
nixos-rebuild switch --flake .#proxmox --target-host root@192.168.1.205 --verbose
|
||||||
nixos-rebuild switch --flake .#sandbox --target-host root@sandbox.lab --verbose
|
nixos-rebuild switch --flake .#sandbox --target-host root@sandbox.lab --verbose
|
||||||
nixos-rebuild switch --flake .#monitoring --target-host root@monitor.lab --verbose
|
nixos-rebuild switch --flake .#monitoring --target-host root@monitor.lab --verbose
|
||||||
|
|
@ -6,6 +6,7 @@ nixos-rebuild switch --flake .#forgejo --target-host root@forgejo.lab --verbose
|
||||||
nixos-rebuild switch --flake .#dns --target-host root@192.168.1.140 --verbose
|
nixos-rebuild switch --flake .#dns --target-host root@192.168.1.140 --verbose
|
||||||
nixos-rebuild switch --flake .#keycloak --target-host root@keycloak.lab --verbose
|
nixos-rebuild switch --flake .#keycloak --target-host root@keycloak.lab --verbose
|
||||||
nixos-rebuild switch --flake .#mail --target-host root@mail.lab --verbose
|
nixos-rebuild switch --flake .#mail --target-host root@mail.lab --verbose
|
||||||
|
nixos-rebuild switch --flake .#media --target-host root@media.lab --verbose
|
||||||
|
|
||||||
nixos-rebuild switch --flake .#runner01 --target-host root@forgejo-runner-01.lab --verbose
|
nixos-rebuild switch --flake .#runner01 --target-host root@forgejo-runner-01.lab --verbose
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
{ config, pkgs, modulesPath, lib, ... }:
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
modulesPath,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
########################################################################
|
########################################################################
|
||||||
# IMPORTS & PROFILE
|
# IMPORTS & PROFILE
|
||||||
#
|
#
|
||||||
|
|
@ -30,9 +34,8 @@
|
||||||
services.qemuGuest.enable = lib.mkDefault true;
|
services.qemuGuest.enable = lib.mkDefault true;
|
||||||
|
|
||||||
# GRUB on the “boot drive”
|
# GRUB on the “boot drive”
|
||||||
# Both live and template should install a bootloader on /dev/disk/by-label/nixos.
|
|
||||||
boot.loader.grub.enable = lib.mkDefault true;
|
boot.loader.grub.enable = lib.mkDefault true;
|
||||||
boot.loader.grub.devices = [ "nodev" ];
|
boot.loader.grub.devices = ["nodev"];
|
||||||
|
|
||||||
# Grow the root partition on first boot
|
# Grow the root partition on first boot
|
||||||
boot.growPartition = lib.mkDefault true;
|
boot.growPartition = lib.mkDefault true;
|
||||||
|
|
@ -53,16 +56,16 @@
|
||||||
# Root’s SSH authorized_keys (copy your own keys here)
|
# Root’s SSH authorized_keys (copy your own keys here)
|
||||||
# Both live & template will install these, so you can ssh in.
|
# Both live & template will install these, so you can ssh in.
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
users.users.root.openssh.authorizedKeys.keys = [
|
||||||
# ← Replace these with your actual public keys
|
# ← Replace these with your actual public keys
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCeg/n/vst9KME8byhxX2FhA+FZNQ60W38kkNt45eNzK5zFqBYuwo1nDXVanJSh9unRvB13b+ygpZhrb4sHvkETGWiEioc49MiWr8czEhu6Wpo0vv5MAJkiYvGZUYPdUW52jUzWcYdw8PukG2rowrxL5G0CmsqLwHMPU2FyeCe5aByFI/JZb8R80LoEacgjUiipJcoLWUVgG2koMomHClqGu+16kB8nL5Ja3Kc9lgLfDK7L0A5R8JXhCjrlEsmXbxZmwDKuxvjDAZdE9Sl1VZmMDfWkyrRlenrt01eR3t3Fec6ziRm5ZJk9e2Iu1DPoz+PoHH9aZGVwmlvvnr/gMF3OILxcqb0qx+AYlCCnb6D6pJ9zufhZkKcPRS1Q187F6fz+v2oD1xLZWFHJ92+7ItM0WmbDOHOC29s5EA6wNm3iXZCq86OI3n6T34njDtPqh6Z7Pk2sdK4GBwnFj4KwEWXvdKZKSX1qb2EVlEBE9QI4Gf3eg4SiBu2cAFt3nOSzs8c= asol\\dbs@ALPHA-DBS-P14sG2"
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCeg/n/vst9KME8byhxX2FhA+FZNQ60W38kkNt45eNzK5zFqBYuwo1nDXVanJSh9unRvB13b+ygpZhrb4sHvkETGWiEioc49MiWr8czEhu6Wpo0vv5MAJkiYvGZUYPdUW52jUzWcYdw8PukG2rowrxL5G0CmsqLwHMPU2FyeCe5aByFI/JZb8R80LoEacgjUiipJcoLWUVgG2koMomHClqGu+16kB8nL5Ja3Kc9lgLfDK7L0A5R8JXhCjrlEsmXbxZmwDKuxvjDAZdE9Sl1VZmMDfWkyrRlenrt01eR3t3Fec6ziRm5ZJk9e2Iu1DPoz+PoHH9aZGVwmlvvnr/gMF3OILxcqb0qx+AYlCCnb6D6pJ9zufhZkKcPRS1Q187F6fz+v2oD1xLZWFHJ92+7ItM0WmbDOHOC29s5EA6wNm3iXZCq86OI3n6T34njDtPqh6Z7Pk2sdK4GBwnFj4KwEWXvdKZKSX1qb2EVlEBE9QI4Gf3eg4SiBu2cAFt3nOSzs8c= asol\\dbs@ALPHA-DBS-P14sG2"
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+U3DWOrklcA8n8wdbLBGyli5LsJI3dpL2Zod8mx8eOdC4H127ZT1hzuk2uSmkic4c73BykPyQv8rcqwaRGW94xdMRanKmHYxnbHXo5FBiGrCkNlNNZuahthAGO49c6sUhJMq0eLhYOoFWjtf15sr5Zu7Ug2YTUL3HXB1o9PZ3c9sqYHo2rC/Il1x2j3jNAMKST/qUZYySvdfNJEeQhMbQcdoKJsShcE3oGRL6DFBoV/mjJAJ+wuDhGLDnqi79nQjYfbYja1xKcrKX+D3MfkFxFl6ZIzomR1t75AnZ+09oaWcv1J7ehZ3h9PpDBFNXvzyLwDBMNS+UYcH6SyFjkUbF David@NZXT"
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+U3DWOrklcA8n8wdbLBGyli5LsJI3dpL2Zod8mx8eOdC4H127ZT1hzuk2uSmkic4c73BykPyQv8rcqwaRGW94xdMRanKmHYxnbHXo5FBiGrCkNlNNZuahthAGO49c6sUhJMq0eLhYOoFWjtf15sr5Zu7Ug2YTUL3HXB1o9PZ3c9sqYHo2rC/Il1x2j3jNAMKST/qUZYySvdfNJEeQhMbQcdoKJsShcE3oGRL6DFBoV/mjJAJ+wuDhGLDnqi79nQjYfbYja1xKcrKX+D3MfkFxFl6ZIzomR1t75AnZ+09oaWcv1J7ehZ3h9PpDBFNXvzyLwDBMNS+UYcH6SyFjkUbF David@NZXT"
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air"
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICUP7m8jZJiclZGfSje8CeBYFhX10SrdtjYziuChmj1X plasmagoat@macbook-air"
|
||||||
];
|
];
|
||||||
|
|
||||||
# Default filesystem on
|
# Default filesystem on
|
||||||
fileSystems."/" = lib.mkDefault {
|
fileSystems."/" = lib.mkDefault {
|
||||||
device = "/dev/disk/by-label/nixos";
|
device = "/dev/disk/by-label/nixos";
|
||||||
autoResize = true; # grow on first boot
|
autoResize = true; # grow on first boot
|
||||||
fsType = "ext4";
|
fsType = "ext4";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -72,23 +75,23 @@
|
||||||
|
|
||||||
# Default set of packages
|
# Default set of packages
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
vim # emergencies
|
vim # emergencies
|
||||||
git # pulling flakes, code
|
git # pulling flakes, code
|
||||||
curl # downloading things
|
curl # downloading things
|
||||||
python3 # for Ansible if needed on live VM
|
python3 # for Ansible if needed on live VM
|
||||||
];
|
];
|
||||||
|
|
||||||
# Nix settings (cache, experimental, gc)
|
# Nix settings (cache, experimental, gc)
|
||||||
nix.settings.trusted-users = [ "root" "@wheel" ];
|
nix.settings.trusted-users = ["root" "@wheel"];
|
||||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
nix.settings.experimental-features = ["nix-command" "flakes"];
|
||||||
nix.extraOptions = ''
|
nix.extraOptions = ''
|
||||||
experimental-features = nix-command flakes
|
experimental-features = nix-command flakes
|
||||||
keep-outputs = true
|
keep-outputs = true
|
||||||
keep-derivations = true
|
keep-derivations = true
|
||||||
'';
|
'';
|
||||||
nix.gc.automatic = true;
|
nix.gc.automatic = true;
|
||||||
nix.gc.dates = "weekly";
|
nix.gc.dates = "weekly";
|
||||||
nix.gc.options = "--delete-older-than 7d";
|
nix.gc.options = "--delete-older-than 7d";
|
||||||
|
|
||||||
# mDNS with avahi to enable .local dns
|
# mDNS with avahi to enable .local dns
|
||||||
services.avahi = {
|
services.avahi = {
|
||||||
|
|
@ -104,7 +107,7 @@
|
||||||
ipv6 = false;
|
ipv6 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.firewall.allowedUDPPorts = [ 5353 ];
|
networking.firewall.allowedUDPPorts = [5353];
|
||||||
|
|
||||||
# State version (set to match the Nixpkgs you’re using)
|
# State version (set to match the Nixpkgs you’re using)
|
||||||
system.stateVersion = lib.mkDefault "25.05";
|
system.stateVersion = lib.mkDefault "25.05";
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
# Static IPs
|
# Static IPs
|
||||||
"/dns.lab/192.168.1.53"
|
"/dns.lab/192.168.1.53"
|
||||||
"/traefik.lab/192.168.1.80"
|
"/traefik.lab/192.168.1.80"
|
||||||
|
"/mail.lab/192.168.1.25"
|
||||||
# "/proxmox-01.lab/192.168.1.205"
|
# "/proxmox-01.lab/192.168.1.205"
|
||||||
# "/nas-01.lab/192.168.1.226"
|
# "/nas-01.lab/192.168.1.226"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
modulesPath,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
../../templates/base.nix
|
|
||||||
./networking.nix
|
|
||||||
./sops.nix
|
|
||||||
./mailserver.nix
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
imports = [
|
|
||||||
(builtins.fetchTarball {
|
|
||||||
# Pick a release version you are interested in and set its hash, e.g.
|
|
||||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.05/nixos-mailserver-nixos-25.05.tar.gz";
|
|
||||||
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
|
|
||||||
# release="nixos-25.05"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
|
||||||
sha256 = "0jpp086m839dz6xh6kw5r8iq0cm4nd691zixzy6z11c4z2vf8v85";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
mailserver = {
|
|
||||||
enable = true;
|
|
||||||
fqdn = "mail.procopius.dk";
|
|
||||||
domains = ["procopius.dk"];
|
|
||||||
|
|
||||||
# A list of all login accounts. To create the password hashes, use
|
|
||||||
# nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt'
|
|
||||||
loginAccounts = {
|
|
||||||
"admin@procopius.dk" = {
|
|
||||||
hashedPasswordFile = config.sops.secrets.mailserver-admin-pass.path;
|
|
||||||
aliases = [
|
|
||||||
"@procopius.dk"
|
|
||||||
"postmaster@procopius.dk"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Use Let's Encrypt certificates. Note that this needs to set up a stripped
|
|
||||||
# down nginx and opens port 80.
|
|
||||||
certificateScheme = "acme-nginx";
|
|
||||||
};
|
|
||||||
security.acme.acceptTerms = true;
|
|
||||||
security.acme.defaults.email = "david.mikael@proton.me";
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: {
|
|
||||||
networking.hostName = "mail";
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{...}: let
|
|
||||||
mailserverSops = ../../secrets/mailserver/secrets.yml;
|
|
||||||
in {
|
|
||||||
sops.secrets.mailserver-admin-pass = {
|
|
||||||
sopsFile = mailserverSops;
|
|
||||||
mode = "0440";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
{config, ...}: {
|
{config, ...}: {
|
||||||
services.sonarr.settings = {
|
services.sonarr.settings.auth.method = "External";
|
||||||
auth.method = "External";
|
services.radarr.settings.auth.method = "External";
|
||||||
};
|
services.lidarr.settings.auth.method = "External";
|
||||||
|
services.readarr.settings.auth.method = "External";
|
||||||
|
services.prowlarr.settings.auth.method = "External";
|
||||||
|
|
||||||
nixarr = {
|
nixarr = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
||||||
|
|
@ -13,19 +13,10 @@
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
oauth2proxy = {
|
lldap = {
|
||||||
rule = "Host(`radarr.procopius.dk`) && PathPrefix(`/oauth2/`)";
|
rule = "Host(`lldap.procopius.dk`)";
|
||||||
service = "oauth2proxy";
|
service = "lldap";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["auth-headers"];
|
|
||||||
tls.certResolver = "letsencrypt";
|
|
||||||
};
|
|
||||||
|
|
||||||
oauth2route = {
|
|
||||||
rule = "Host(`oauth.procopius.dk`)";
|
|
||||||
service = "oauth2proxy";
|
|
||||||
entryPoints = ["websecure"];
|
|
||||||
middlewares = ["auth-headers"];
|
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
keycloak.loadBalancer.servers = [{url = "http://keycloak.lab:8080";}];
|
keycloak.loadBalancer.servers = [{url = "http://keycloak.lab:8080";}];
|
||||||
oauth2proxy.loadBalancer.servers = [{url = "http://localhost:4180";}];
|
|
||||||
|
|
||||||
authelia.loadBalancer.servers = [{url = "http://auth.lab:9091";}];
|
authelia.loadBalancer.servers = [{url = "http://auth.lab:9091";}];
|
||||||
|
lldap.loadBalancer.servers = [{url = "http://auth.lab:17170";}];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
rule = "Host(`traefik.procopius.dk`)";
|
rule = "Host(`traefik.procopius.dk`)";
|
||||||
service = "traefik";
|
service = "traefik";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
rule = "Host(`proxmox.procopius.dk`)";
|
rule = "Host(`proxmox.procopius.dk`)";
|
||||||
service = "proxmox";
|
service = "proxmox";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
nas = {
|
nas = {
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,18 @@
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
jellyseerr = {
|
||||||
|
rule = "Host(`jellyseerr.procopius.dk`)";
|
||||||
|
service = "jellyseerr";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
|
||||||
radarr = {
|
radarr = {
|
||||||
rule = "Host(`radarr.procopius.dk`)";
|
rule = "Host(`radarr.procopius.dk`)";
|
||||||
service = "radarr";
|
service = "radarr";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = [
|
middlewares = ["authelia"];
|
||||||
"oauth-auth"
|
|
||||||
"restrict-admin"
|
|
||||||
];
|
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -21,15 +25,39 @@
|
||||||
rule = "Host(`sonarr.procopius.dk`)";
|
rule = "Host(`sonarr.procopius.dk`)";
|
||||||
service = "sonarr";
|
service = "sonarr";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
|
|
||||||
jellyseerr = {
|
prowlarr = {
|
||||||
rule = "Host(`jellyseerr.procopius.dk`)";
|
rule = "Host(`prowlarr.procopius.dk`)";
|
||||||
service = "jellyseerr";
|
service = "prowlarr";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
# middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
|
||||||
|
bazarr = {
|
||||||
|
rule = "Host(`bazarr.procopius.dk`)";
|
||||||
|
service = "bazarr";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
middlewares = ["authelia"];
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
|
||||||
|
lidarr = {
|
||||||
|
rule = "Host(`lidarr.procopius.dk`)";
|
||||||
|
service = "lidarr";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
middlewares = ["authelia"];
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
|
||||||
|
readarr = {
|
||||||
|
rule = "Host(`readarr.procopius.dk`)";
|
||||||
|
service = "readarr";
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
{
|
{
|
||||||
jellyfin.loadBalancer.servers = [{url = "http://media.lab:8096";}];
|
jellyfin.loadBalancer.servers = [{url = "http://media.lab:8096";}];
|
||||||
|
jellyseerr.loadBalancer.servers = [{url = "http://media.lab:5055";}];
|
||||||
|
|
||||||
radarr.loadBalancer.servers = [{url = "http://media.lab:7878";}];
|
radarr.loadBalancer.servers = [{url = "http://media.lab:7878";}];
|
||||||
sonarr.loadBalancer.servers = [{url = "http://media.lab:8989";}];
|
sonarr.loadBalancer.servers = [{url = "http://media.lab:8989";}];
|
||||||
jellyseerr.loadBalancer.servers = [{url = "http://media.lab:5055";}];
|
readarr.loadBalancer.servers = [{url = "http://media.lab:8787";}];
|
||||||
|
lidarr.loadBalancer.servers = [{url = "http://media.lab:8686";}];
|
||||||
|
bazarr.loadBalancer.servers = [{url = "http://media.lab:6767";}];
|
||||||
|
prowlarr.loadBalancer.servers = [{url = "http://media.lab:9696";}];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,16 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
oauth-auth = {
|
authelia = {
|
||||||
forwardAuth = {
|
forwardAuth = {
|
||||||
address = "http://localhost:4180/";
|
address = "http://auth.lab:9091/api/authz/forward-auth";
|
||||||
trustForwardHeader = true;
|
trustForwardHeader = true;
|
||||||
authResponseHeaders = [
|
authResponseHeaders = [
|
||||||
"Authorization"
|
"Remote-User"
|
||||||
"X-Auth-Request-Access-Token"
|
"Remote-Groups"
|
||||||
"X-Auth-Request-User"
|
"Remote-Email"
|
||||||
"X-Auth-Request-Email"
|
"Remote-Name"
|
||||||
"X-Auth-Request-Preferred-Username" # Recommended
|
|
||||||
"X-Auth-Request-Access-Token" # If you want to pass the token
|
|
||||||
"X-Auth-Request-Groups" # If you configured a mapper in Keycloak to emit groups
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
restrict-admin = {
|
|
||||||
forwardAuth = {
|
|
||||||
address = "http://localhost:4180/oauth2/auth?allowed_groups=role:admin";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
rule = "Host(`prometheus.procopius.dk`)";
|
rule = "Host(`prometheus.procopius.dk`)";
|
||||||
service = "prometheus";
|
service = "prometheus";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
grafana = {
|
grafana = {
|
||||||
|
|
@ -16,14 +16,14 @@
|
||||||
rule = "Host(`alertmanager.procopius.dk`)";
|
rule = "Host(`alertmanager.procopius.dk`)";
|
||||||
service = "alertmanager";
|
service = "alertmanager";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
gatus = {
|
gatus = {
|
||||||
rule = "Host(`gatus.procopius.dk`)";
|
rule = "Host(`gatus.procopius.dk`)";
|
||||||
service = "gatus";
|
service = "gatus";
|
||||||
entryPoints = ["websecure"];
|
entryPoints = ["websecure"];
|
||||||
middlewares = ["oauth-auth"];
|
middlewares = ["authelia"];
|
||||||
tls.certResolver = "letsencrypt";
|
tls.certResolver = "letsencrypt";
|
||||||
};
|
};
|
||||||
umami = {
|
umami = {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,5 @@
|
||||||
./traefik.nix
|
./traefik.nix
|
||||||
./promtail.nix
|
./promtail.nix
|
||||||
./sops.nix
|
./sops.nix
|
||||||
./oauth2proxy.nix
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
# /etc/nixos/configuration.nix
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
oauth2ProxyKeyFile = config.sops.secrets."oauth2-proxy-env".path;
|
|
||||||
in {
|
|
||||||
services.oauth2-proxy = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.oauth2-proxy;
|
|
||||||
|
|
||||||
keyFile = oauth2ProxyKeyFile;
|
|
||||||
|
|
||||||
provider = "keycloak-oidc"; # Use "oidc" for standard OIDC providers like Keycloak
|
|
||||||
oidcIssuerUrl = "https://keycloak.procopius.dk/realms/homelab";
|
|
||||||
clientID = "oauth2-proxy"; # Matches the client ID in Keycloak
|
|
||||||
|
|
||||||
# Public URL for oauth2-proxy itself, where Keycloak redirects back to
|
|
||||||
redirectURL = "https://oauth.procopius.dk/oauth2/callback";
|
|
||||||
upstream = ["static://202"];
|
|
||||||
extraConfig = {
|
|
||||||
code-challenge-method = "S256";
|
|
||||||
# email-domain = "*";
|
|
||||||
auth-logging = true;
|
|
||||||
request-logging = true;
|
|
||||||
whitelist-domain = ".procopius.dk";
|
|
||||||
pass-host-header = true;
|
|
||||||
skip-provider-button = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Cookie configuration
|
|
||||||
cookie = {
|
|
||||||
name = "_oauth2_proxy_homelab";
|
|
||||||
domain = ".procopius.dk";
|
|
||||||
secure = true;
|
|
||||||
httpOnly = true;
|
|
||||||
expire = "24h";
|
|
||||||
refresh = "1h";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Listen address for oauth2-proxy internally. Traefik will forward to this.
|
|
||||||
httpAddress = "http://127.0.0.1:4180"; # Ensure this port is not blocked by your firewall internally
|
|
||||||
|
|
||||||
# Reverse proxy settings for headers
|
|
||||||
reverseProxy = true; # Set to true because it's behind Traefik
|
|
||||||
|
|
||||||
# Headers to set for the upstream applications after successful authentication
|
|
||||||
setXauthrequest = true; # Set X-Auth-Request-User, X-Auth-Request-Email etc.
|
|
||||||
passBasicAuth = true; # Pass HTTP Basic Auth headers
|
|
||||||
passHostHeader = true; # Pass the original Host header to the upstream
|
|
||||||
|
|
||||||
# Authorization rules for who can access
|
|
||||||
# You can restrict by email domain (allows everyone from that domain)
|
|
||||||
email.domains = ["*"]; # Allows any authenticated user from Keycloak
|
|
||||||
# Or restrict by specific email addresses (if you want tighter control):
|
|
||||||
# email.addresses = allowedOauth2ProxyEmails;
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
requestLogging = true;
|
|
||||||
|
|
||||||
# Optional: If you use specific scopes for Keycloak (e.g., if you want groups claim)
|
|
||||||
# scope = "openid profile email";
|
|
||||||
# If you specifically added a 'groups' claim in Keycloak:
|
|
||||||
scope = "openid profile email";
|
|
||||||
|
|
||||||
# You can add extra command-line flags here if needed, e.g., for debug logging
|
|
||||||
# extraConfig = {
|
|
||||||
#
|
|
||||||
# };
|
|
||||||
};
|
|
||||||
|
|
||||||
# Expose the internal port for oauth2-proxy if needed for debugging or direct access (less common)
|
|
||||||
networking.firewall.allowedTCPPorts = [4180];
|
|
||||||
}
|
|
||||||
|
|
@ -21,6 +21,10 @@ service_accounts:
|
||||||
password: ENC[AES256_GCM,data:r4Qy09FOhUgD48SHSkWKtrlrMptvXYdScCL8h7gjJNs=,iv:IzsDdV4o35hnS/F2S713cJ5pQ+PGiaVTmTWe6YXgfYc=,tag:OisvmY7QI2Ph7R3g3Xy/Ww==,type:str]
|
password: ENC[AES256_GCM,data:r4Qy09FOhUgD48SHSkWKtrlrMptvXYdScCL8h7gjJNs=,iv:IzsDdV4o35hnS/F2S713cJ5pQ+PGiaVTmTWe6YXgfYc=,tag:OisvmY7QI2Ph7R3g3Xy/Ww==,type:str]
|
||||||
forgejo:
|
forgejo:
|
||||||
password: ENC[AES256_GCM,data:HLEoGjx++9fkiJQoLWQvAjgg58mIs1vk1hvUJvr6TiA=,iv:mPIx9cSlHEK+0wLs1/1bjYcsxgdwgLReUoI5JrA4E1k=,tag:TdyznTIGiAFFq8D3Irb0rA==,type:str]
|
password: ENC[AES256_GCM,data:HLEoGjx++9fkiJQoLWQvAjgg58mIs1vk1hvUJvr6TiA=,iv:mPIx9cSlHEK+0wLs1/1bjYcsxgdwgLReUoI5JrA4E1k=,tag:TdyznTIGiAFFq8D3Irb0rA==,type:str]
|
||||||
|
jellyfin:
|
||||||
|
password: ENC[AES256_GCM,data:PpUHEhNfnR1eg7DmnO7tyNciNE4Tsx/Y4uL92gqiods=,iv:DNKQfymvgEu/iEW8t79m0ZmKTU0Ffasu+gp2KOIAK3o=,tag:lGKw5dbXqImDJNVX6p8kLg==,type:str]
|
||||||
|
mail:
|
||||||
|
password: ENC[AES256_GCM,data:6lfziq1zXlFxCAFWv5co3MkBgwaWixjHHX9riQXCbe0=,iv:/t4CnW3bKUDxfpE/qGf1LPs0ciivRMkfgJ1nMseruy4=,tag:TWApzLsm2HV+JMaZLG/Kig==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1n20y9kmdh324m3tkclvhmyuc7c8hk4w84zsal725adahwl8nzq0s04aq4y
|
- recipient: age1n20y9kmdh324m3tkclvhmyuc7c8hk4w84zsal725adahwl8nzq0s04aq4y
|
||||||
|
|
@ -32,7 +36,7 @@ sops:
|
||||||
QzNYRk5ERmR4aGtLQ3dwQ1lPeDZyaEkKJMLXqv6tBBql7VVnWDIwAh24SfQ2O6Ca
|
QzNYRk5ERmR4aGtLQ3dwQ1lPeDZyaEkKJMLXqv6tBBql7VVnWDIwAh24SfQ2O6Ca
|
||||||
CEOQTGEonbqr5doWqTsXUXrdQAS0amL45UdT6ITFtfNAjaHwCMfhZg==
|
CEOQTGEonbqr5doWqTsXUXrdQAS0amL45UdT6ITFtfNAjaHwCMfhZg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-07-16T00:07:58Z"
|
lastmodified: "2025-07-16T15:33:06Z"
|
||||||
mac: ENC[AES256_GCM,data:kKSjCmLGbr7WaLb+Z1KZL/bjBszNgCCAb67CENaKKpFbqbCk3o5QFok/kVTs3k3JwKmODqbTe0ebP6uMENN/t85+1n4ofnMq5ire/NqCyoE1EJFDmG9xyys24CB+NJJZ2trdxm5CYutme7FfG4bQY0/2OgflmjiZeBsMZcxRxtI=,iv:md6qX+WlFFgMFbDs8MTTKXEOPWKFoVYAUMehWvGF5wk=,tag:Y3AelrfrsBMIJ0wYzFYtLQ==,type:str]
|
mac: ENC[AES256_GCM,data:nZm7N8qfANzHadtW+3eTJljpmYejJdKGFO44iw40CnwlGgb454us9LZbQIAYkNiS7UkivoWa5BqvgLcpObHNAn3tVi+ha0jySIrAmp43y5ilmg76fvL4znel4Nk7eRiGoF3t3xiCR39/3l7PPffx2RJ6PerEyGBpiUZ6mBcWoTE=,iv:UmhSynpMdTnY0R6jwDJts13b0rKsaRFlCizdM2oargE=,tag:Q2xh/QXFOQYqqkxKs7nujA==,type:str]
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.10.2
|
version: 3.10.2
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue