feat(keepalived): init keepalived for pihole

This commit is contained in:
2025-09-14 08:27:13 +02:00
parent 7167ddc06d
commit 438d847d11
6 changed files with 145 additions and 108 deletions

View File

@@ -63,6 +63,10 @@
syncthing = {
enable = true;
};
keepalived = {
enable = true;
interface = "enp6s0";
};
podman = {
enable = true;
gluetun.enable = true;

View File

@@ -48,6 +48,10 @@
fail2ban = {
enable = false;
};
keepalived = {
enable = true;
interface = "enu1u1";
};
podman = {
enable = true;
gluetun.enable = false;

View File

@@ -136,6 +136,7 @@
./server/podman
./server/unbound
./server/uptime-kuma
./server/keepalived
];
};
settings = {

View File

@@ -0,0 +1,73 @@
{
lib,
config,
self,
...
}:
let
unit = "keepalived";
cfg = config.server.${unit};
hostCfg =
hostname:
if hostname == "sobotka" then
{
ip = "192.168.88.14";
priority = 20;
}
else if hostname == "ziggy" then
{
ip = "192.168.88.12";
priority = 10;
}
else
throw "No keepalived config defined for host ${hostname}";
_self = hostCfg config.networking.hostName;
allPeers = [
"192.168.88.12"
"192.168.88.14"
];
# Remove self from peers
peers = builtins.filter (ip: ip != _self.ip) allPeers;
in
{
options.server.${unit} = {
enable = lib.mkEnableOption {
description = "Enable ${unit}";
};
interface = lib.mkOption {
type = lib.types.str;
example = "eth0";
description = "The network interface keepalived should bind to.";
};
};
config = lib.mkIf cfg.enable {
age.secrets.keepalived.file = "${self}/secrets/keepalived.age";
services.keepalived = {
enable = true;
openFirewall = true;
vrrpInstances.VI = {
interface = cfg.interface;
virtualRouterId = 69;
priority = _self.priority;
unicastPeers = peers;
virtualIps = [
{
addr = "10.2.1.69/24";
}
];
extraConfig = ''
authentication {
auth_type PASS
auth_pass ${config.age.secrets.keepalived.path}
}
'';
};
};
};
}

15
secrets/keepalived.age Normal file
View File

@@ -0,0 +1,15 @@
age-encryption.org/v1
-> ssh-ed25519 t9iOEg XWSZ9PaQPb0MFf2ZzsCSFnIdMZsiwTkw1w4u644IVSs
11m94aK8vLC3Ua5bcwwt8vF1BxcUBNd2H9IbFz1L5eM
-> ssh-ed25519 KUYMFA 6S7sUrE7ffua0FIqUXArhEAM+l+X4xuiPNryrfeqJng
EJDyvEiAO4Pi6CfblE6wQ/mZV9ZpYpN2O9iLdEKMQis
-> ssh-ed25519 76RhUQ zyX7okInLUL8QrJ/it8jWWpCP/ZhhFplrohKhCaUAAM
oPpWTH74mwbesxTixAzANIuZg35sz18/6hJUcl8h0Nk
-> ssh-ed25519 Jf8sqw NGjWNNF7NDsO9PcIREorsyA8ggNLKYAKCqyDAQGvuxk
9llH7vdlwPLOLqKLZYpPWh8XB2wlRgnquz2uIKyjr7Y
-> ssh-ed25519 AzmhiA wG85fqKHKmzmnj39XSabc2E0U9waeiIf5klJUfF3n3I
3oA0rEQmsUmwigHGAtQG72kJw43B2/UovAzKN+kUarM
-> ssh-ed25519 qWEgFA HgBCuaJ5GcHMXBstvNR5J7AokqgZ+2WOTa5ScYp6PzM
p5+zVg4fe4dAysDHivbSHrgQMArhpXWKHFiHL4RBwLA
--- gJuBfLa4zVMUzQSRat93ImeNwTX3/WI1RyqHjCaCvSY
<EFBFBD>ˋ<EFBFBD><0E>EqP<71>Ei<45>`7<1F>O<EFBFBD>V>h<08><>Rn<52>~<03><>,o<><6F>es<65>/<2F><>;<3B><>FA0<07>=<3D><>0

View File

@@ -1,118 +1,58 @@
let
# --- Users ---
cnst = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEUub8vbzUn2f39ILhAJ2QeH8xxLSjiyUuo8xvHGx/VB adam@cnst.dev";
kima = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJjoPdpiF8pjKN3ZEHeLEwVxoqwcCdzpVVlZkxJohFdg root@cnix";
# --- Hosts: sobotka ---
usobotka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG5ydTeaWcowmNXdDNqIa/lb5l9w5CAzyF2Kg6U5PSSu cnst@sobotka";
rsobotka = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJWLTYWowtpGmGolmkCE7+l9jr5QEnDqRxoezNqAIe+j root@nixos";
# --- Hosts: ziggy ---
uziggy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICtL8uBsJ3UL4+scqjEcyXYQOVlKziJk9YJ78YP6jCxq cnst@nixos";
rziggy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHnca8xg1MZ4Hx5k5SVFSxcPnWc1O6r7w7JGYzX9aQm8 root@nixos";
# --- Groups ---
core = [
cnst
kima
];
sobotka = [
usobotka
rsobotka
];
ziggy = [
uziggy
rziggy
];
all = core ++ sobotka ++ ziggy;
in
{
"cnstssh.age".publicKeys = [
cnst
kima
];
"cnixssh.age".publicKeys = [
cnst
kima
];
"certpem.age".publicKeys = [
cnst
kima
];
"keypem.age".publicKeys = [
cnst
kima
];
"mailpwd.age".publicKeys = [
cnst
kima
];
"gcapi.age".publicKeys = [
cnst
kima
];
"cloudflareEnvironment.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"vaultwardenEnvironment.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"homepageEnvironment.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"cloudflareFirewallApiKey.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"vaultwardenCloudflared.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"cloudflareDnsApiToken.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"cloudflareDnsCredentials.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"cloudflareDnsCredentialsZiggy.age".publicKeys = [
cnst
kima
uziggy
rziggy
];
"wgCredentials.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"wgSobotkaPrivateKey.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"gluetunEnvironment.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"pihole.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
"piholeZiggy.age".publicKeys = [
cnst
kima
uziggy
rziggy
];
"slskd.age".publicKeys = [
cnst
kima
usobotka
rsobotka
];
# Generic
"cnstssh.age".publicKeys = core;
"cnixssh.age".publicKeys = core;
"certpem.age".publicKeys = core;
"keypem.age".publicKeys = core;
"mailpwd.age".publicKeys = core;
"gcapi.age".publicKeys = core;
# Shared between core + sobotka
"cloudflareEnvironment.age".publicKeys = core ++ sobotka;
"vaultwardenEnvironment.age".publicKeys = core ++ sobotka;
"homepageEnvironment.age".publicKeys = core ++ sobotka;
"cloudflareFirewallApiKey.age".publicKeys = core ++ sobotka;
"vaultwardenCloudflared.age".publicKeys = core ++ sobotka;
"cloudflareDnsApiToken.age".publicKeys = core ++ sobotka;
"cloudflareDnsCredentials.age".publicKeys = core ++ sobotka;
"wgCredentials.age".publicKeys = core ++ sobotka;
"wgSobotkaPrivateKey.age".publicKeys = core ++ sobotka;
"gluetunEnvironment.age".publicKeys = core ++ sobotka;
"pihole.age".publicKeys = core ++ sobotka;
"slskd.age".publicKeys = core ++ sobotka;
# Ziggy-specific
"cloudflareDnsCredentialsZiggy.age".publicKeys = core ++ ziggy;
"piholeZiggy.age".publicKeys = core ++ ziggy;
# Both sobotka + ziggy (for HA stuff like keepalived)
"keepalived.age".publicKeys = core ++ sobotka ++ ziggy;
}