Move modules in programs/services subfolders

This commit is contained in:
SebastianStork 2025-05-28 11:33:05 +02:00
parent 2ff87c8404
commit 211ca98e92
38 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,55 @@
{
config,
pkgs,
lib,
...
}:
let
user = config.users.users.actual.name;
in
{
options.custom.services.actualbudget.backups.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.actualbudget.backups.enable {
security.polkit = {
enable = true;
extraConfig =
let
service = "actual.service";
in
''
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "${service}" &&
subject.user == "${user}") {
return polkit.Result.YES;
}
});
'';
};
custom.services.resticBackup.actual = {
inherit user;
healthchecks.enable = true;
extraConfig = {
backupPrepareCommand = "${lib.getExe' pkgs.systemd "systemctl"} stop actual.service";
backupCleanupCommand = "${lib.getExe' pkgs.systemd "systemctl"} start actual.service";
paths = [ config.services.actual.settings.dataDir ];
};
};
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "actual-restore";
text = ''
sudo --user=${user} bash -c "
systemctl stop actual.service
restic-actual restore latest --target /
systemctl start actual.service
"
'';
})
];
};
}

View file

@ -0,0 +1,38 @@
{
config,
lib,
...
}:
let
cfg = config.custom.services.actualbudget;
in
{
options.custom.services.actualbudget = {
enable = lib.mkEnableOption "";
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "";
};
port = lib.mkOption {
type = lib.types.port;
default = 8080;
};
};
config = lib.mkIf cfg.enable {
users.groups.actual = { };
users.users.actual = {
isSystemUser = true;
group = "actual";
};
services.actual = {
enable = true;
settings = {
hostname = "localhost";
inherit (cfg) port;
};
};
};
}

View file

@ -0,0 +1,16 @@
{ config, lib, ... }:
{
options.custom.services.bluetooth.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.bluetooth.enable {
hardware = {
bluetooth = {
enable = true;
powerOnBoot = true;
};
logitech.wireless.enable = true;
};
services.blueman.enable = true;
};
}

View file

@ -0,0 +1,74 @@
{
config,
inputs,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.crowdsec;
in
{
imports = [ inputs.crowdsec.nixosModules.crowdsec ];
options.custom.services.crowdsec = {
enable = lib.mkEnableOption "";
apiPort = lib.mkOption {
type = lib.types.port;
default = 8080;
};
sources = lib.mkOption {
type = lib.types.listOf (
lib.types.enum [
"iptables"
"caddy"
]
);
default = [ ];
};
};
config = lib.mkIf cfg.enable {
nixpkgs.overlays = [ inputs.crowdsec.overlays.default ];
sops.secrets."crowdsec/enrollment-key".owner = config.users.users.crowdsec.name;
services.crowdsec = {
enable = true;
package = inputs.crowdsec.packages.${pkgs.system}.crowdsec;
enrollKeyFile = config.sops.secrets."crowdsec/enrollment-key".path;
settings = {
api.server.listen_uri = "127.0.0.1:${toString cfg.apiPort}";
prometheus.enabled = false;
};
acquisitions = [
(lib.mkIf (lib.elem "iptables" cfg.sources) {
source = "journalctl";
journalctl_filter = [ "-k" ];
labels.type = "syslog";
})
(lib.mkIf (lib.elem "caddy" cfg.sources) {
source = "journalctl";
journalctl_filter = [ "_SYSTEMD_UNIT=caddy.service" ];
labels.type = "syslog";
})
];
};
systemd.services.crowdsec.preStart =
let
collections = lib.flatten [
"crowdsecurity/linux"
(lib.optional (lib.elem "iptables" cfg.sources) "crowdsecurity/iptables")
(lib.optional (lib.elem "caddy" cfg.sources) "crowdsecurity/caddy")
];
addCollection = collection: ''
if ! cscli collections list | grep -q "${collection}"; then
cscli collections install ${collection}
fi
'';
in
collections |> lib.map addCollection |> lib.concatLines;
};
}

View file

@ -0,0 +1,32 @@
{
config,
inputs,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.crowdsec;
in
{
imports = [ inputs.crowdsec.nixosModules.crowdsec-firewall-bouncer ];
options.custom.services.crowdsec.firewallBouncer.enable = lib.mkEnableOption "";
config = lib.mkIf cfg.firewallBouncer.enable {
services.crowdsec-firewall-bouncer = {
enable = true;
package = inputs.crowdsec.packages.${pkgs.system}.crowdsec-firewall-bouncer;
settings = {
api_key = "cs-firewall-bouncer";
api_url = "http://127.0.0.1:${toString cfg.apiPort}";
};
};
systemd.services.crowdsec.preStart = ''
if ! cscli bouncers list | grep -q "firewall-bouncer"; then
cscli bouncers add "firewall-bouncer" --key "cs-firewall-bouncer"
fi
'';
};
}

View file

@ -0,0 +1,57 @@
{
config,
lib,
...
}:
let
cfg = config.custom.services.forgejo;
user = config.users.users.forgejo.name;
in
{
options.custom.services.forgejo = {
enable = lib.mkEnableOption "";
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "";
};
port = lib.mkOption {
type = lib.types.port;
default = 3000;
};
};
config = lib.mkIf cfg.enable {
sops.secrets."forgejo/admin-password".owner = user;
services.forgejo = {
enable = true;
lfs.enable = true;
settings = {
server = {
DOMAIN = "${cfg.subdomain}.${config.networking.domain}";
ROOT_URL = "https://${config.services.forgejo.settings.server.DOMAIN}/";
HTTP_PORT = cfg.port;
};
service.DISABLE_REGISTRATION = true;
# https://forgejo.org/docs/latest/admin/recommendations
database.SQLITE_JOURNAL_MODE = "WAL";
cache = {
ADAPTER = "twoqueue";
HOST = ''{"size":100, "recent_ratio":0.25, "ghost_ratio":0.5}'';
};
"repository.signing".DEFAULT_TRUST_MODEL = "committer";
security.LOGIN_REMEMBER_DAYS = 365;
};
};
systemd.services.forgejo.preStart =
let
createCmd = "${lib.getExe config.services.forgejo.package} admin user create";
passwordPath = config.sops.secrets."forgejo/admin-password".path;
in
''${createCmd} --username SebastianStork --password "$(cat ${passwordPath})" --email "sebastian.stork@pm.me" --admin || true'';
};
}

View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
{
options.custom.services.gc.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.gc.enable {
programs.nh = {
enable = true;
clean = {
enable = true;
dates = "weekly";
extraArgs = "--keep 10 --keep-since 7d";
};
};
};
}

View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
{
options.custom.services.geoclue.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.geoclue.enable {
services.geoclue2 = {
enable = true;
appConfig.gammastep = {
isAllowed = true;
isSystem = false;
};
};
};
}

View file

@ -0,0 +1,58 @@
{
config,
pkgs,
lib,
...
}:
let
user = config.users.users.hedgedoc.name;
in
{
options.custom.services.hedgedoc.backups.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.hedgedoc.backups.enable {
security.polkit = {
enable = true;
extraConfig =
let
service = "hedgedoc.service";
in
''
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "${service}" &&
subject.user == "${user}") {
return polkit.Result.YES;
}
});
'';
};
custom.services.resticBackup.hedgedoc = {
inherit user;
healthchecks.enable = true;
extraConfig = {
backupPrepareCommand = "${lib.getExe' pkgs.systemd "systemctl"} stop hedgedoc.service";
backupCleanupCommand = "${lib.getExe' pkgs.systemd "systemctl"} start hedgedoc.service";
paths = with config.services.hedgedoc.settings; [
uploadsPath
db.storage
];
};
};
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "hedgedoc-restore";
text = ''
sudo --user=${user} bash -c "
systemctl stop hedgedoc.service
restic-hedgedoc restore latest --target /
systemctl start hedgedoc.service
"
'';
})
];
};
}

View file

@ -0,0 +1,82 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.hedgedoc;
user = config.users.users.hedgedoc.name;
manage_users = "CMD_CONFIG_FILE=/run/hedgedoc/config.json NODE_ENV=production ${lib.getExe' pkgs.hedgedoc "manage_users"}";
in
{
options.custom.services.hedgedoc = {
enable = lib.mkEnableOption "";
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "";
};
port = lib.mkOption {
type = lib.types.port;
default = 3000;
};
};
config = lib.mkIf cfg.enable {
sops = {
secrets = {
"hedgedoc/seb-password".owner = user;
"hedgedoc/gitlab-auth-secret".owner = user;
};
templates."hedgedoc/environment" = {
owner = user;
content = "GITLAB_CLIENTSECRET=${config.sops.placeholder."hedgedoc/gitlab-auth-secret"}";
};
};
services.hedgedoc = {
enable = true;
environmentFile = config.sops.templates."hedgedoc/environment".path;
settings = {
domain = "${cfg.subdomain}.${config.networking.domain}";
inherit (cfg) port;
protocolUseSSL = true;
allowAnonymous = false;
allowEmailRegister = false;
defaultPermission = "limited";
sessionSecret = "$SESSION_SECRET";
gitlab = {
baseURL = "https://code.fbi.h-da.de";
clientID = "dc71d7ec1525ce3b425d7d41d602f67e1a06cef981259605a87841a6be62cc58";
clientSecret = "$GITLAB_CLIENTSECRET";
};
};
};
systemd.services.hedgedoc = {
# Ensure session-secret
preStart = lib.mkBefore ''
if [ ! -f /var/lib/hedgedoc/session-secret ]; then
${lib.getExe pkgs.pwgen} -s 64 1 > /var/lib/hedgedoc/session-secret
fi
export SESSION_SECRET=$(cat /var/lib/hedgedoc/session-secret)
'';
postStart =
let
manageUserSeb =
mode:
"${manage_users} --${mode} sebastian.stork@pm.me --pass \"$(cat ${
config.sops.secrets."hedgedoc/seb-password".path
})\"";
in
"${manageUserSeb "add"} || ${manageUserSeb "reset"}";
};
environment.shellAliases.hedgedoc-manage-users = "sudo --user=${user} ${manage_users}";
};
}

View file

@ -0,0 +1,49 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.nextcloud;
dataDir = config.services.nextcloud.home;
user = config.users.users.nextcloud.name;
in
{
options.custom.services.nextcloud.backups.enable = lib.mkEnableOption "";
config = lib.mkIf cfg.backups.enable {
custom.services.resticBackup.nextcloud = {
inherit user;
healthchecks.enable = true;
extraConfig = {
backupPrepareCommand = ''
${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --on
${lib.getExe' config.services.postgresql.package "pg_dump"} nextcloud --format=custom --file=${dataDir}/db.dump
'';
backupCleanupCommand = "${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --off";
paths = [
"${dataDir}/data"
"${dataDir}/config/config.php"
"${dataDir}/db.dump"
];
};
};
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "nextcloud-restore";
text = ''
sudo --user=${user} bash -c "
${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --on
restic-nextcloud restore latest --target /
pg_restore --clean --if-exists --dbname nextcloud ${dataDir}/db.dump
${lib.getExe' config.services.nextcloud.occ "nextcloud-occ"} maintenance:mode --off
"
'';
})
];
};
}

View file

@ -0,0 +1,75 @@
{
config,
inputs,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.nextcloud;
user = config.users.users.nextcloud.name;
in
{
options.custom.services.nextcloud = {
enable = lib.mkEnableOption "";
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "";
};
port = lib.mkOption {
type = lib.types.port;
default = 80;
readOnly = true;
};
};
config = lib.mkIf cfg.enable {
sops.secrets."nextcloud/admin-password".owner = user;
services.nextcloud = {
enable = true;
package = pkgs.nextcloud31;
hostName = "${cfg.subdomain}.${config.networking.domain}";
database.createLocally = true;
config = {
dbtype = "pgsql";
adminuser = "admin";
adminpassFile = config.sops.secrets."nextcloud/admin-password".path;
};
https = true;
settings = {
overwriteProtocol = "https";
trusted_proxies = [ "127.0.0.1" ];
log_type = "file";
default_phone_region = "DE";
maintenance_window_start = "2"; # UTC
defaultapp = "side_menu";
};
configureRedis = true;
maxUploadSize = "16G";
phpOptions."opcache.interned_strings_buffer" = "16";
autoUpdateApps = {
enable = true;
startAt = "04:00:00";
};
extraApps = {
inherit (config.services.nextcloud.package.packages.apps)
calendar
contacts
;
twofactor_totp = pkgs.fetchNextcloudApp {
url = inputs.nextcloud-twofactor-totp.outPath;
sha256 = inputs.nextcloud-twofactor-totp.narHash;
license = "agpl3Plus";
unpack = true;
};
};
};
};
}

View file

@ -0,0 +1,15 @@
{ config, lib, ... }:
{
options.custom.services.printing.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.printing.enable {
services = {
printing.enable = true;
avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
};
};
}

View file

@ -0,0 +1,106 @@
{
config,
pkgs,
lib,
...
}:
let
backupServices = lib.filterAttrs (_: value: value.enable) config.custom.services.resticBackup;
healthchecksEnable = (lib.filterAttrs (_: value: value.healthchecks.enable) backupServices) != { };
in
{
options.custom.services.resticBackup = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
enable = lib.mkEnableOption "" // {
default = true;
};
user = lib.mkOption {
type = lib.types.str;
default = config.users.users.root.name;
};
healthchecks.enable = lib.mkEnableOption "";
extraConfig = lib.mkOption {
type = lib.types.attrsOf lib.types.anything;
default = { };
};
};
}
);
default = { };
};
config = lib.mkIf (backupServices != { }) {
users.groups.backup.members = builtins.filter (user: user != config.users.users.root.name) (
lib.mapAttrsToList (_: value: value.user) backupServices
);
sops.secrets =
let
resticPermissions = {
mode = "440";
group = config.users.groups.backup.name;
};
in
{
"restic/environment" = resticPermissions;
"restic/password" = resticPermissions;
"healthchecks-ping-key" = lib.mkIf healthchecksEnable resticPermissions;
};
systemd.tmpfiles.rules = lib.mapAttrsToList (
name: value:
"d /var/cache/restic-backups-${name} 700 ${value.user} ${config.users.groups.backup.name} -"
) backupServices;
services.restic.backups = lib.mapAttrs (
name: value:
lib.mkMerge [
{
inherit (value) user;
initialize = true;
repository = "s3:https://s3.eu-central-003.backblazeb2.com/stork-atlas/${name}";
environmentFile = config.sops.secrets."restic/environment".path;
passwordFile = config.sops.secrets."restic/password".path;
pruneOpts = [
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 6"
"--keep-yearly 1"
];
timerConfig = {
OnCalendar = "03:00";
RandomizedDelaySec = "1h";
};
}
value.extraConfig
]
) backupServices;
systemd.services = lib.mkMerge [
(lib.mapAttrs' (
name: _:
lib.nameValuePair "restic-backups-${name}" {
wants = [ "healthcheck-ping@${name}-backup_start.service" ];
onSuccess = [ "healthcheck-ping@${name}-backup.service" ];
onFailure = [ "healthcheck-ping@${name}-backup_fail.service" ];
}
) (lib.filterAttrs (_: value: value.healthchecks.enable) backupServices))
(lib.mkIf healthchecksEnable {
"healthcheck-ping@" = {
description = "Pings healthcheck (%i)";
serviceConfig.Type = "oneshot";
scriptArgs = "%i";
script = ''
${lib.getExe pkgs.curl} --fail --silent --show-error --max-time 10 --retry 5 https://hc-ping.com/$(cat ${
config.sops.secrets."healthchecks-ping-key".path
})/$(echo $1 | tr _ /)
'';
};
})
];
};
}

View file

@ -0,0 +1,20 @@
{ config, lib, ... }:
{
options.custom.services.sound.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.sound.enable {
security.rtkit.enable = true;
services = {
pulseaudio.enable = false;
pipewire = {
enable = true;
wireplumber.enable = true;
pulse.enable = true;
alsa = {
enable = true;
support32Bit = true;
};
};
};
};
}

View file

@ -0,0 +1,64 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.syncthing;
user = config.users.users.syncthing.name;
in
{
options.custom.services.syncthing.backups.enable = lib.mkEnableOption "";
config = lib.mkIf cfg.backups.enable {
assertions = [
{
assertion = cfg.isServer;
message = "syncthing backups can only be made on a server";
}
];
security.polkit = {
enable = true;
extraConfig =
let
service = "syncthing.service";
in
''
polkit.addRule(function(action, subject) {
if (action.id == "org.freedesktop.systemd1.manage-units" &&
action.lookup("unit") == "${service}" &&
subject.user == "${user}") {
return polkit.Result.YES;
}
});
'';
};
custom.services.resticBackup.syncthing = {
inherit user;
healthchecks.enable = true;
extraConfig = {
backupPrepareCommand = "${lib.getExe' pkgs.systemd "systemctl"} stop syncthing.service";
backupCleanupCommand = "${lib.getExe' pkgs.systemd "systemctl"} start syncthing.service";
paths = [ config.services.syncthing.dataDir ];
};
};
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "syncthing-restore";
text = ''
sudo --user=${user} bash -c "
systemctl stop syncthing.service
restic-syncthing restore latest --target /
systemctl start syncthing.service
"
'';
})
];
};
}

View file

@ -0,0 +1,73 @@
{
config,
self,
lib,
...
}:
let
cfg = config.custom.services.syncthing;
in
{
options.custom.services.syncthing = {
enable = lib.mkEnableOption "";
isServer = lib.mkEnableOption "";
deviceId = lib.mkOption {
type = lib.types.nonEmptyStr;
default = "";
};
};
config = lib.mkIf cfg.enable {
services.syncthing = {
enable = true;
user = lib.mkIf (!cfg.isServer) "seb";
group = lib.mkIf (!cfg.isServer) "users";
dataDir = lib.mkIf (!cfg.isServer) "/home/seb";
guiAddress = lib.mkIf cfg.isServer "0.0.0.0:8384";
settings = {
# Get the devices and their ids from the configs of the other hosts
devices =
self.nixosConfigurations
|> lib.filterAttrs (name: _: name != config.networking.hostName)
|> lib.filterAttrs (_: value: value.config.custom.services.syncthing.enable)
|> lib.mapAttrs (
name: value: {
id = value.config.custom.services.syncthing.deviceId;
addresses = [ "tcp://${name}.${value.config.networking.domain}:22000" ];
}
);
folders =
let
genFolders =
folders:
lib.genAttrs folders (name: {
path = "${config.services.syncthing.dataDir}/${name}";
ignorePerms = false;
devices = lib.attrNames config.services.syncthing.settings.devices;
});
in
genFolders [
"Documents"
"Downloads"
"Music"
"Pictures"
"Projects"
"Videos"
];
options = {
globalAnnounceEnabled = false;
localAnnounceEnabled = false;
relaysEnabled = false;
natEnabled = false;
urAccepted = -1;
autoUpgradeIntervalH = 0;
};
};
};
};
}

View file

@ -0,0 +1,66 @@
{
config,
pkgs,
lib,
...
}:
let
nodes = config.custom.services.tailscale.caddyServe |> lib.filterAttrs (_: value: value.enable);
caddy-tailscale = pkgs.caddy.withPlugins {
plugins = [ "github.com/tailscale/caddy-tailscale@v0.0.0-20250207163903-69a970c84556" ];
hash = "sha256-wt3+xCsT83RpPySbL7dKVwgqjKw06qzrP2Em+SxEPto=";
};
in
{
options.custom.services.tailscale.caddyServe = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
enable = lib.mkEnableOption "" // {
default = true;
};
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = name;
};
port = lib.mkOption {
type = lib.types.nullOr lib.types.port;
default = null;
};
};
}
)
);
default = { };
};
config = lib.mkIf (nodes != { }) {
sops.secrets."service-tailscale-auth-key".owner = config.services.caddy.user;
services.caddy = {
enable = true;
package = caddy-tailscale;
enableReload = false;
globalConfig = ''
tailscale {
auth_key {file.${config.sops.secrets."service-tailscale-auth-key".path}}
}
'';
virtualHosts = lib.mapAttrs' (
_: value:
lib.nameValuePair "https://${value.subdomain}.${config.networking.domain}" {
extraConfig = ''
bind tailscale/${value.subdomain}
tailscale_auth
reverse_proxy localhost:${toString value.port}
'';
}
) nodes;
};
};
}

View file

@ -0,0 +1,70 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.custom.services.tailscale;
in
{
options.custom.services.tailscale = {
enable = lib.mkEnableOption "";
subdomain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = config.networking.hostName;
};
ssh.enable = lib.mkEnableOption "";
exitNode.enable = lib.mkEnableOption "";
serve = {
isFunnel = lib.mkEnableOption "";
target = lib.mkOption {
type = lib.types.nullOr lib.types.nonEmptyStr;
default = null;
};
};
};
config = lib.mkIf cfg.enable {
sops.secrets."tailscale-auth-key" = { };
services.tailscale = {
enable = true;
authKeyFile = config.sops.secrets."tailscale-auth-key".path;
openFirewall = true;
useRoutingFeatures =
if (cfg.exitNode.enable || (cfg.serve.target != null)) then "server" else "client";
extraUpFlags = [ "--reset=true" ];
extraSetFlags = [
"--hostname=${cfg.subdomain}"
"--ssh=${lib.boolToString cfg.ssh.enable}"
"--advertise-exit-node=${lib.boolToString cfg.exitNode.enable}"
];
};
systemd.services =
let
mode = if cfg.serve.isFunnel then "funnel" else "serve";
in
{
"tailscaled-${mode}" = lib.mkIf (cfg.serve.target != null) {
after = [
"tailscaled.service"
"tailscaled-autoconnect.service"
];
wants = [ "tailscaled.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStartPre = "${lib.getExe pkgs.tailscale} cert --min-validity 120h ${cfg.subdomain}.${config.networking.domain}";
ExecStart = "${lib.getExe pkgs.tailscale} ${mode} --bg ${cfg.serve.target}";
ExecStop = "${lib.getExe pkgs.tailscale} ${mode} reset";
Restart = "on-failure";
};
};
tailscaled-set.after = [ "tailscaled-autoconnect.service" ];
};
};
}

View file

@ -0,0 +1,71 @@
{
config,
pkgs,
lib,
...
}:
let
pskSsids = [
"WLAN-233151"
"EW90N"
"Fairphone4"
"DSL_EXT"
];
in
{
options.custom.services.wlan.enable = lib.mkEnableOption "";
config = lib.mkIf config.custom.services.wlan.enable (
lib.mkMerge [
{
networking.wireless.iwd = {
enable = true;
settings = {
General.EnableNetworkConfiguration = true;
Settings.AutoConnect = true;
Network.NameResolvingService = "resolvconf";
};
};
environment.systemPackages = [ pkgs.iwgtk ];
sops = {
secrets = {
"wlan/eduroam/password" = { };
"wlan/eduroam/cert" = { };
};
templates."iwd/eduroam.8021x".content = ''
[Security]
EAP-Method=PEAP
EAP-Identity=anonymous@h-da.de
EAP-PEAP-CACert=${config.sops.secrets."wlan/eduroam/cert".path}
EAP-PEAP-Phase2-Method=MSCHAPV2
EAP-PEAP-Phase2-Identity=sebastian.stork@stud.h-da.de
EAP-PEAP-Phase2-Password=${config.sops.placeholder."wlan/eduroam/password"}
'';
};
systemd.tmpfiles.rules = [
"C /var/lib/iwd/eduroam.8021x - - - - ${config.sops.templates."iwd/eduroam.8021x".path}"
];
}
(lib.mkMerge (
lib.forEach pskSsids (ssid: {
sops = {
secrets."wlan/${ssid}/key" = { };
templates."iwd/${ssid}.psk".content = ''
[Security]
Passphrase=${config.sops.placeholder."wlan/${ssid}/key"}
'';
};
systemd.tmpfiles.rules = [
"C /var/lib/iwd/${ssid}.psk - - - - ${config.sops.templates."iwd/${ssid}.psk".path}"
];
})
))
]
);
}