feat: adguard home

feat: implement extra module containers
feat: final smb confi
feat: final nextcloud confi
feat: rework networks ip
feat: move acme and ddclient to server
This commit is contained in:
Patrick Großmann 2024-01-11 22:42:03 +01:00
parent ffd869b97d
commit e469eab2b8
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
32 changed files with 574 additions and 281 deletions

View file

@ -1056,11 +1056,11 @@
"pre-commit-hooks": "pre-commit-hooks_2"
},
"locked": {
"lastModified": 1704938286,
"narHash": "sha256-/uv+N2v5ixqYz7SG8R5GWOTdrNKboHEp85BR5Jdz6qE=",
"lastModified": 1704999567,
"narHash": "sha256-Whj1PFPomS/f97OD30CRrETTH/dmnUJdjEevDLJG4MM=",
"owner": "oddlama",
"repo": "nixos-extra-modules",
"rev": "c55f465ba1f369852ab4122a9fa42c85b4a571de",
"rev": "4744a2844cd74ca9b122fbaaae5ae97159c0d30e",
"type": "github"
},
"original": {

View file

@ -165,7 +165,6 @@
modules = [
./nix/installer-configuration.nix
./modules/config/ssh.nix
{system.stateVersion = stateVersion;}
];
format =
{

View file

@ -17,3 +17,7 @@ system = "x86_64-linux"
[maddy]
type = "nixos"
system = "x86_64-linux"
[elisabeth]
type = "nixos"
system = "x86_64-linux"

View file

@ -1,6 +1,8 @@
{inputs, ...}: {
imports = [
inputs.nixos-hardware.nixosModules.common-gpu-nvidia-nonprime
inputs.nixos-hardware.nixosModules.common-cpu-intel
inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc-hdd
inputs.nixos-hardware.nixosModules.common-pc-ssd
@ -12,7 +14,6 @@
../../modules/optional/xserver.nix
../../modules/optional/secureboot.nix
../../modules/hardware/intel.nix
../../modules/hardware/nintendo.nix
../../modules/hardware/nvidia.nix
../../modules/hardware/physical.nix

View file

@ -43,4 +43,5 @@
fileSystems."/state".neededForBoot = true;
fileSystems."/persist".neededForBoot = true;
fileSystems."/panzer/state".neededForBoot = true;
boot.initrd.systemd.services."zfs-import-panzer".after = ["cryptsetup.target"];
}

View file

@ -4,19 +4,12 @@
};
systemd.network.networks = {
"01-lan1" = {
address = ["192.168.178.30/24"];
gateway = ["192.168.178.1"];
DHCP = "yes";
matchConfig.MACAddress = config.secrets.secrets.local.networking.lan1.mac;
dns = ["192.168.178.2"];
networkConfig = {
IPv6PrivacyExtensions = "yes";
MulticastDNS = true;
};
};
};
networking.extraHosts = ''
192.168.178.32 pgrossmann.org
192.168.178.32 nc.pgrossmann.org
'';
}

View file

@ -0,0 +1,34 @@
{
inputs,
minimal,
lib,
...
}: {
imports =
[
inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc-ssd
inputs.nixos-hardware.nixosModules.common-pc-hdd
inputs.nixos-hardware.nixosModules.common-cpu-amd
inputs.nixos-hardware.nixosModules.common-cpu-amd-pstate
../../modules/config
../../modules/optional/initrd-ssh.nix
../../modules/hardware/physical.nix
../../modules/hardware/zfs.nix
../../modules/services/acme.nix
../../modules/services/ddclient.nix
./net.nix
./fs.nix
]
++ lib.lists.optionals (!minimal) [
./guests.nix
];
services.xserver = {
layout = "de";
xkbVariant = "bone";
};
}

128
hosts/elisabeth/fs.nix Normal file
View file

@ -0,0 +1,128 @@
{
config,
lib,
...
}: {
disko.devices = {
disk = {
internal-ssd = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko.nvme}";
content = with lib.disko.gpt; {
type = "table";
format = "gpt";
partitions = [
(partEfi "boot" "0%" "1GiB")
(partLuksZfs "ssd" "rpool" "1GiB" "100%")
];
};
};
"4TB-hdd-1" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."4TB-1"}";
content = lib.disko.content.luksZfs "hdd-4TB-1" "renaultft";
};
"4TB-hdd-2" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."4TB-2"}";
content = lib.disko.content.luksZfs "hdd-4TB-2" "renaultft";
};
"4TB-hdd-3" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."4TB-3"}";
content = lib.disko.content.luksZfs "hdd-4TB-3" "renaultft";
};
"8TB-hdd-1" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."8TB-1"}";
content = lib.disko.content.luksZfs "hdd-8TB-1" "panzer";
};
"8TB-hdd-2" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."8TB-2"}";
content = lib.disko.content.luksZfs "hdd-8TB-2" "panzer";
};
"8TB-hdd-3" = {
type = "disk";
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko."8TB-3"}";
content = lib.disko.content.luksZfs "hdd-8TB-3" "panzer";
};
};
zpool = with lib.disko.zfs; {
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
panzer = mkZpool {
datasets = {
"safe/guests" = unmountable;
};
};
renaultft = mkZpool {
datasets = {
"safe/guests" = unmountable;
};
};
};
};
services.zrepl = {
enable = true;
settings = {
global = {
logging = [
{
type = "syslog";
level = "info";
format = "human";
}
];
# TODO Monitoring
};
jobs = [
#{
# type = "push";
# name = "push-to-remote";
#}
{
type = "snap";
name = "mach-schnipp-schusss";
filesystems = {
"panzer/safe<" = true;
"rpool/local/state<" = true;
"rpool/safe<" = true;
"renaultft/safe<" = true;
};
snapshotting = {
type = "periodic";
prefix = "zrepl-";
interval = "10m";
timestamp_format = "iso-8601";
};
pruning = {
keep = [
{
type = "regex";
regex = "^zrepl-.*$";
negate = true;
}
{
type = "grid";
grid = lib.concatStringsSep " | " [
"1x1d(keep=all)"
"142x1h(keep=2)"
"90x1d(keep=2)"
"500x7d"
];
regex = "^zrepl-.*$";
}
];
};
}
];
};
};
fileSystems."/state".neededForBoot = true;
fileSystems."/persist".neededForBoot = true;
boot.initrd.systemd.services."zfs-import-panzer".after = ["cryptsetup.target"];
boot.initrd.systemd.services."zfs-import-renaultft".after = ["cryptsetup.target"];
}

130
hosts/elisabeth/guests.nix Normal file
View file

@ -0,0 +1,130 @@
{
config,
stateVersion,
inputs,
lib,
minimal,
nodes,
...
}: let
adguardhomedomain = "adguardhome.${config.secrets.secrets.global.domains.web}";
nextclouddomain = "nc.${config.secrets.secrets.global.domains.web}";
in {
services.nginx = {
enable = true;
recommendedSetup = true;
upstreams.adguardhome = {
servers."TODO:3000" = {};
extraConfig = ''
zone adguardhome 64k ;
keepalive 5 ;
'';
};
virtualHosts.${adguardhomedomain} = {
forceSSL = true;
useACMEHost = "web";
locations."/" = {
proxyPass = "http://adguardhome";
proxyWebsockets = true;
};
extraConfig = ''
allow 192.168.178.0/24;
deny all;
'';
};
upstreams.nextcloud = {
servers."TODO:80" = {};
extraConfig = ''
zone nextcloud 64k ;
keepalive 5 ;
'';
};
virtualHosts.${nextclouddomain} = {
forceSSL = true;
useACMEHost = "web";
locations."/".proxyPass = "http://nextcloud";
extraConfig = ''
client_max_body_size 4G ;
'';
};
};
guests = let
mkGuest = guestName: {
enablePanzer ? false,
enableRenaultFT ? false,
...
}: {
autostart = true;
zfs."/state" = {
pool = "rpool";
dataset = "local/guests/${guestName}";
};
zfs."/persist" = {
pool = "rpool";
dataset = "safe/guests/${guestName}";
};
zfs."/panzer" = lib.mkIf enablePanzer {
pool = "panzer";
dataset = "safe/guests/${guestName}";
};
zfs."/renaultft" = lib.mkIf enableRenaultFT {
pool = "renaultft";
dataset = "safe/guests/${guestName}";
};
modules = [
../../modules/config
../../modules/services/${guestName}.nix
{
node.secretsDir = ./secrets/${guestName};
systemd.network.networks."10-${config.guests.${guestName}.networking.mainLinkName}" = {
DHCP = lib.mkForce "no";
address = [(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.guests.${guestName}.nodeName} config.secrets.secrets.global.net.privateSubnet)];
gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnet)];
};
}
];
};
#deadnix: skip
mkMicrovm = guestName: cfg: {
${guestName} =
mkGuest guestName cfg
// {
backend = "microvm";
microvm = {
system = "x86_64-linux";
macvtap = "lan";
baseMac = config.repo.secrets.local.networking.interfaces.lan.mac;
};
extraSpecialArgs = {
inherit (inputs.self) nodes;
inherit (inputs.self.pkgs.x86_64-linux) lib;
inherit inputs minimal stateVersion;
};
};
};
mkContainer = guestName: cfg: {
${guestName} =
mkGuest guestName cfg
// {
backend = "container";
container.macvlan = "lan";
extraSpecialArgs = {
inherit lib nodes inputs minimal stateVersion;
};
};
};
in
{}
// mkContainer "adguardhome" {}
// mkContainer "nextcloud" {
enablePanzer = true;
}
// mkContainer "samba" {
enablePanzer = true;
enableRenaultFT = true;
};
}

42
hosts/elisabeth/net.nix Normal file
View file

@ -0,0 +1,42 @@
{
config,
lib,
...
}: {
networking = {
inherit (config.secrets.secrets.local.networking) hostId;
};
systemd.network.networks = {
"lan01" = {
address = [(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnet)];
gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnet)];
#matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
matchConfig.Name = "lan";
networkConfig = {
IPv6PrivacyExtensions = "yes";
MulticastDNS = true;
};
};
};
boot.initrd.systemd.network = {
enable = true;
networks = {
# redo the network cause the livesystem has macvlans
"lan01" = {
address = [(lib.net.cidr.host config.secrets.secrets.global.net.ips.${config.node.name} config.secrets.secrets.global.net.privateSubnet)];
gateway = [(lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnet)];
matchConfig.MACAddress = config.secrets.secrets.local.networking.interfaces.lan01.mac;
networkConfig = {
IPv6PrivacyExtensions = "yes";
MulticastDNS = true;
};
};
};
};
# To be able to ping containers from the host, it is necessary
# to create a macvlan on the host on the VLAN 1 network.
networking.macvlans.lan = {
interface = "lan01";
mode = "bridge";
};
}

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> X25519 WretELIMVw/omsoHEMGR7PsFsfiUEfyUmlKMzmrw+wA
IW+zJKWSMfZiKs1LQwuAtej7ZDEvDt5oY+wfWpZoB1c
-> piv-p256 XTQkUA A5MNklHowU6rYbcJBT/+dW0v9Gex5IJ1sC5ksuRsfu1k
VPN/pCvMXi6Uc1uk6yuySK/e8bSjJ66zm4W62leQpBk
-> piv-p256 ZFgiIw Ah5jjfu6nrqXrW7YqfIEKWF3PrLOmEEM5LhRvi5EJVmE
MaVt5imJLBgM3NEw7tc18g9jMwPRl9c5RgCFzDIl8hk
-> piv-p256 5vmPtQ AqViuuU1xW/ngBTWFMjZax9SaQyZ/COo0fHNOwq/8Hkb
MDD3bD8PMS3AWPougqz/BXGGZGGnFPafZ0dc7Xqa0VM
-> piv-p256 ZFgiIw AuTg62739Zom64yEb4FZfA5lyeW9YP9h+3iDQJcQZSuM
TtwsPfCJi6bYH8tpPSdf9ZQlpXUC6t/AT1wM2aCXcNM
-> "-grease
n7GU3iZJjAz/ul8nNXzXYtrR
--- mvuAEeT2IOYZKF9u/htBSJSAxKuzLjx4hR65yyHzPK4
fœ<šJ{ïAzß(Ôz(Z|òxÏ0þhÍiaJd*T,o‡Ì«“A?¯ôò,ùÒ>²?»òe§.*Ð'Lû„ Æ7Õ®®B±÷ˆ®Â=<3D>ÈQ&<>c?*Wã¢#"ðÛù$Ee~?íû1‡í²Aý…ÿ±°aŸñÓ1Elƶx<C2B6>ÄñƼñ\<5C>Ëfµ'ê¼Xb"KÞñØÜf oÄhy|I¨5¦hÐÏÍÕî%?CKÒ <0C>R‰…È5÷ŽC! T7¯ÏÒððñ½'‰zÝIøSΰÖ&­AÖ&l´²®¤†ïþv$JYŸíR<C3AD> DVòO"üô­±Ùåў¥µ LSˆ|€¾øˆ\St,éÅŽÇ€w°Ïɬ<C389>,]>¼Qï8uLä~L&ûhÎ ÑÅ`špÙXÐ)Çål²
ã`ãÓ¸L/Rþ åÖ<ºZ3qW
î®\n]$çlÂÊ>Á<>Døj˜a5ÔÂ@=ñÒ5À|‰‰@Rõü- a½ÊÖµë<C2B5><C3AB>s•³^žŠÆ´—`ašì«b^ƒ0qræˆÙ™F¿%ÖCåë¼Ykª¯à&%<25><>ʪ7V™þUj2¯Ü.¥õ<C2A5>KÞ'«c!†ôÈ°+AÝ è[ ¸<>ö¥r©—¼&òjÉ[<06>†G<E280A0>t2D}ÿ»‚³-ÙHî Þàú€Å¾4ø0奣ýÊå&WÖ,“;}¢ØÀ5ðš¤÷
‰Zmìô^á[=çL Ëa(
4­=NŽ8ø¹=ð<>ƒ¢ü=åKQl“ð^ôm¶¢Aæ´?¸ì*°¾$í+<56>Ç—%UZ"á2²™Bá7ëÈbÅ>ÆMÛÊé(ø§û·ÿbÇAV^Ù¾a1bæg£ûA³ù,:±¢‚Å­íÖöRÙ.RöZ6M„ãšö! BÏ·þQ¶³El
”‰‰ïÓ¹~qö=ê³ üJ<C3BC>R{Œ#¾Ø×fªwQC>®cOºf<>°q¬ªÊä.eY@®Ú_붹»<cï.G˜â®ßÓù9E¬~´ë£¬xPÿ

Binary file not shown.

View file

@ -19,7 +19,6 @@
../../modules/hardware/bluetooth.nix
../../modules/hardware/laptop.nix
../../modules/hardware/intel.nix
../../modules/hardware/physical.nix
../../modules/hardware/pipewire.nix
../../modules/hardware/yubikey.nix

View file

@ -12,7 +12,7 @@
type = "table";
format = "gpt";
partitions = [
(partEfiBoot "boot" "0%" "260MB")
(partEfi "boot" "0%" "260MB")
{
name = "rpool";
content = {
@ -25,7 +25,7 @@
};
};
zpool = with lib.disko.zfs; {
rpool = defaultZpoolOptions // {datasets = defaultZfsDatasets;};
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
};
};
fileSystems."/state".neededForBoot = true;

View file

@ -13,7 +13,7 @@
format = "gpt";
partitions = [
(partGrub "grub" "0%" "1MiB")
(partEfiBoot "bios" "1MiB" "512MiB")
(partEfi "bios" "1MiB" "512MiB")
(partLuksZfs "rpool" "rpool" "512MiB" "100%")
#(lib.attrsets.recursiveUpdate (partLuksZfs "rpool" "rpool" "17GiB" "100%") {content.extraFormatArgs = ["--pbkdf pbkdf2"];})
];
@ -22,7 +22,7 @@
};
zpool = with lib.disko.zfs; {
rpool = defaultZpoolOptions // {datasets = defaultZfsDatasets;};
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
};
};

View file

@ -19,7 +19,6 @@
../../modules/hardware/bluetooth.nix
../../modules/hardware/laptop.nix
../../modules/hardware/intel.nix
../../modules/hardware/nvidia.nix
../../modules/hardware/physical.nix
../../modules/hardware/pipewire.nix

View file

@ -12,7 +12,7 @@
type = "table";
format = "gpt";
partitions = [
(partEfiBoot "boot" "0%" "1GiB")
(partEfi "boot" "0%" "1GiB")
(partSwap "swap" "1GiB" "17GiB")
(partLuksZfs "rpool" "rpool" "17GiB" "100%")
];
@ -20,7 +20,7 @@
};
};
zpool = with lib.disko.zfs; {
rpool = defaultZpoolOptions // {datasets = defaultZfsDatasets;};
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
};
};
fileSystems."/state".neededForBoot = true;

View file

@ -12,7 +12,6 @@
../../modules/config
../../modules/optional/initrd-ssh.nix
../../modules/hardware/intel.nix
../../modules/hardware/physical.nix
../../modules/hardware/zfs.nix

View file

@ -12,7 +12,7 @@
type = "table";
format = "gpt";
partitions = [
(partEfiBoot "boot" "0%" "1GiB")
(partEfi "boot" "0%" "1GiB")
(partSwap "swap" "1GiB" "17GiB")
(lib.attrsets.recursiveUpdate (partLuksZfs "rpool" "rpool" "17GiB" "100%") {content.extraFormatArgs = ["--pbkdf pbkdf2"];})
];
@ -43,10 +43,10 @@
};
zpool = with lib.disko.zfs; {
rpool = defaultZpoolOptions // {datasets = defaultZfsDatasets;};
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
panzer =
defaultZpoolOptions
// {
mkZpool
{
datasets = {
"local" = unmountable;
"local/state" = filesystem "/panzer/state";

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> X25519 +i63saSU8RBHO56nE65z4pFN72weFIH0MO2B6kKFX1o
O03ucWspS7ERnPwqPVVDLpokcR+VDGfeema+7VCdUcE
-> piv-p256 XTQkUA A222BiQ7aVaSdbpTgH0zop6Yc7iD3o9p+DpBT/53cfsI
NiOx77wz7D8tIWOitsVynStIGjUlDaXfYdjAvjvpV68
-> piv-p256 ZFgiIw AgR85lUO7c+rwARcAkHBzoWONva7zDwCZ8hGNhP5FNXb
iIWz22A6YIzLlEbOhA6AwIVS5B4mOOLUMUvjel/QPPM
-> piv-p256 5vmPtQ Ao50NLd25O1sdk96G8a3acSjhOwfq+DbHiVl6q/E+2+3
4R9ScWJsjyLxUqVTaKfzmsMvbZQH8shiqPbIGshbNpA
-> piv-p256 ZFgiIw A90xpxtG8MMDmsQpgx5fRavYIrmlv0rkcjev3LZYKRnS
2Wc3c2LPcWcRfL5+yH/GNWwblkofSrY/Bj7AxuOPX8g
-> `tr=>/j-grease Fr#5$ANy D0UHo: aD
F8V7YAtFk4XQjKdsN/pwtYnH
--- wCUeLyGHUi/Qwc7INkFXilCQz/N5rRgVtZ3TQu6jfgU
Lnţ62ú6:©†F¬Ö•tW<74>őô†Rm®ŠÓňęĂň\ÂmbiÝ°ˇÁŞPśµç‡ĹWŽEd!ő™[/B
k«żÜ÷4`hC¨Lł˝řĚęS

View file

@ -1,4 +1,3 @@
inputs: [
(import ./containers.nix inputs)
(import ./misc.nix inputs)
]

View file

@ -1,10 +1,13 @@
{
inputs,
lib,
stateVersion,
pkgs,
config,
...
}: {
system.stateVersion = stateVersion;
age.rekey = {
inherit
(inputs.self.secretsConfig)

View file

@ -1,4 +0,0 @@
{
powerManagement.cpuFreqGovernor = "powersave";
hardware.cpu.intel.updateMicrocode = true;
}

View file

@ -0,0 +1,65 @@
{config, ...}: {
services.adguardhome = {
enable = true;
mutableSettings = false;
openFirewall = true; # opens webinterface firewall
settings = {
bind_port = 3000;
bind_host = "0.0.0.0";
dns = {
bind_hosts = ["TODO"];
anonymize_client_ip = true;
upstream_dns = [
"1.0.0.1"
"2606:4700:4700::1111"
"8.8.8.8"
"2001:4860:4860::8844"
];
bootstrap_dns = [
"1.0.0.1"
"2606:4700:4700::1111"
"8.8.8.8"
"2001:4860:4860::8844"
];
};
user_rules = ''
||${config.secrets.secrets.global.domains.web}^$dnsrewrite=TODO
'';
dhcp.enabled = false;
ratelimit = 60;
users = [
{
name = "patrick";
password = "$2b$05$Dapc2LWUfebNOgIeBcaf2OVhW7uKmthmp9Ptykn96Iw1UE5pt2U72";
}
];
filters = [
{
name = "AdGuard DNS filter";
url = "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt";
enabled = true;
}
{
name = "AdaAway Default Blocklist";
url = "https://adaway.org/hosts.txt";
enabled = true;
}
{
name = "OISD (Big)";
url = "https://big.oisd.nl";
enabled = true;
}
];
};
};
networking.firewall = {
allowedTCPPorts = [53];
allowedUDPPorts = [53];
};
environment.persistence."/persist".directories = [
{
directory = "/var/lib/private/AdGuardHome";
mode = "0700";
}
];
}

View file

@ -1,118 +0,0 @@
{
config,
lib,
utils,
pkgs,
...
}: let
inherit
(lib)
mapAttrs'
concatStrings
nameValuePair
mapAttrsToList
flip
types
mkOption
mkEnableOption
mdDoc
mkIf
disko
makeBinPath
escapeShellArg
mkMerge
;
in {
options.containers = mkOption {
type = types.attrsOf (types.submodule (
{name, ...}: {
options = {
zfs = {
enable = mkEnableOption (mdDoc "persistent data on separate zfs dataset");
pool = mkOption {
type = types.str;
description = mdDoc "The host's zfs pool on which the dataset resides";
};
dataset = mkOption {
type = types.str;
default = "safe/containers/${name}";
description = mdDoc "The host's dataset that should be used for this containers persistent data (will automatically be created)";
};
mountpoint = mkOption {
type = types.str;
description = mdDoc "The host's mountpoint for the containers dataset";
};
};
};
}
));
};
config.system.activationScripts = let
mkDir = paths: (concatStrings (flip map paths (path: ''
[[ -d "${path}" ]] || ${pkgs.coreutils}/bin/mkdir -p "${path}"
'')));
in
flip mapAttrs' config.containers (
name: value:
nameValuePair "mkContainerFolder-${name}" (mkDir (mapAttrsToList (_: x: x.hostPath) value.bindMounts))
);
config.disko = mkMerge (flip mapAttrsToList config.containers
(
_: cfg: {
devices.zpool = mkIf cfg.zfs.enable {
${cfg.zfs.pool}.datasets."${cfg.zfs.dataset}" =
disko.zfs.filesystem cfg.zfs.mountpoint;
};
# Ensure that the zfs dataset exists before it is mounted.
}
));
config.systemd = mkMerge (flip mapAttrsToList config.containers
(
name: cfg: {
services = let
fsMountUnit = "${utils.escapeSystemdPath cfg.zfs.mountpoint}.mount";
in
mkIf cfg.zfs.enable {
# Ensure that the zfs dataset exists before it is mounted.
"zfs-ensure-${utils.escapeSystemdPath cfg.zfs.mountpoint}" = {
wantedBy = [fsMountUnit];
before = [fsMountUnit];
after = [
"zfs-import-${utils.escapeSystemdPath cfg.zfs.pool}.service"
"zfs-mount.target"
];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = let
poolDataset = "${cfg.zfs.pool}/${cfg.zfs.dataset}";
diskoDataset = config.disko.devices.zpool.${cfg.zfs.pool}.datasets.${cfg.zfs.dataset};
in ''
export PATH=${makeBinPath [pkgs.zfs]}":$PATH"
if ! zfs list -H -o type ${escapeShellArg poolDataset} &>/dev/null ; then
${diskoDataset._create}
fi
'';
};
# Ensure that the zfs dataset has the correct permissions when mounted
"zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}" = {
after = [fsMountUnit];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
chmod 755 ${escapeShellArg cfg.zfs.mountpoint}
'';
};
"container@${name}" = {
requires = [fsMountUnit "zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}.service"];
after = [fsMountUnit "zfs-chown-${utils.escapeSystemdPath cfg.zfs.mountpoint}.service"];
};
};
}
));
}

View file

@ -5,11 +5,11 @@
};
services.ddclient = {
enable = true;
zone = config.secrets.secrets.global.domains.mail;
zone = config.secrets.secrets.global.domains.web;
protocol = "Cloudflare";
username = "token";
use = "web, web='https://cloudflare.com/cdn-cgi/trace', web-skip='ip='";
passwordFile = config.age.secrets.cloudflare_token_dns.path;
domains = [config.secrets.secrets.global.domains.mail];
domains = [config.secrets.secrets.global.domains.web];
};
}

View file

@ -1,47 +1,13 @@
{
lib,
stateVersion,
config,
#deadnix: skip
pkgs, # not unused needed for the usage of attrs later to contains pkgs
...
} @ attrs: let
hostName = "nc.${config.secrets.secrets.global.domains.mail}";
in {
imports = [./containers.nix ./ddclient.nix ./acme.nix];
services.nginx = {
enable = true;
recommendedSetup = true;
upstreams.nextcloud = {
servers."192.168.178.33:80" = {};
extraConfig = ''
zone nextcloud 64k ;
keepalive 5 ;
'';
};
virtualHosts.${hostName} = {
forceSSL = true;
useACMEHost = "mail";
locations."/".proxyPass = "http://nextcloud";
extraConfig = ''
client_max_body_size 4G ;
'';
};
};
containers.nextcloud = lib.containers.mkConfig "nextcloud" attrs {
zfs = {
enable = true;
pool = "panzer";
};
config = {
config,
pkgs,
config,
...
}: {
#TODO enable recommended nginx setup
}: let
hostName = "nc.${config.secrets.secrets.global.domains.web}";
in {
systemd.network.networks = {
"lan01" = {
"TODO" = {
address = ["192.168.178.33/24"];
gateway = ["192.168.178.1"];
matchConfig.Name = "lan01*";
@ -53,6 +19,14 @@ in {
};
};
environment.persistence."/persist".directories = [
{
directory = "/var/lib/postgresql/";
user = "postgres";
group = "postgres";
mode = "750";
}
];
environment.persistence."/panzer".directories = [
{
directory = config.services.nextcloud.home;
user = "nextcloud";
@ -60,23 +34,34 @@ in {
mode = "750";
}
];
age.secrets.ncpasswd = {
generator.script = "alnum";
mode = "440";
owner = "nextcloud";
};
services.postgresql.package = pkgs.postgresql_16;
services.nginx.virtualHosts.${hostName}.extraConfig = ''
allow TODO;
deny all;
'';
services.nextcloud = {
inherit hostName;
enable = true;
package = pkgs.nextcloud28;
configureRedis = true;
config.adminpassFile = "${pkgs.writeText "adminpass" "test123"}"; # DON'T DO THIS IN PRODUCTION - the password file will be world-readable in the Nix Store!
config.adminpassFile = config.age.secrets.ncpasswd.path; # Kinda ok just remember to instanly change after first setup
config.adminuser = "admin";
extraApps = with config.services.nextcloud.package.packages.apps; {
inherit contacts calendar tasks notes maps;
inherit contacts calendar tasks notes maps phonetrack;
};
maxUploadSize = "2G";
maxUploadSize = "4G";
extraAppsEnable = true;
database.createLocally = true;
phpOptions."opcache.interned_strings_buffer" = "32";
extraOptions = {
default_phone_region = "DE";
trusted_proxies = ["192.168.178.32"];
trusted_proxies = ["TODO"];
overwriteprotocol = "https";
enabledPreviewProviders = [
"OC\\Preview\\BMP"
@ -97,26 +82,11 @@ in {
};
};
system.stateVersion = stateVersion;
networking = {
firewall = {
enable = true;
allowedTCPPorts = [80];
};
firewall.allowedTCPPorts = [80];
# Use systemd-resolved inside the container
useHostResolvConf = lib.mkForce false;
};
services.resolved.enable = true;
};
};
}
#wireguard
#samba/printer finding
#vaultwarden
#maddy
#kanidm
#remote backups
#immich

View file

@ -3,17 +3,16 @@
lib,
...
}: {
services.samba-wsdd.enable = true; # make shares visible for windows 10 clients
networking.firewall.allowedTCPPorts = [
5357 # wsdd
];
networking.firewall.allowedUDPPorts = [
3702 # wsdd
];
services.samba-wsdd = {
enable = true; # make shares visible for windows 10 clients
openFirewall = true;
};
services.samba = {
enable = true;
securityType = "user";
openFirewall = true;
enableWinbindd = false;
enableNmbd = false;
extraConfig = lib.concatLines [
''
logging = systemd
@ -56,10 +55,12 @@
name,
user ? "smb",
group ? "smb",
persistRoot ? "/panzer",
}: cfg: {
"${name}" =
{
"path" = "/media/smb/${name}";
"#persistRoot" = persistRoot;
"read only" = "no";
"guest ok" = "no";
"create mask" = "0640";
@ -101,7 +102,10 @@
user = "family";
group = "family";
} {})
((mkShare {name = "media";})
(mkShare {
name = "media";
persistRoot = "/renaultft";
}
{
"read only" = "yes";
"write list" = "@family";
@ -149,10 +153,14 @@
}));
};
environment.persistence."/panzer/persist".directories = lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: {
environment.persistence = lib.mkMerge (lib.flip lib.mapAttrsToList config.services.samba.shares (_: v: {
${v."#persistRoot"}.directories = [
{
directory = "${v.path}";
user = "${v."force user"}";
group = "${v."force group"}";
mode = "0770";
});
}
];
}));
}

View file

@ -48,13 +48,18 @@ inputs: let
nixosConfigurations = flip mapAttrs nixosHosts (mkHost {minimal = false;});
minimalConfigurations = flip mapAttrs nixosHosts (mkHost {minimal = true;});
# True NixOS nodes can define additional microvms (guest nodes) that are built
# together with the true host. We collect all defined microvm nodes
# from each node here to allow accessing any node via the unified attribute `nodes`.
# True NixOS nodes can define additional guest nodes that are built
# together with it. We collect all defined guests from each node here
# to allow accessing any node via the unified attribute `nodes`.
guestConfigurations = flip concatMapAttrs self.nixosConfigurations (_: node:
mapAttrs'
(vm: _: nameValuePair vm {inherit (node.config.containers.${vm}) config;})
(node.config.containers or {}));
flip mapAttrs' (node.config.guests or {}) (
guestName: guestDef:
nameValuePair guestDef.nodeName (
if guestDef.backend == "microvm"
then node.config.microvm.vms.${guestName}.config
else node.config.containers.${guestName}.nixosConfiguration
)
));
in {
inherit
hosts

Binary file not shown.