commit d87d6856da63c5c358a38ee5e28f403d92d15fbc
parent 80bc076559a6cb8c7a5038c3194465b14076487e
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 4 Mar 2025 11:12:53 +0100
parent 80bc076559a6cb8c7a5038c3194465b14076487e
Author: Katja (ctucx) <git@ctu.cx>
Date: Tue, 4 Mar 2025 11:12:53 +0100
machines: refactor
54 files changed, 1452 insertions(+), 1622 deletions(-)
A
|
64
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
204
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
R
|
0
A
|
47
+++++++++++++++++++++++++++++++++++++++++++++++
A
|
216
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
36
++++++++++++++++++++++++++++++++++++
A
|
102
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
199
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
123
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
61
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
52
++++++++++++++++++++++++++++++++++++++++++++++++++++
A
|
82
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
D
|
64
----------------------------------------------------------------
D
|
204
-------------------------------------------------------------------------------
D
|
217
-------------------------------------------------------------------------------
D
|
102
-------------------------------------------------------------------------------
D
|
82
-------------------------------------------------------------------------------
D
|
199
-------------------------------------------------------------------------------
D
|
123
-------------------------------------------------------------------------------
D
|
64
----------------------------------------------------------------
D
|
82
-------------------------------------------------------------------------------
M
|
70
+++++++++++++++++++++++++++++++++++++---------------------------------
diff --git a/configurations/nixos/configure/router/ppp.nix b/configurations/nixos/configure/router/ppp.nix @@ -0,0 +1,64 @@ +{ config, utils, pkgs, ... }: + +{ + + age.secrets.pppd-env.file = ./. + "/../../../../secrets/${config.networking.hostName}/pppd-env.age"; + + services.pppd = { + enable = true; + peers.dtagdsl = { + config = '' + plugin pppoe.so dtagdsl + user "''${DTAG_PPP_USER}" + password "''${DTAG_PPP_PASS}" + hide-password + ifname ppp-dtagdsl + persist + + maxfail 0 + holdoff 5 + + noipdefault + + lcp-echo-interval 20 + lcp-echo-failure 3 + + mtu 1492 + defaultroute + replacedefaultroute + +ipv6 + ''; + }; + }; + + environment.etc."ppp/peers/dtagdsl".enable = false; + environment.etc."ip-up.d/1systemd-networkd" = { + mode = "755"; + text = '' + #!{pkgs.bash}/bin/bash + networkctl reconfigure "$PPP_IFACE"; + ''; + }; + + systemd.services."pppd-dtagdsl".serviceConfig = let + preStart = '' + mkdir -p /etc/ppp/peers + + # Created files only readable by root + umask u=rw,g=,o= + + # Copy config and substitute env-vars + rm -f /etc/ppp/peers/dtagdsl + ${pkgs.envsubst}/bin/envsubst -i "${config.environment.etc."ppp/peers/dtagdsl".source}" > /etc/ppp/peers/dtagdsl + ''; + + preStartFile = utils.systemdUtils.lib.makeJobScript { name = "pppd-dtagdsl-pre-start"; text = preStart; enableStrictShellChecks = true; }; + in { + EnvironmentFile = config.age.secrets.pppd-env.path; + ExecStartPre = [ + # "+" marks script to be executed without priviledge restrictions + "+${preStartFile}" + ]; + }; + +}
diff --git a/configurations/nixos/configure/router/systemd-networkd.nix b/configurations/nixos/configure/router/systemd-networkd.nix @@ -0,0 +1,204 @@ +{ config, ... }: + +{ + +# systemd.services."systemd-networkd".serviceConfig.Environment = "SYSTEMD_LOG_LEVEL=debug"; + + age.secrets.wireguard-privkey = { + file = ./. + "../../../../../secrets/${config.networking.hostName}/wireguard-privkey.age"; + mode = "640"; + owner = "root"; + group = "systemd-network"; + }; + + systemd.network = { + enable = true; + wait-online.enable = false; + + config.networkConfig = { + IPv6Forwarding = true; + }; + + links."5-dtagdsl" = { + matchConfig.PermanentMACAddress = "d0:37:45:06:de:de"; + linkConfig.Name = "dtagdsl"; + }; + + links."5-iphone" = { + matchConfig.PermanentMACAddress = "aa:ab:b5:18:95:d9"; + linkConfig.Name = "iphone"; + }; + + netdevs."20-brlan" = { + netdevConfig = { + Kind = "bridge"; + Name = "brlan"; + }; + }; + + netdevs."10-wg-wanderduene" = { + netdevConfig = { + Kind = "wireguard"; + Name = "wg-wanderduene"; + }; + + wireguardConfig = { + PrivateKeyFile = config.age.secrets.wireguard-privkey.path; + ListenPort = 51820; + FirewallMark = 51820; + }; + + wireguardPeers = [{ + Endpoint = "wanderduene.ctu.cx:51820"; + PublicKey = "hOUeP8RFchzJXyy8DceTFKN9f1VHi9GzZQii0dX2zww="; + AllowedIPs = [ "::/0" ]; + PersistentKeepalive = 10; + }]; + }; + + networks = { + "5-dtagdsl" = { + matchConfig.Name = "dtagdsl"; + + linkConfig.RequiredForOnline = false; + networkConfig.LinkLocalAddressing = false; + }; + + "5-enp1s0" = { + matchConfig.Name = "enp1s0"; + + networkConfig.ConfigureWithoutCarrier = true; + bridge = [ "brlan" ]; + }; + + "5-iphone" = { + matchConfig.Name = "iphone"; + + networkConfig.DHCP = true; + }; + + "10-ppp-dtagdsl" = { + matchConfig.Name = "ppp-dtagdsl"; + + networkConfig = { + KeepConfiguration = true; + IPv6AcceptRA = true; + DHCP = "ipv6"; + }; + + ipv6AcceptRAConfig = { + UseDNS = false; + }; + + dhcpV6Config = { + WithoutRA = "solicit"; + PrefixDelegationHint = "::/56"; + IAID = 0; + UseDNS = false; + }; + }; + + "10-wg-wanderduene" = { + matchConfig.Name = "wg-wanderduene"; + + linkConfig.RequiredForOnline = false; + routes = [{ + Destination = "::/0"; + Table = "1234"; + }]; + }; + + "20-brlan" = { + matchConfig = { + Name = "brlan"; + Driver = "bridge"; + }; + + address = [ "10.0.0.1/8" "2a03:4000:4d:5e:acab::1/112" ]; + + routingPolicyRules = [ + { + From = "2a03:4000:4d:5e:acab::/112"; + Table = 254; + Priority = 1900; + SuppressPrefixLength = 0; + } + { + From = "2a03:4000:4d:5e:acab::/112"; + Table = 1234; + Priority = 2000; + } + ]; + + networkConfig = { + ConfigureWithoutCarrier = true; + IPv4Forwarding = true; + IPMasquerade = "ipv4"; + + DHCPPrefixDelegation = true; + IPv6PrivacyExtensions = false; + IPv6AcceptRA = false; + IPv6SendRA = true; + + DHCPServer = true; + DNS = "10.0.0.1"; + }; + + dhcpPrefixDelegationConfig = { + UplinkInterface = "ppp-dtagdsl"; + Announce = true; + SubnetId = 0; + Token = "::1"; + }; + + ipv6SendRAConfig = { + EmitDNS = true; + DNS = "_link_local"; + }; + + ipv6PREF64Prefixes = [{ + Prefix = "64:ff9b::/96"; + }]; + + dhcpServerConfig = { + PersistLeases = true; + PoolOffset = 100; + PoolSize = 100; + EmitDNS = true; + DNS = "10.0.0.1"; + IPv6OnlyPreferredSec = 300; + }; + + dhcpServerStaticLeases = [ + { + # accesspoint + MACAddress = "48:a9:8a:8e:dd:0b"; + Address = "10.0.0.2"; + } + { + # pbx + MACAddress = "34:31:c4:46:88:31"; + Address = "10.0.0.3"; + } + { + # scanner + MACAddress = "5c:f3:70:b9:35:9c"; + Address = "10.0.0.4"; + } + { + # printer + MACAddress = "70:77:81:2a:e7:96"; + Address = "10.0.0.5"; + } + { + # katja x13 + MACAddress = "04:CF:4B:76:93:55"; + Address = "10.0.0.10"; + } + ]; + }; + + }; + }; + +}
diff --git a/configurations/nixos/configure/smarthome/influxdb2.nix b/configurations/nixos/configure/smarthome/influxdb2.nix @@ -0,0 +1,36 @@ +{ config, pkgs, lib, ... }: + +{ + + dns.zones."ctu.cx".subdomains."influx.home".AAAA = [ config.networking.primaryIP ]; + + age.secrets.restic-influxdb.file = ./. + "/../../../../secrets/${config.networking.hostName}/restic/influxdb.age"; + age.secrets.influx-backup-env.file = ./. + "/../../../../secrets/${config.networking.hostName}/influx/backup_env.age"; + + systemd.services.restic-backup-influxdb.serviceConfig.EnvironmentFile = config.age.secrets.influx-backup-env.path; + + restic-backups.influxdb = { + user = "influxdb2"; + passwordFile = config.age.secrets.restic-influxdb.path; + influxBuckets = [ "mqttData" ]; + }; + + systemd.services.influxdb2 = { + serviceConfig.ExecStartPost = "${pkgs.bash}/bin/bash -c 'until ${pkgs.netcat}/bin/nc -z ::1 8086; do sleep 0.2; done'"; + onFailure = [ "email-notify@%i.service" ]; + }; + + services.influxdb2.enable = true; + services.influxdb2.settings.http-bind-address = "[::1]:8086"; + + services.nginx = { + enable = true; + virtualHosts."influx.home.ctu.cx" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + kTLS = true; + locations."/".proxyPass = "http://${toString config.services.influxdb2.settings.http-bind-address}/"; + }; + }; + +}
diff --git a/configurations/nixos/configure/smarthome/mosquitto.nix b/configurations/nixos/configure/smarthome/mosquitto.nix @@ -0,0 +1,47 @@ +{ inputs, config, pkgs, ... }: + +{ + + age.secrets = { + mosquitto-passwd-katja = { + file = ./. + "/../../../../secrets/${config.networking.hostName}/mosquitto/passwd-katja.age"; + owner = "mosquitto"; + }; + }; + + services = { + mosquitto = { + enable = true; + persistence = false; + settings = { + max_keepalive = 60; + }; + listeners = [ + + { + port = 1883; + omitPasswordAuth = true; + users = {}; + settings = { + allow_anonymous = true; + }; + acl = [ "topic readwrite #" "pattern readwrite #" ]; + } + + { + address = "::1"; + port = 9005; + users = { + katja.passwordFile = config.age.secrets.mosquitto-passwd-katja.path; + }; + settings = { + protocol = "websockets"; + }; + acl = [ "topic readwrite #" "pattern readwrite #" ]; + } + + ]; + }; + }; + +}
diff --git a/configurations/nixos/configure/smarthome/mqtt-webui/config.nix b/configurations/nixos/configure/smarthome/mqtt-webui/config.nix @@ -0,0 +1,216 @@ +let + + Switch = name: topic: { + title = name; + type = "switch"; + icon = "icons/power_button.png"; + topic.get = topic; + topic.set = "${topic}/set"; + transform.get = "return (message.state == 'ON') ? true : false"; + transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})"; + }; + + BrighnessSlider = name: topic: { + title = name; + type = "slider"; + icon = "icons/bulb.png"; + sliderMinValue = 0; + sliderMaxValue = 254; + sliderStepValue = 1; + topic.get = topic; + topic.set = "${topic}/set"; + transform.get = "return message.brightness"; + transform.set = "return JSON.stringify({brightness: Number(input)})"; + }; + + ColorTemperatureSlider = name: topic: { + title = name; + type = "slider"; + icon = "icons/bulb.png"; + sliderMinValue = 250; + sliderMaxValue = 454; + sliderStepValue = 1; + topic.get = topic; + topic.set = "${topic}/set"; + transform.get = "return message.color_temp"; + transform.set = "return JSON.stringify({color_temp: Number(input)})"; + }; + + DimmableLamp = name: topic: { + title = name; + items = [ + (Switch "Power" topic) + (BrighnessSlider "Brighness" topic) + ]; + }; + + WhiteSpectrumLamp = name: topic: { + title = name; + items = [ + (Switch "Power" topic) + (BrighnessSlider "Brighness" topic) + (ColorTemperatureSlider "Color Temperature" topic) + ]; + }; + + ColorSpectrumLamp = name: topic: { + title = name; + items = [ + (Switch "Power" topic) + (BrighnessSlider "Brighness" topic) + (ColorTemperatureSlider "Color Temperature" topic) + + { + title = "Color"; + type = "select"; + icon = "icons/bulb.png"; + topic.get = topic; + topic.set = "${topic}/set"; + transform.get = "return message.color.x + ','+message.color.y"; + transform.set = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})"; + selectOptions = [ + { + label = "Red"; + value = "0.71,0.26"; + } + { + label = "Green"; + value = "0.19,0.78"; + } + { + label = "Blue"; + value = "0.09,0.13"; + } + ]; + } + ]; + }; + + +in { + + appName = "Smart-Home"; + extraCSS = "/extra.css"; + pages = [ + { + id = "mainpage"; + icon = "favicon-512x512.png"; + title = "Smart-Home"; + sections = [ + + (WhiteSpectrumLamp "Hallway" "zigbee2mqtt/ikea_lamp_hallway") + + (WhiteSpectrumLamp "Living room" "zigbee2mqtt/ikea_lamp_livingroom") + + (WhiteSpectrumLamp "Sleeping room" "zigbee2mqtt/ikea_lamp_sleepingroom") + + (DimmableLamp "Desk" "zigbee2mqtt/tuya_led_stripe_desk") + + (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_rgb") + + { + title = "Temperature-Sensors"; + items = [ + { + title = "Fridge"; + type = "text"; + topic = "zigbee2mqtt/tuya_sensor_fridge"; + icon = "icons/temperature.png"; + transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; + } + { + title = "Bathroom"; + type = "text"; + topic = "zigbee2mqtt/tuya_sensor_bathroom"; + icon = "icons/temperature.png"; + transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; + } + + { + title = "Door"; + type = "text"; + topic = "zigbee2mqtt/tuya_sensor_l"; + icon = "icons/temperature.png"; + transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; + } + { + title = "Bed"; + type = "text"; + topic = "zigbee2mqtt/tuya_sensor_l2"; + icon = "icons/temperature.png"; + transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; + } + + ]; + } + + { + items = [ + { + title = "Departures"; + type = "text"; + icon = "icons/electric_range.png"; + link = "#departures"; + } + { + title = "Grafana-Dashboard"; + type = "text"; + icon = "icons/sun.png"; + link = "https://grafana.ctu.cx/d/FRDYqjEGz/smarthome-influx?orgId=1&refresh=5s"; + } + ]; + } + + ]; + } + + { + id = "departures"; + title = "Departures"; + sections = [ + { + items = [ + { + type = "html"; + topic = "departures2mqtt"; + html = "<div class=\"loader\"></div>"; + transform = '' + clearInterval(globalThis.departuresUpdater) + globalThis.departuresUpdater = setInterval(() => { + let element = document.querySelector('[data-last-updated]'); + element.textContent = 'Last Update: ' + (Math.floor(Date.now() / 1000) - element.dataset.lastUpdated) + ' seconds ago'; + }, 10000) + + let output = ""; + + Object.entries(message.departures).forEach((data) => { + output += '<div class="departures"><div class="table-column table-title">' + data[0] + '</div><div class="table">'; + + output += '<div class="table-row line-column"><div class="table-column table-heading">Linie</div>'; + data[1].forEach((departure) => output += '<div class="table-column">' + departure.line + '</div>'); + output += '</div>'; + + output += '<div class="table-row direction-column"><div class="table-column table-heading">Richtung</div>'; + data[1].forEach((departure) => output += '<div class="table-column">' + departure.direction + '</div>'); + output += '</div>'; + + output += '<div class="table-row dep-column"><div class="table-column table-heading">Abfahrt</div>'; + data[1].forEach((departure) => output += '<div class="table-column">' + (Number(departure.departure_in) ? departure.departure_in + " min" : "sofort") + '</div>'); + output += '</div>'; + + output += '</div></div>'; + }); + + output += '<div class="lastUpdated" data-last-updated="' + message.lastUpdated + '">Last Update: ' + (Math.floor(Date.now() / 1000) - message.lastUpdated) + ' seconds ago</div>'; + + return output; + ''; + } + ]; + } + ]; + } + + ]; + +}
diff --git a/configurations/nixos/configure/smarthome/mqtt-webui/default.nix b/configurations/nixos/configure/smarthome/mqtt-webui/default.nix @@ -0,0 +1,36 @@ +{ inputs, lib, pkgs, config, ... }: + +let + configFile = pkgs.writeTextDir "config.json" (builtins.toJSON (import ./config.nix)); + +in { + + dns.zones."ctu.cx".subdomains."smart.home".AAAA = [ config.networking.primaryIP ]; + + services.nginx = { + enable = true; + virtualHosts."smart.home.ctu.cx" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + kTLS = true; + + locations = { + "/" = { + root = "${pkgs.buildEnv { + name = "mqtt-webui-env"; + paths = [ + pkgs.mqtt-webui + configFile + ./extra-css + ]; + }}/"; + }; + "/mqtt" = { + proxyPass = "http://[::1]:9005"; + proxyWebsockets = true; + }; + }; + }; + }; + +}
diff --git a/configurations/nixos/configure/smarthome/mqtt-webui/extra-css/manifest.json b/configurations/nixos/configure/smarthome/mqtt-webui/extra-css/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "Smart-Home", + "short_name": "Smart-Home", + "start_url": ".", + "display": "standalone", + "icons": [ + { + "src": "favicon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +}
diff --git a/configurations/nixos/configure/smarthome/telegraf.nix b/configurations/nixos/configure/smarthome/telegraf.nix @@ -0,0 +1,40 @@ +{ inputs, config, ... }: + +{ + + age.secrets.telegraf-env = { + file = ./. + "/../../../../secrets/${config.networking.hostName}/telegraf/secrets.env.age"; + owner = "telegraf"; + }; + + services.telegraf = { + enable = true; + environmentFiles = [ config.age.secrets.telegraf-env.path ]; + extraConfig = { + inputs = { + mqtt_consumer = { + servers = [ "tcp://[::1]:1883" ]; + topics = [ + "zigbee2mqtt/tuya_sensor_fridge" + "zigbee2mqtt/tuya_sensor_bathroom" + "zigbee2mqtt/tuya_sensor_sleepingroom" + "zigbee2mqtt/tuya_sensor_l2" + ]; + data_format = "json"; + fielddrop = [ "newBatt" "weakBatt" ]; + }; + }; + outputs = { + influxdb_v2 = [ + { + urls = [ "http://${toString config.services.influxdb2.settings.http-bind-address}/" ]; + organization = "smarthome"; + bucket = "mqttData"; + token = "\${INFLUX_TOKEN_MQTTDATA}"; + } + ]; + }; + }; + }; + +}
diff --git a/configurations/nixos/configure/smarthome/zigbee2mqtt.nix b/configurations/nixos/configure/smarthome/zigbee2mqtt.nix @@ -0,0 +1,102 @@ +{ inputs, pkgs, lib, config, ... }: + +{ + + dns.zones."ctu.cx".subdomains."zigbee2mqtt.home".AAAA = [ config.networking.primaryIP ]; + + age.secrets = { + "zigbee2mqtt-htpasswd" = { + file = ./. + "/../../../../secrets/${config.networking.hostName}/zigbee2mqtt/htpasswd.age"; + owner = "nginx"; + }; + "zigbee2mqtt-secrets.yaml" = { + file = ./. + "/../../../../secrets/${config.networking.hostName}/zigbee2mqtt/secrets.age"; + owner = "zigbee2mqtt"; + }; + }; + + systemd.services.zigbee2mqtt = { + requires = [ "mosquitto.service" ]; + after = [ "mosquitto.service" ]; + onFailure = [ "email-notify@%i.service" ]; + serviceConfig = { + Restart = lib.mkForce "always"; + RuntimeMaxSec = "1d"; + }; + }; + + services = { + udev.extraRules = '' + SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{serial}=="00_12_4B_00_25_9B_C1_FC", SYMLINK+="zigbee0" + ATTR{idVendor}=="0451", ATTR{idProduct}=="16a8", ENV{ID_MM_DEVICE_IGNORE}="1" + SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee0" + ''; + + nginx = { + enable = true; + virtualHosts."zigbee2mqtt.${config.networking.domain}" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + kTLS = true; + locations."/" = { + proxyPass = "http://[::1]:${toString config.services.zigbee2mqtt.settings.frontend.port}"; + proxyWebsockets = true; + extraConfig = '' + auth_basic Auth; + auth_basic_user_file ${config.age.secrets.zigbee2mqtt-htpasswd.path}; + ''; + }; + }; + }; + + zigbee2mqtt = { + enable = true; + package = pkgs.zigbee2mqtt; + settings = { + homeassistant = false; + permit_join = false; + + mqtt = { + base_topic = "zigbee2mqtt"; + server = "mqtt://[::1]"; + }; + + serial = { + port = "/dev/zigbee0"; + disable_led = true; + }; + + frontend = { + port = 8422; + host = "::1"; + }; + + advanced = { + log_level = "info"; + log_output = [ "console" ]; + channel = 26; + network_key = "!${config.age.secrets."zigbee2mqtt-secrets.yaml".path} network_key"; + }; + + device_options.retain = true; + devices = { + "0x84fd27fffe6b9ddd".friendly_name = "ikea_lamp_hallway"; + "0x94deb8fffe52e639".friendly_name = "ikea_lamp_rgb"; + "0x84fd27fffe44369e".friendly_name = "ikea_lamp_sleepingroom"; + "0x84fd27fffea515fc".friendly_name = "ikea_lamp_livingroom"; + +# "0x804b50fffe42a74e".friendly_name = "ikea_remote_l_door"; +# "0x842e14fffe977bfa".friendly_name = "ikea_remote_l_bed"; + + "0xa4c138da0f6d23de".friendly_name = "tuya_led_stripe_desk"; + + "0xa4c1389d5f391891".friendly_name = "tuya_sensor_fridge"; + "0xa4c13809f76bcdc2".friendly_name = "tuya_sensor_bathroom"; + "0xa4c13882b76fa1ac".friendly_name = "tuya_sensor_sleepingroom"; + "0xa4c138ebeae2efd2".friendly_name = "tuya_sensor_l2"; + }; + + }; + }; + }; +}
diff --git a/configurations/nixos/default.nix b/configurations/nixos/default.nix @@ -9,8 +9,11 @@ in { ctucxConfig.common ]; - age.secrets.katja-systempassword.file = ../../secrets/passwords/katja.age; - age.secrets.acmeTSIGKey.file = ./. + "/../../secrets/${config.networking.hostName}/acme-tsig-key.age"; + boot.loader.efi.canTouchEfiVariables = lib.mkDefault true; + boot.loader.systemd-boot.enable = lib.mkDefault true; + + networking.hostName = lib.mkDefault args.name; + networking.domain = lib.mkDefault "ctu.cx"; deployment = { buildOnTarget = lib.mkDefault false; @@ -19,6 +22,12 @@ in { targetPort = lib.mkDefault (lib.head config.services.openssh.ports); }; + i18n.defaultLocale = "en_US.UTF-8"; + i18n.supportedLocales = ["de_DE.UTF-8/UTF-8" "en_US.UTF-8/UTF-8"]; + + age.secrets.katja-systempassword.file = ../../secrets/passwords/katja.age; + age.secrets.acmeTSIGKey.file = ./. + "/../../secrets/${config.networking.hostName}/acme-tsig-key.age"; + system = { nixos.revision = lib.mkIf (inputs.nixpkgs.sourceInfo ? rev) inputs.nixpkgs.sourceInfo.rev; nixos.versionSuffix = ".${lib.substring 0 8 (inputs.nixpkgs.sourceInfo.lastModifiedDate or inputs.nixpkgs.sourceInfo.lastModified or "19700101")}.${inputs.nixpkgs.sourceInfo.shortRev or "dirty"}"; @@ -41,12 +50,6 @@ in { }; }; - networking.hostName = lib.mkDefault args.name; - networking.domain = lib.mkDefault "ctu.cx"; - - i18n.defaultLocale = "en_US.UTF-8"; - i18n.supportedLocales = ["de_DE.UTF-8/UTF-8" "en_US.UTF-8/UTF-8"]; - systemd.services.nginx.onFailure = [ "email-notify@%i.service" ]; nix = { @@ -65,7 +68,6 @@ in { gc.dates = "18:00"; }; - services = { timesyncd.enable = true; fstrim.enable = true;
diff --git a/configurations/nixos/services/mailserver/default.nix b/configurations/nixos/services/mailserver/default.nix @@ -0,0 +1,199 @@ +{ inputs, pkgs, config, ... }: + +let + mailAutoConfig = '' + <?xml version="1.0" encoding="UTF-8"?> + <clientConfig version="1.1"> + <emailProvider id="ctu.cx"> + <domain>ctu.cx</domain> + <displayName>${config.networking.fqdn}</displayName> + <displayShortName>${config.networking.domain}</displayShortName> + <incomingServer type="imap"> + <hostname>${config.networking.fqdn}</hostname> + <port>993</port> + <socketType>SSL</socketType> + <authentication>password-cleartext</authentication> + <username>%EMAILADDRESS%</username> + </incomingServer> + <outgoingServer type="smtp"> + <hostname>${config.networking.fqdn}</hostname> + <port>465</port> + <socketType>SSL</socketType> + <authentication>password-cleartext</authentication> + <username>%EMAILADDRESS%</username> + </outgoingServer> + </emailProvider> + </clientConfig> + ''; + +in { + + age.secrets.restic-mail.file = ./. + "/../../../../secrets/${config.networking.hostName}/restic/mail.age"; + age.secrets.mail-password-katja.file = ./. + "/../../../../secrets/${config.networking.hostName}/mail/password-katja-ctu.cx.age"; + age.secrets.mail-password-gts.file = ./. + "/../../../../secrets/${config.networking.hostName}/mail/password-gts-ctu.cx.age"; + age.secrets.mail-password-gts-zug.file = ./. + "/../../../../secrets/${config.networking.hostName}/mail/password-gts-zuggeschmack.de.age"; + age.secrets.mail-password-info-zug.file = ./. + "/../../../../secrets/${config.networking.hostName}/mail/password-info-zuggeschmack.de.age"; + age.secrets.mail-password-vaultwarden.file = ./. + "/../../../../secrets/${config.networking.hostName}/mail/password-vaultwarden-ctu.cx.age"; + + dns.zones = with pkgs.dns.lib.combinators; let + TXT = [ "v=spf1 a mx ip4:${config.networking.primaryIP4} +ip6:${config.networking.primaryIP} ~all" ]; + DMARC = "v=DMARC1; p=none"; + MX = with mx; [ (mx 10 "${config.networking.fqdn}.") ]; + in { + "ctu.cx" = { + inherit MX TXT; + + SRV = [ + { proto = "tcp"; service = "imaps"; priority = 0; weight = 1; port = 993; target = "${config.networking.fqdn}."; } + { proto = "tcp"; service = "imap"; priority = 0; weight = 1; port = 143; target = "${config.networking.fqdn}."; } + { proto = "tcp"; service = "submission"; priority = 0; weight = 1; port = 587; target = "${config.networking.fqdn}."; } + ]; + + subdomains = { + autoconfig.CNAME = [ config.networking.hostName ]; + _dmarc.TXT = [ DMARC ]; + "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKryfX99NkcU5Xe4AmG+kO/sfuYSXk5RqJhzxS4uMqERE8UszgEGdteXcD8pqON2MfDmA3G6cA+Oa+N4tIWdIYNwTISVXXMGdHvjFIsVUEW0turM104tXESELaPRntkCvDBk/yOgsBDRZQHSx5MdGwpzeRC8TLdCbalh3W0jp5PQIDAQAB" ]; + }; + }; + + "katja.wtf" = { + inherit MX TXT; + + subdomains = { + _dmarc.TXT = [ DMARC ]; + "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDk63I3fkv/p1TMrcU8T1gjli0hJZp92JjK+YhOJAAdpeKMuePMI1vi/aw1Ribx9fBXGlMbNERIu4fiYWF9SsrMKqYFayD8CWbok+enZl+yQSh+UgP7jhXo0zNSTec6DK/AczZh+HbpzMSxCKQhVdjCx60F6tnh/m2OxddAw5oe6QIDAQAB" ]; + }; + }; + + "ctucx.de" = { + inherit MX TXT; + + subdomains = { + _dmarc.TXT = [ DMARC ]; + "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5fu690bKYCZLPAFfQQK+nl+aAmtetaWBKCWzGj6pt7HjpFjystgtgnQ6+DZLFXWUp8GRfMEycySB5kQULtYtSMUmx0gQBnTTLsRj+e55/CYUllLV6YXb5uca7LuVhlWPpH3sCr6TvC2VFWe4t0UC3uIXhYPrCm6p8OE7g+TdHHwIDAQAB" ]; + }; + }; + + "zuggeschmack.de" = { + inherit MX TXT; + + subdomains = { + _dmarc.TXT = [ DMARC ]; + "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf0PX32wWq068cThCnAaX1RJMBiMo6pGfT/VOp9/IzXWmNO2aSyWEFp5lVwYFJnlGX1Sg1uvThICVDiscOqG5jBUAc0gl3SPEBFJ0cqLl7CYhD3Nkvgc8+7zn4huKvFGYXRSDqQm+AL4SSEjZ8hF+N9bGxt0bYu2WlGwZX8mTptwIDAQAB" ]; + }; + }; + + "thein.ovh" = { + inherit MX TXT; + + subdomains = { + _dmarc.TXT = [ DMARC ]; + "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8oumqNkHboF/S4dnKue+hEC3V226ToMmL/fmXqbAhsW88m+jUuLgZE8Nl7kc/lzD9yY7JmCXcWFzoLJWE8xusfmT1yMOW9sQmee7g0tHsm1fVqFMUetmC4+QuqAdvjIGU5QndjdWHP/gssIoLPT7lCNUL4/lkaPmFiiDyvaMpkQIDAQAB" ]; + }; + }; + }; + + security.acme.certs."${config.networking.fqdn}".reloadServices = [ + "postfix.service" + "dovecot2.service" + ]; + + services.nginx = { + enable = true; + virtualHosts = { + "${config.networking.fqdn}" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + }; + + "autoconfig.ctu.cx" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + locations."= /mail/config-v1.1.xml".return = "200 '${mailAutoConfig}'"; + }; + }; + }; + + services.redis.servers.rspamd.bind = "::1"; + + services.dovecot2.sieve.extensions = [ + "editheader" + ]; + + mailserver = { + enable = true; + fqdn = config.networking.fqdn; + + openFirewall = true; + localDnsResolver = false; + virusScanning = false; + + redis.address = "[::1]"; + + certificateScheme = "manual"; + certificateFile = "${config.security.acme.certs.${config.networking.fqdn}.directory}/fullchain.pem"; + keyFile = "${config.security.acme.certs.${config.networking.fqdn}.directory}/key.pem"; + + enableManageSieve = true; + enableSubmission = true; + enableSubmissionSsl = true; + enableImap = true; + enableImapSsl = true; + enablePop3 = false; + enablePop3Ssl = false; + + mailDirectory = "/var/lib/mailboxes"; + sieveDirectory = "/var/lib/sieve"; + dkimKeyDirectory = "/var/lib/dkimKeys"; + + domains = [ + "ctu.cx" + "ctucx.de" + "katja.wtf" + "thein.ovh" + "zuggeschmack.de" + ]; + + loginAccounts = { + "katja@ctu.cx" = { + hashedPasswordFile = config.age.secrets.mail-password-katja.path; + sieveScript = builtins.readFile ./rules-katja.sieve; + aliases = [ + "@ctu.cx" + "@ctucx.de" + "@thein.ovh" + "@katja.wtf" + ]; + }; + + "vaultwarden@ctu.cx" = { + hashedPasswordFile = config.age.secrets.mail-password-vaultwarden.path; + }; + + "gts@ctu.cx" = { + hashedPasswordFile = config.age.secrets.mail-password-gts.path; + }; + + "gts@zuggeschmack.de" = { + hashedPasswordFile = config.age.secrets.mail-password-gts-zug.path; + }; + + "info@zuggeschmack.de" = { + hashedPasswordFile = config.age.secrets.mail-password-info-zug.path; + aliases = [ + "@zuggeschmack.de" + ]; + }; + }; + }; + + restic-backups.mail = { + passwordFile = config.age.secrets.restic-mail.path; + paths = [ + "/var/lib/mailboxes" + "/var/lib/dkimKeys" + "/var/lib/sieve" + ]; + }; + +}
diff --git a/configurations/nixos/services/mailserver/rules-katja.sieve b/configurations/nixos/services/mailserver/rules-katja.sieve @@ -0,0 +1,123 @@ +require [ + "variables", "date", "regex", + "fileinto", "mailbox", "editheader", + "imap4flags" +]; + + +if currentdate :matches "year" "*" { set "year" "${1}"; } +if currentdate :matches "month" "*" { set "month" "${1}"; } + + +if address :is "to" "le0nth3in@gmail.com" { + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + deleteheader "Subject"; + addheader :last "Subject" "[OLD GMAIL] ${subject}"; +} + +if address :contains "to" "@thein.ovh" { + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + deleteheader "Subject"; + addheader :last "Subject" "[OLD DOMAIN] ${subject}"; +} + +if address :contains "to" "leah" { + if header :matches "Subject" "*" { + set "subject" "${1}"; + } + + deleteheader "Subject"; + addheader :last "Subject" "[OLD NAME] ${subject}"; +} + +if header :contains "From" [ + "newsletter", + "ikea@hej.news.email.ikea.de", + "inside@cowboy.com", + "hello@cowboy.com", + "News@InsideApple.Apple.com", + "no-reply@newsletter.ab-in-die-box.de", + "info@join.netflix.com", + "marketing.support@porkbun.com", + "update@email.flixbus.com", + "telekom@email-telekom.de", + "rewe-bonus@mailing.rewe.de" +] { + fileinto :create "INBOX.Newsletters"; + stop; +} + +if header :contains "subject" [ "Fahrgastrechteanträge", "Fahrgastrechteantrag" ] { + fileinto :create "Archive.FGR${year}"; + stop; +} + +if header :contains "From" [ "ebon@mailing.rewe.de" ] { + fileinto :create "INBOX.REWE-Bons"; + stop; +} + +if header :contains "From" [ "@amazon.de", "@audible.de" ] { + fileinto :create "INBOX.Amazon"; + stop; +} + +if header :contains "From" [ "@apple.com", "@email.apple.com", "@id.apple.com" ] { + fileinto :create "INBOX.Apple"; + stop; +} + +if header :contains "From" [ "@bahn.de", "@mailing.bahn.de", "@mail.bahncard.bahn.de", "@deutschebahn.com" ] { + fileinto :create "INBOX.Bahn"; + stop; +} + +if header :contains "From" [ + "@bunq.com", "@hello.bunq.com", "@update.bunq.com", + "@gls.de", + "@paypal.de", "@paypal.com", "@emails.paypal.com" +] { + fileinto :create "INBOX.Banking"; + stop; +} + +if header :contains "From" [ + "@hetzner.com", + "@netcup.de", + "@ovh.de" +] { + fileinto :create "INBOX.Hosting"; + stop; +} + + +if header :contains "From" [ "@dhl.de", "@dhl.com" ] { + fileinto :create "INBOX.DHL"; + stop; +} + +if header :contains "From" [ "@duolingo.com" ] { + fileinto :create "INBOX.Duolingo"; + stop; +} + +if header :contains "From" [ "@ebay.de", "@ebay.com" ] { + fileinto :create "INBOX.eBay"; + stop; +} + +if header :contains "From" [ "@google.com", "@accounts.google.com" ] { + fileinto :create "INBOX.Google"; + stop; +} + +if header :contains "From" [ "@mein-grundeinkommen.de" ] { + fileinto :create "INBOX.MeinGrundeinkommen"; + stop; +}
diff --git a/configurations/nixos/services/mautrix-whatsapp.nix b/configurations/nixos/services/mautrix-whatsapp.nix @@ -0,0 +1,61 @@ +{ config, pkgs, ... }: + +{ + + users.users.matrix-synapse.extraGroups = [ "mautrix-whatsapp" ]; + + services = { + mautrix-whatsapp.enable = true; + mautrix-whatsapp.settings = { + homeserver.address = "https://matrix.ctu.cx"; + homeserver.domain = "ctu.cx"; + + metrics.enabled = true; + + whatsapp.os_name = "Mautrix-WhatsApp bridge (ctu.cx)"; + + appservice = { + address = "http://localhost:29318"; + hostname = "[::1]"; + port = 29318; + + id = "whatsapp"; + + database.type = "sqlite3-fk-wal"; + database.uri = "file:/var/lib/mautrix-whatsapp/mautrix-whatsapp.db?_txlock=immediate"; + }; + + bridge = { + command_prefix = "!wa"; + displayname_template = "{{if .BusinessName}}{{.BusinessName}}{{else if .PushName}}{{.PushName}}{{else}}{{.JID}}{{end}} (WA)"; + username_template = "whatsapp_{{.}}"; + + delivery_receipts = true; + message_status_events = true; + message_error_notices = true; + call_start_notices = true; + identity_change_notices = true; + user_avatar_sync = true; + personal_filtering_spaces = true; + + encryption.allow = true; + + permissions = { + "ctu.cx" = "user"; + }; + + history_sync = { + backfill = true; + message_count = 250; + request_full_sync = true; + }; + + relay = { + enabled = true; + }; + }; + + }; + }; + +}
diff --git a/configurations/nixos/websites/dendrite.ctucx.de.nix b/configurations/nixos/websites/dendrite.ctucx.de.nix @@ -0,0 +1,52 @@ +{ pkgs, lib, config, ... }: + +{ + + dns.zones."ctucx.de".subdomains.dendrite.CNAME = [ "${config.networking.fqdn}." ]; + + users.groups.dendrite = {}; + users.users.dendrite = { + isSystemUser = true; + home = "/var/lib/dendrite"; + group = "dendrite"; + }; + + services.dendrite = { + enable = true; + openRegistration = false; + settings = { + global.server_name = "dendrite.ctucx.de"; + global.private_key = "/var/lib/dendrite/private_key.pem"; + + global.well_known_server_name = "dendrite.ctucx.de:443"; + global.well_known_client_name = "https://dendrite.ctucx.de"; + + client_api.registration_disabled = true; + client_api.registration_shared_secret = "joihgpiufgpueiuessqiegp87tf-e8d7pgwiugbdpiugp87dfo87ugfodiujpfd87g97dpg97dp97"; + }; + }; + + services.nginx = { + enable = true; + virtualHosts = { + "dendrite.ctucx.de" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + kTLS = true; + locations = { + "/.well-known".proxyPass = "http://[::1]:8008"; + "/_matrix".proxyPass = "http://[::1]:8008"; + "/".root = pkgs.cinny.override { + conf = { + defaultHomeserver = 0; + homeserverList = [ "dendrite.ctucx.de" ]; + allowCustomHomesevrers = false; + }; + }; + }; + }; + + }; + }; + +}
diff --git a/configurations/nixos/websites/grafana.ctu.cx/default.nix b/configurations/nixos/websites/grafana.ctu.cx/default.nix @@ -0,0 +1,82 @@ +{ inputs, config, lib, pkgs, ... }: + +{ + + age.secrets.grafana-influx-token-mqttData = { + file = ../../../../secrets/briefkasten/influx/grafana_token_mqttData.age; + owner = "grafana"; + }; + + dns.zones."ctu.cx".subdomains.grafana.CNAME = [ "${config.networking.fqdn}." ]; + + systemd.services.grafana.onFailure = [ "email-notify@%i.service" ]; + + services = { + grafana = { + enable = true; + + settings = { + server = { + domain = "grafana.ctu.cx"; + root_url = "https://grafana.ctu.cx/"; + http_addr = "::1"; + http_port = 3001; + }; + security.allow_embedding = true; + "users".auto_assign_org_role = "Viewer"; +# "users".viewers_can_edit = true; + "users".home_page = "/d/FRDYqjEGz/smarthome-influx"; + "auth".disable_login_form = true; + "auth.basic".enabled = false; + "auth.anonymous".enabled = true; + "auth.anonymous".org_name = "Main Org."; + "auth.anonymous".org_role = "Viewer"; + }; + + provision = { + enable = true; + datasources.settings.datasources = [ + + { + name = "Prometheus"; + type = "prometheus"; + url = "https://prometheus.ctu.cx/"; + isDefault = true; + editable = false; + jsonData.timeInterval = "20s"; + } + + { + name = "InfluxDB (mqttData)"; + type = "influxdb"; + url = "https://influx.home.ctu.cx"; + orgId = 1; + database = "mqttData"; + editable = false; + jsonData.version = "Flux"; + jsonData.organization = "katja"; + jsonData.defaultBucket = "mqttData"; + secureJsonData.token = "$__file{${config.age.secrets.grafana-influx-token-mqttData.path}}"; + } + + ]; + + dashboards.settings.providers = [{ + folder = "provisioned"; + options.path = ./dashboards; + }]; + }; + }; + + nginx = { + enable = true; + virtualHosts."grafana.ctu.cx" = { + useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; + forceSSL = true; + kTLS = true; + locations."/".proxyPass = "http://[::1]:${toString config.services.grafana.settings.server.http_port}/"; + }; + }; + }; + +}
diff --git a/flake.nix b/flake.nix @@ -65,13 +65,7 @@ ]; }; - seifenkiste = import ./machines/seifenkiste; - briefkasten = import ./machines/briefkasten; - - trabbi = import ./machines/trabbi; - wanderduene = import ./machines/wanderduene; - hector = import ./machines/hector; - }; + } // loadDir ./machines; colmenaHive = inputs.colmena.lib.makeHive self.outputs.colmena; nixosConfigurations = (import (inputs.colmena + "/src/nix/hive/eval.nix") {
diff --git a/machines/briefkasten/default.nix b/machines/briefkasten/default.nix @@ -6,11 +6,15 @@ ./hardware-configuration.nix ./impermanence.nix + ctucxConfig.programs.yt-dlp + ctucxConfig.programs.ocrmypdf + + ctucxConfig.configure.router + ctucxConfig.configure.smarthome + ctucxConfig.services.prometheus-exporters ctucxConfig.services.restic-server - ctucxConfig.programs.yt-dlp - ctucxConfig.programs.ocrmypdf ctucxConfig.websites."music.home.ctu.cx" ctucxConfig.websites."audiobooks.home.ctu.cx" @@ -19,11 +23,7 @@ # syncthing (and it's backup) ./syncthing.nix - ./smarthome - ./scanner-sftp.nix - - ./router ]; age.secrets = { @@ -41,14 +41,7 @@ kernelModules = [ "intel_rapl_common" ]; # seems to make realtek ethernet faster? - kernelParams = [ - "pcie_aspm=off" - ]; - - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; - }; + kernelParams = [ "pcie_aspm=off" ]; initrd.network = { enable = true; @@ -92,6 +85,9 @@ email-notify.enable = true; }; + powerManagement.cpuFreqGovernor = "powersave"; + hardware.cpu.intel.updateMicrocode = true; + system.stateVersion = "22.11"; # Did you read the comment? home-manager.users.katja.home.stateVersion = "22.11";
diff --git a/machines/briefkasten/hardware-configuration.nix b/machines/briefkasten/hardware-configuration.nix @@ -1,17 +1,10 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "r8169" ]; - boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "r8169" ]; + boot.initrd.luks.devices."nix-store".device = "/dev/disk/by-uuid/d1e0568c-042a-4e76-8901-30bcb9fb8efb"; fileSystems."/" = { device = "tmpfs"; @@ -35,11 +28,4 @@ fsType = "vfat"; }; - boot.initrd.luks.devices."nix-store".device = "/dev/disk/by-uuid/d1e0568c-042a-4e76-8901-30bcb9fb8efb"; - - - swapDevices = [ ]; - - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; }
diff --git a/machines/briefkasten/impermanence.nix b/machines/briefkasten/impermanence.nix @@ -2,11 +2,6 @@ { - services.syncthing = { - dataDir = "/nix/persist/home/katja/syncthing"; - configDir = "/nix/persist/home/katja/.config/syncthing"; - }; - services.openssh.hostKeys = [ { bits = 4096; @@ -34,9 +29,7 @@ programs.fuse.userAllowOther = true; home-manager.users.katja = { - imports = [ - inputs.impermanence.homeManagerModules.default - ]; + imports = [ inputs.impermanence.homeManagerModules.default ]; home.persistence."/nix/persist/home/katja" = { allowOther = true;
diff --git a/machines/briefkasten/router/ppp.nix b/machines/briefkasten/router/ppp.nix @@ -1,64 +0,0 @@ -{ config, utils, pkgs, ... }: - -{ - - age.secrets.pppd-env.file = ./. + "/../../../secrets/${config.networking.hostName}/pppd-env.age"; - - services.pppd = { - enable = true; - peers.dtagdsl = { - config = '' - plugin pppoe.so dtagdsl - user "''${DTAG_PPP_USER}" - password "''${DTAG_PPP_PASS}" - hide-password - ifname ppp-dtagdsl - persist - - maxfail 0 - holdoff 5 - - noipdefault - - lcp-echo-interval 20 - lcp-echo-failure 3 - - mtu 1492 - defaultroute - replacedefaultroute - +ipv6 - ''; - }; - }; - - environment.etc."ppp/peers/dtagdsl".enable = false; - environment.etc."ip-up.d/1systemd-networkd" = { - mode = "755"; - text = '' - #!{pkgs.bash}/bin/bash - networkctl reconfigure "$PPP_IFACE"; - ''; - }; - - systemd.services."pppd-dtagdsl".serviceConfig = let - preStart = '' - mkdir -p /etc/ppp/peers - - # Created files only readable by root - umask u=rw,g=,o= - - # Copy config and substitute env-vars - rm -f /etc/ppp/peers/dtagdsl - ${pkgs.envsubst}/bin/envsubst -i "${config.environment.etc."ppp/peers/dtagdsl".source}" > /etc/ppp/peers/dtagdsl - ''; - - preStartFile = utils.systemdUtils.lib.makeJobScript { name = "pppd-dtagdsl-pre-start"; text = preStart; enableStrictShellChecks = true; }; - in { - EnvironmentFile = config.age.secrets.pppd-env.path; - ExecStartPre = [ - # "+" marks script to be executed without priviledge restrictions - "+${preStartFile}" - ]; - }; - -}
diff --git a/machines/briefkasten/router/systemd-networkd.nix b/machines/briefkasten/router/systemd-networkd.nix @@ -1,204 +0,0 @@ -{ config, ... }: - -{ - -# systemd.services."systemd-networkd".serviceConfig.Environment = "SYSTEMD_LOG_LEVEL=debug"; - - age.secrets.wireguard-privkey = { - file = ./. + "../../../../secrets/${config.networking.hostName}/wireguard-privkey.age"; - mode = "640"; - owner = "root"; - group = "systemd-network"; - }; - - systemd.network = { - enable = true; - wait-online.enable = false; - - config.networkConfig = { - IPv6Forwarding = true; - }; - - links."5-dtagdsl" = { - matchConfig.PermanentMACAddress = "d0:37:45:06:de:de"; - linkConfig.Name = "dtagdsl"; - }; - - links."5-iphone" = { - matchConfig.PermanentMACAddress = "aa:ab:b5:18:95:d9"; - linkConfig.Name = "iphone"; - }; - - netdevs."20-brlan" = { - netdevConfig = { - Kind = "bridge"; - Name = "brlan"; - }; - }; - - netdevs."10-wg-wanderduene" = { - netdevConfig = { - Kind = "wireguard"; - Name = "wg-wanderduene"; - }; - - wireguardConfig = { - PrivateKeyFile = config.age.secrets.wireguard-privkey.path; - ListenPort = 51820; - FirewallMark = 51820; - }; - - wireguardPeers = [{ - Endpoint = "wanderduene.ctu.cx:51820"; - PublicKey = "hOUeP8RFchzJXyy8DceTFKN9f1VHi9GzZQii0dX2zww="; - AllowedIPs = [ "::/0" ]; - PersistentKeepalive = 10; - }]; - }; - - networks = { - "5-dtagdsl" = { - matchConfig.Name = "dtagdsl"; - - linkConfig.RequiredForOnline = false; - networkConfig.LinkLocalAddressing = false; - }; - - "5-enp1s0" = { - matchConfig.Name = "enp1s0"; - - networkConfig.ConfigureWithoutCarrier = true; - bridge = [ "brlan" ]; - }; - - "5-iphone" = { - matchConfig.Name = "iphone"; - - networkConfig.DHCP = true; - }; - - "10-ppp-dtagdsl" = { - matchConfig.Name = "ppp-dtagdsl"; - - networkConfig = { - KeepConfiguration = true; - IPv6AcceptRA = true; - DHCP = "ipv6"; - }; - - ipv6AcceptRAConfig = { - UseDNS = false; - }; - - dhcpV6Config = { - WithoutRA = "solicit"; - PrefixDelegationHint = "::/56"; - IAID = 0; - UseDNS = false; - }; - }; - - "10-wg-wanderduene" = { - matchConfig.Name = "wg-wanderduene"; - - linkConfig.RequiredForOnline = false; - routes = [{ - Destination = "::/0"; - Table = "1234"; - }]; - }; - - "20-brlan" = { - matchConfig = { - Name = "brlan"; - Driver = "bridge"; - }; - - address = [ "10.0.0.1/8" "2a03:4000:4d:5e:acab::1/112" ]; - - routingPolicyRules = [ - { - From = "2a03:4000:4d:5e:acab::/112"; - Table = 254; - Priority = 1900; - SuppressPrefixLength = 0; - } - { - From = "2a03:4000:4d:5e:acab::/112"; - Table = 1234; - Priority = 2000; - } - ]; - - networkConfig = { - ConfigureWithoutCarrier = true; - IPv4Forwarding = true; - IPMasquerade = "ipv4"; - - DHCPPrefixDelegation = true; - IPv6PrivacyExtensions = false; - IPv6AcceptRA = false; - IPv6SendRA = true; - - DHCPServer = true; - DNS = "10.0.0.1"; - }; - - dhcpPrefixDelegationConfig = { - UplinkInterface = "ppp-dtagdsl"; - Announce = true; - SubnetId = 0; - Token = "::1"; - }; - - ipv6SendRAConfig = { - EmitDNS = true; - DNS = "_link_local"; - }; - - ipv6PREF64Prefixes = [{ - Prefix = "64:ff9b::/96"; - }]; - - dhcpServerConfig = { - PersistLeases = true; - PoolOffset = 100; - PoolSize = 100; - EmitDNS = true; - DNS = "10.0.0.1"; - IPv6OnlyPreferredSec = 300; - }; - - dhcpServerStaticLeases = [ - { - # accesspoint - MACAddress = "48:a9:8a:8e:dd:0b"; - Address = "10.0.0.2"; - } - { - # pbx - MACAddress = "34:31:c4:46:88:31"; - Address = "10.0.0.3"; - } - { - # scanner - MACAddress = "5c:f3:70:b9:35:9c"; - Address = "10.0.0.4"; - } - { - # printer - MACAddress = "70:77:81:2a:e7:96"; - Address = "10.0.0.5"; - } - { - # katja x13 - MACAddress = "04:CF:4B:76:93:55"; - Address = "10.0.0.10"; - } - ]; - }; - - }; - }; - -}
diff --git a/machines/briefkasten/smarthome/influxdb2.nix b/machines/briefkasten/smarthome/influxdb2.nix @@ -1,36 +0,0 @@ -{ config, pkgs, lib, ... }: - -{ - - dns.zones."ctu.cx".subdomains."influx.home".AAAA = [ config.networking.primaryIP ]; - - age.secrets.restic-influxdb.file = ./. + "/../../../secrets/${config.networking.hostName}/restic/influxdb.age"; - age.secrets.influx-backup-env.file = ./. + "/../../../secrets/${config.networking.hostName}/influx/backup_env.age"; - - systemd.services.restic-backup-influxdb.serviceConfig.EnvironmentFile = config.age.secrets.influx-backup-env.path; - - restic-backups.influxdb = { - user = "influxdb2"; - passwordFile = config.age.secrets.restic-influxdb.path; - influxBuckets = [ "mqttData" ]; - }; - - systemd.services.influxdb2 = { - serviceConfig.ExecStartPost = "${pkgs.bash}/bin/bash -c 'until ${pkgs.netcat}/bin/nc -z ::1 8086; do sleep 0.2; done'"; - onFailure = [ "email-notify@%i.service" ]; - }; - - services.influxdb2.enable = true; - services.influxdb2.settings.http-bind-address = "[::1]:8086"; - - services.nginx = { - enable = true; - virtualHosts."influx.home.ctu.cx" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://${toString config.services.influxdb2.settings.http-bind-address}/"; - }; - }; - -}
diff --git a/machines/briefkasten/smarthome/mosquitto.nix b/machines/briefkasten/smarthome/mosquitto.nix @@ -1,47 +0,0 @@ -{ inputs, config, pkgs, ... }: - -{ - - age.secrets = { - mosquitto-passwd-katja = { - file = ./. + "/../../../secrets/${config.networking.hostName}/mosquitto/passwd-katja.age"; - owner = "mosquitto"; - }; - }; - - services = { - mosquitto = { - enable = true; - persistence = false; - settings = { - max_keepalive = 60; - }; - listeners = [ - - { - port = 1883; - omitPasswordAuth = true; - users = {}; - settings = { - allow_anonymous = true; - }; - acl = [ "topic readwrite #" "pattern readwrite #" ]; - } - - { - address = "::1"; - port = 9005; - users = { - katja.passwordFile = config.age.secrets.mosquitto-passwd-katja.path; - }; - settings = { - protocol = "websockets"; - }; - acl = [ "topic readwrite #" "pattern readwrite #" ]; - } - - ]; - }; - }; - -}- \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/mqtt-webui/config.nix b/machines/briefkasten/smarthome/mqtt-webui/config.nix @@ -1,216 +0,0 @@ -let - - Switch = name: topic: { - title = name; - type = "switch"; - icon = "icons/power_button.png"; - topic.get = topic; - topic.set = "${topic}/set"; - transform.get = "return (message.state == 'ON') ? true : false"; - transform.set = "return JSON.stringify({state: (input) ? 'ON' : 'OFF'})"; - }; - - BrighnessSlider = name: topic: { - title = name; - type = "slider"; - icon = "icons/bulb.png"; - sliderMinValue = 0; - sliderMaxValue = 254; - sliderStepValue = 1; - topic.get = topic; - topic.set = "${topic}/set"; - transform.get = "return message.brightness"; - transform.set = "return JSON.stringify({brightness: Number(input)})"; - }; - - ColorTemperatureSlider = name: topic: { - title = name; - type = "slider"; - icon = "icons/bulb.png"; - sliderMinValue = 250; - sliderMaxValue = 454; - sliderStepValue = 1; - topic.get = topic; - topic.set = "${topic}/set"; - transform.get = "return message.color_temp"; - transform.set = "return JSON.stringify({color_temp: Number(input)})"; - }; - - DimmableLamp = name: topic: { - title = name; - items = [ - (Switch "Power" topic) - (BrighnessSlider "Brighness" topic) - ]; - }; - - WhiteSpectrumLamp = name: topic: { - title = name; - items = [ - (Switch "Power" topic) - (BrighnessSlider "Brighness" topic) - (ColorTemperatureSlider "Color Temperature" topic) - ]; - }; - - ColorSpectrumLamp = name: topic: { - title = name; - items = [ - (Switch "Power" topic) - (BrighnessSlider "Brighness" topic) - (ColorTemperatureSlider "Color Temperature" topic) - - { - title = "Color"; - type = "select"; - icon = "icons/bulb.png"; - topic.get = topic; - topic.set = "${topic}/set"; - transform.get = "return message.color.x + ','+message.color.y"; - transform.set = "return JSON.stringify({color: {x: input.split(',')[0], y: input.split(',')[1]}})"; - selectOptions = [ - { - label = "Red"; - value = "0.71,0.26"; - } - { - label = "Green"; - value = "0.19,0.78"; - } - { - label = "Blue"; - value = "0.09,0.13"; - } - ]; - } - ]; - }; - - -in { - - appName = "Smart-Home"; - extraCSS = "/extra.css"; - pages = [ - { - id = "mainpage"; - icon = "favicon-512x512.png"; - title = "Smart-Home"; - sections = [ - - (WhiteSpectrumLamp "Hallway" "zigbee2mqtt/ikea_lamp_hallway") - - (WhiteSpectrumLamp "Living room" "zigbee2mqtt/ikea_lamp_livingroom") - - (WhiteSpectrumLamp "Sleeping room" "zigbee2mqtt/ikea_lamp_sleepingroom") - - (DimmableLamp "Desk" "zigbee2mqtt/tuya_led_stripe_desk") - - (ColorSpectrumLamp "RGB Lamp" "zigbee2mqtt/ikea_lamp_rgb") - - { - title = "Temperature-Sensors"; - items = [ - { - title = "Fridge"; - type = "text"; - topic = "zigbee2mqtt/tuya_sensor_fridge"; - icon = "icons/temperature.png"; - transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; - } - { - title = "Bathroom"; - type = "text"; - topic = "zigbee2mqtt/tuya_sensor_bathroom"; - icon = "icons/temperature.png"; - transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; - } - - { - title = "Door"; - type = "text"; - topic = "zigbee2mqtt/tuya_sensor_l"; - icon = "icons/temperature.png"; - transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; - } - { - title = "Bed"; - type = "text"; - topic = "zigbee2mqtt/tuya_sensor_l2"; - icon = "icons/temperature.png"; - transform = "return Math.round((message.temperature + Number.EPSILON) * 100) / 100 + ' °C - ' + message.humidity + ' %'"; - } - - ]; - } - - { - items = [ - { - title = "Departures"; - type = "text"; - icon = "icons/electric_range.png"; - link = "#departures"; - } - { - title = "Grafana-Dashboard"; - type = "text"; - icon = "icons/sun.png"; - link = "https://grafana.ctu.cx/d/FRDYqjEGz/smarthome-influx?orgId=1&refresh=5s"; - } - ]; - } - - ]; - } - - { - id = "departures"; - title = "Departures"; - sections = [ - { - items = [ - { - type = "html"; - topic = "departures2mqtt"; - html = "<div class=\"loader\"></div>"; - transform = '' - clearInterval(globalThis.departuresUpdater) - globalThis.departuresUpdater = setInterval(() => { - let element = document.querySelector('[data-last-updated]'); - element.textContent = 'Last Update: ' + (Math.floor(Date.now() / 1000) - element.dataset.lastUpdated) + ' seconds ago'; - }, 10000) - - let output = ""; - - Object.entries(message.departures).forEach((data) => { - output += '<div class="departures"><div class="table-column table-title">' + data[0] + '</div><div class="table">'; - - output += '<div class="table-row line-column"><div class="table-column table-heading">Linie</div>'; - data[1].forEach((departure) => output += '<div class="table-column">' + departure.line + '</div>'); - output += '</div>'; - - output += '<div class="table-row direction-column"><div class="table-column table-heading">Richtung</div>'; - data[1].forEach((departure) => output += '<div class="table-column">' + departure.direction + '</div>'); - output += '</div>'; - - output += '<div class="table-row dep-column"><div class="table-column table-heading">Abfahrt</div>'; - data[1].forEach((departure) => output += '<div class="table-column">' + (Number(departure.departure_in) ? departure.departure_in + " min" : "sofort") + '</div>'); - output += '</div>'; - - output += '</div></div>'; - }); - - output += '<div class="lastUpdated" data-last-updated="' + message.lastUpdated + '">Last Update: ' + (Math.floor(Date.now() / 1000) - message.lastUpdated) + ' seconds ago</div>'; - - return output; - ''; - } - ]; - } - ]; - } - - ]; - -}- \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/mqtt-webui/default.nix b/machines/briefkasten/smarthome/mqtt-webui/default.nix @@ -1,40 +0,0 @@ -{ inputs, lib, pkgs, config, ... }: - -let - - configFile = pkgs.writeTextDir "config.json" (builtins.toJSON (import ./config.nix)); - -in { - - dns.zones."ctu.cx".subdomains."smart.home".AAAA = [ config.networking.primaryIP ]; - - services = { - nginx = { - enable = true; - virtualHosts."smart.home.ctu.cx" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - kTLS = true; - - locations = { - "/" = { - root = "${pkgs.buildEnv { - name = "mqtt-webui-env"; - paths = [ - pkgs.mqtt-webui - configFile - ./extra-css - ]; - }}/"; - }; - "/mqtt" = { - proxyPass = "http://[::1]:9005"; - proxyWebsockets = true; - }; - }; - }; - }; - - }; - -}- \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/mqtt-webui/extra-css/manifest.json b/machines/briefkasten/smarthome/mqtt-webui/extra-css/manifest.json @@ -1,13 +0,0 @@ -{ - "name": "Smart-Home", - "short_name": "Smart-Home", - "start_url": ".", - "display": "standalone", - "icons": [ - { - "src": "favicon-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ] -}- \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/telegraf.nix b/machines/briefkasten/smarthome/telegraf.nix @@ -1,40 +0,0 @@ -{ inputs, config, ... }: - -{ - - age.secrets.telegraf-env = { - file = ./. + "/../../../secrets/${config.networking.hostName}/telegraf/secrets.env.age"; - owner = "telegraf"; - }; - - services.telegraf = { - enable = true; - environmentFiles = [ config.age.secrets.telegraf-env.path ]; - extraConfig = { - inputs = { - mqtt_consumer = { - servers = [ "tcp://[::1]:1883" ]; - topics = [ - "zigbee2mqtt/tuya_sensor_fridge" - "zigbee2mqtt/tuya_sensor_bathroom" - "zigbee2mqtt/tuya_sensor_sleepingroom" - "zigbee2mqtt/tuya_sensor_l2" - ]; - data_format = "json"; - fielddrop = [ "newBatt" "weakBatt" ]; - }; - }; - outputs = { - influxdb_v2 = [ - { - urls = [ "http://${toString config.services.influxdb2.settings.http-bind-address}/" ]; - organization = "smarthome"; - bucket = "mqttData"; - token = "\${INFLUX_TOKEN_MQTTDATA}"; - } - ]; - }; - }; - }; - -}- \ No newline at end of file
diff --git a/machines/briefkasten/smarthome/zigbee2mqtt.nix b/machines/briefkasten/smarthome/zigbee2mqtt.nix @@ -1,102 +0,0 @@ -{ inputs, pkgs, lib, config, ... }: - -{ - - dns.zones."ctu.cx".subdomains."zigbee2mqtt.home".AAAA = [ config.networking.primaryIP ]; - - age.secrets = { - "zigbee2mqtt-htpasswd" = { - file = ./. + "/../../../secrets/${config.networking.hostName}/zigbee2mqtt/htpasswd.age"; - owner = "nginx"; - }; - "zigbee2mqtt-secrets.yaml" = { - file = ./. + "/../../../secrets/${config.networking.hostName}/zigbee2mqtt/secrets.age"; - owner = "zigbee2mqtt"; - }; - }; - - systemd.services.zigbee2mqtt = { - requires = [ "mosquitto.service" ]; - after = [ "mosquitto.service" ]; - onFailure = [ "email-notify@%i.service" ]; - serviceConfig = { - Restart = lib.mkForce "always"; - RuntimeMaxSec = "1d"; - }; - }; - - services = { - udev.extraRules = '' - SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{serial}=="00_12_4B_00_25_9B_C1_FC", SYMLINK+="zigbee0" - ATTR{idVendor}=="0451", ATTR{idProduct}=="16a8", ENV{ID_MM_DEVICE_IGNORE}="1" - SUBSYSTEM=="tty", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="16a8", SYMLINK+="zigbee0" - ''; - - nginx = { - enable = true; - virtualHosts."zigbee2mqtt.${config.networking.domain}" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - kTLS = true; - locations."/" = { - proxyPass = "http://[::1]:${toString config.services.zigbee2mqtt.settings.frontend.port}"; - proxyWebsockets = true; - extraConfig = '' - auth_basic Auth; - auth_basic_user_file ${config.age.secrets.zigbee2mqtt-htpasswd.path}; - ''; - }; - }; - }; - - zigbee2mqtt = { - enable = true; - package = pkgs.zigbee2mqtt; - settings = { - homeassistant = false; - permit_join = false; - - mqtt = { - base_topic = "zigbee2mqtt"; - server = "mqtt://[::1]"; - }; - - serial = { - port = "/dev/zigbee0"; - disable_led = true; - }; - - frontend = { - port = 8422; - host = "::1"; - }; - - advanced = { - log_level = "info"; - log_output = [ "console" ]; - channel = 26; - network_key = "!${config.age.secrets."zigbee2mqtt-secrets.yaml".path} network_key"; - }; - - device_options.retain = true; - devices = { - "0x84fd27fffe6b9ddd".friendly_name = "ikea_lamp_hallway"; - "0x94deb8fffe52e639".friendly_name = "ikea_lamp_rgb"; - "0x84fd27fffe44369e".friendly_name = "ikea_lamp_sleepingroom"; - "0x84fd27fffea515fc".friendly_name = "ikea_lamp_livingroom"; - -# "0x804b50fffe42a74e".friendly_name = "ikea_remote_l_door"; -# "0x842e14fffe977bfa".friendly_name = "ikea_remote_l_bed"; - - "0xa4c138da0f6d23de".friendly_name = "tuya_led_stripe_desk"; - - "0xa4c1389d5f391891".friendly_name = "tuya_sensor_fridge"; - "0xa4c13809f76bcdc2".friendly_name = "tuya_sensor_bathroom"; - "0xa4c13882b76fa1ac".friendly_name = "tuya_sensor_sleepingroom"; - "0xa4c138ebeae2efd2".friendly_name = "tuya_sensor_l2"; - }; - - }; - }; - }; -}
diff --git a/machines/briefkasten/syncthing.nix b/machines/briefkasten/syncthing.nix @@ -15,6 +15,11 @@ in { imports = [ ctucxConfig.services.syncthing ]; + services.syncthing = { + dataDir = "/nix/persist/home/katja/syncthing"; + configDir = "/nix/persist/home/katja/.config/syncthing"; + }; + age.secrets = lib.mapAttrs' ( name: path: lib.nameValuePair "restic-syncthing-${name}" { file = ./. + "/../../secrets/${config.networking.hostName}/restic/syncthing-${name}.age";
diff --git a/machines/hector/default.nix b/machines/hector/default.nix @@ -7,7 +7,9 @@ ctucxConfig.services.prometheus-exporters ctucxConfig.services.dns-server + ctucxConfig.services.syncthing + # website / webservices ctucxConfig.websites."ctu.cx" ctucxConfig.websites."things.ctu.cx" ctucxConfig.websites."bikemap.ctu.cx" @@ -16,7 +18,7 @@ # monitoring ctucxConfig.websites."prometheus.ctu.cx" - ./grafana + ctucxConfig.websites."grafana.ctu.cx" # cal-/card-dav server (radicale) ctucxConfig.websites."dav.ctu.cx" @@ -29,11 +31,13 @@ # fediverse server (gotosocial) ctucxConfig.websites."fedi.ctu.cx" - ./matrix - ./mail - ./syncthing.nix + # mailserver + ctucxConfig.services.mailserver + # matrix server + ctucxConfig.services.matrix-synapse + ctucxConfig.services.mautrix-whatsapp ]; dns.zones."ctu.cx".subdomains."${config.networking.hostName}" = (pkgs.dns.lib.combinators.host config.networking.primaryIP4 config.networking.primaryIP); @@ -41,33 +45,26 @@ age.secrets.restic-server-briefkasten.file = ../../secrets/restic-server/briefkasten.age; age.secrets.restic-server-wanderduene.file = ../../secrets/restic-server/wanderduene.age; - boot = { - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + port = 22; + hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; + authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); }; - initrd.network = { - enable = true; - ssh = { - enable = true; - port = 22; - hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; - authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); - }; - - postCommands = '' - ip link set dev ens3 up + postCommands = '' + ip link set dev ens3 up - ip addr add ${config.networking.primaryIP}/128 dev ens3 - ip route add default via fe80::1 dev ens3 onlink + ip addr add ${config.networking.primaryIP}/128 dev ens3 + ip route add default via fe80::1 dev ens3 onlink - ip addr add ${config.networking.primaryIP4}/22 dev ens3 - ip route add default via 194.59.204.1 dev ens3 onlink + ip addr add ${config.networking.primaryIP4}/22 dev ens3 + ip route add default via 194.59.204.1 dev ens3 onlink - echo 'cryptsetup-askpass' >> /root/.profile - ''; - }; + echo 'cryptsetup-askpass' >> /root/.profile + ''; }; networking = { @@ -109,6 +106,7 @@ }; }; + services.syncthing.dataDir = "/home/katja/syncthing"; services.email-notify.enable = true; system.stateVersion = "24.11";
diff --git a/machines/hector/grafana/default.nix b/machines/hector/grafana/default.nix @@ -1,82 +0,0 @@ -{ inputs, config, lib, pkgs, ... }: - -{ - - age.secrets.grafana-influx-token-mqttData = { - file = ../../../secrets/briefkasten/influx/grafana_token_mqttData.age; - owner = "grafana"; - }; - - dns.zones."ctu.cx".subdomains.grafana.CNAME = [ "${config.networking.fqdn}." ]; - - systemd.services.grafana.onFailure = [ "email-notify@%i.service" ]; - - services = { - grafana = { - enable = true; - - settings = { - server = { - domain = "grafana.ctu.cx"; - root_url = "https://grafana.ctu.cx/"; - http_addr = "::1"; - http_port = 3001; - }; - security.allow_embedding = true; - "users".auto_assign_org_role = "Viewer"; -# "users".viewers_can_edit = true; - "users".home_page = "/d/FRDYqjEGz/smarthome-influx"; - "auth".disable_login_form = true; - "auth.basic".enabled = false; - "auth.anonymous".enabled = true; - "auth.anonymous".org_name = "Main Org."; - "auth.anonymous".org_role = "Viewer"; - }; - - provision = { - enable = true; - datasources.settings.datasources = [ - - { - name = "Prometheus"; - type = "prometheus"; - url = "https://prometheus.ctu.cx/"; - isDefault = true; - editable = false; - jsonData.timeInterval = "20s"; - } - - { - name = "InfluxDB (mqttData)"; - type = "influxdb"; - url = "https://influx.home.ctu.cx"; - orgId = 1; - database = "mqttData"; - editable = false; - jsonData.version = "Flux"; - jsonData.organization = "katja"; - jsonData.defaultBucket = "mqttData"; - secureJsonData.token = "$__file{${config.age.secrets.grafana-influx-token-mqttData.path}}"; - } - - ]; - - dashboards.settings.providers = [{ - folder = "provisioned"; - options.path = ./dashboards; - }]; - }; - }; - - nginx = { - enable = true; - virtualHosts."grafana.ctu.cx" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - kTLS = true; - locations."/".proxyPass = "http://[::1]:${toString config.services.grafana.settings.server.http_port}/"; - }; - }; - }; - -}
diff --git a/machines/hector/hardware-configuration.nix b/machines/hector/hardware-configuration.nix @@ -1,39 +1,23 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; - boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/1986cef8-3b9a-4473-a44f-08f48abd7e6e"; - fsType = "ext4"; - }; + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; boot.initrd.luks.devices."root".device = "/dev/disk/by-uuid/b99dc901-2104-4193-909c-034d5d46d4bf"; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/25F5-CEC1"; - fsType = "vfat"; - options = [ "fmask=0022" "dmask=0022" ]; - }; - - swapDevices = [ ]; + fileSystems."/" = { + device = "/dev/disk/by-uuid/1986cef8-3b9a-4473-a44f-08f48abd7e6e"; + fsType = "ext4"; + }; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.ens3.useDHCP = lib.mkDefault true; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/25F5-CEC1"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; }
diff --git a/machines/hector/mail/default.nix b/machines/hector/mail/default.nix @@ -1,199 +0,0 @@ -{ inputs, pkgs, config, ... }: - -let - mailAutoConfig = '' - <?xml version="1.0" encoding="UTF-8"?> - <clientConfig version="1.1"> - <emailProvider id="ctu.cx"> - <domain>ctu.cx</domain> - <displayName>${config.networking.fqdn}</displayName> - <displayShortName>${config.networking.domain}</displayShortName> - <incomingServer type="imap"> - <hostname>${config.networking.fqdn}</hostname> - <port>993</port> - <socketType>SSL</socketType> - <authentication>password-cleartext</authentication> - <username>%EMAILADDRESS%</username> - </incomingServer> - <outgoingServer type="smtp"> - <hostname>${config.networking.fqdn}</hostname> - <port>465</port> - <socketType>SSL</socketType> - <authentication>password-cleartext</authentication> - <username>%EMAILADDRESS%</username> - </outgoingServer> - </emailProvider> - </clientConfig> - ''; - -in { - - age.secrets.restic-mail.file = ./. + "/../../../secrets/${config.networking.hostName}/restic/mail.age"; - age.secrets.mail-password-katja.file = ./. + "/../../../secrets/${config.networking.hostName}/mail/password-katja-ctu.cx.age"; - age.secrets.mail-password-gts.file = ./. + "/../../../secrets/${config.networking.hostName}/mail/password-gts-ctu.cx.age"; - age.secrets.mail-password-gts-zug.file = ./. + "/../../../secrets/${config.networking.hostName}/mail/password-gts-zuggeschmack.de.age"; - age.secrets.mail-password-info-zug.file = ./. + "/../../../secrets/${config.networking.hostName}/mail/password-info-zuggeschmack.de.age"; - age.secrets.mail-password-vaultwarden.file = ./. + "/../../../secrets/${config.networking.hostName}/mail/password-vaultwarden-ctu.cx.age"; - - dns.zones = with pkgs.dns.lib.combinators; let - TXT = [ "v=spf1 a mx ip4:${config.networking.primaryIP4} +ip6:${config.networking.primaryIP} ~all" ]; - DMARC = "v=DMARC1; p=none"; - MX = with mx; [ (mx 10 "${config.networking.fqdn}.") ]; - in { - "ctu.cx" = { - inherit MX TXT; - - SRV = [ - { proto = "tcp"; service = "imaps"; priority = 0; weight = 1; port = 993; target = "${config.networking.fqdn}."; } - { proto = "tcp"; service = "imap"; priority = 0; weight = 1; port = 143; target = "${config.networking.fqdn}."; } - { proto = "tcp"; service = "submission"; priority = 0; weight = 1; port = 587; target = "${config.networking.fqdn}."; } - ]; - - subdomains = { - autoconfig.CNAME = [ config.networking.hostName ]; - _dmarc.TXT = [ DMARC ]; - "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKryfX99NkcU5Xe4AmG+kO/sfuYSXk5RqJhzxS4uMqERE8UszgEGdteXcD8pqON2MfDmA3G6cA+Oa+N4tIWdIYNwTISVXXMGdHvjFIsVUEW0turM104tXESELaPRntkCvDBk/yOgsBDRZQHSx5MdGwpzeRC8TLdCbalh3W0jp5PQIDAQAB" ]; - }; - }; - - "katja.wtf" = { - inherit MX TXT; - - subdomains = { - _dmarc.TXT = [ DMARC ]; - "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDk63I3fkv/p1TMrcU8T1gjli0hJZp92JjK+YhOJAAdpeKMuePMI1vi/aw1Ribx9fBXGlMbNERIu4fiYWF9SsrMKqYFayD8CWbok+enZl+yQSh+UgP7jhXo0zNSTec6DK/AczZh+HbpzMSxCKQhVdjCx60F6tnh/m2OxddAw5oe6QIDAQAB" ]; - }; - }; - - "ctucx.de" = { - inherit MX TXT; - - subdomains = { - _dmarc.TXT = [ DMARC ]; - "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5fu690bKYCZLPAFfQQK+nl+aAmtetaWBKCWzGj6pt7HjpFjystgtgnQ6+DZLFXWUp8GRfMEycySB5kQULtYtSMUmx0gQBnTTLsRj+e55/CYUllLV6YXb5uca7LuVhlWPpH3sCr6TvC2VFWe4t0UC3uIXhYPrCm6p8OE7g+TdHHwIDAQAB" ]; - }; - }; - - "zuggeschmack.de" = { - inherit MX TXT; - - subdomains = { - _dmarc.TXT = [ DMARC ]; - "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf0PX32wWq068cThCnAaX1RJMBiMo6pGfT/VOp9/IzXWmNO2aSyWEFp5lVwYFJnlGX1Sg1uvThICVDiscOqG5jBUAc0gl3SPEBFJ0cqLl7CYhD3Nkvgc8+7zn4huKvFGYXRSDqQm+AL4SSEjZ8hF+N9bGxt0bYu2WlGwZX8mTptwIDAQAB" ]; - }; - }; - - "thein.ovh" = { - inherit MX TXT; - - subdomains = { - _dmarc.TXT = [ DMARC ]; - "mail._domainkey".TXT = [ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8oumqNkHboF/S4dnKue+hEC3V226ToMmL/fmXqbAhsW88m+jUuLgZE8Nl7kc/lzD9yY7JmCXcWFzoLJWE8xusfmT1yMOW9sQmee7g0tHsm1fVqFMUetmC4+QuqAdvjIGU5QndjdWHP/gssIoLPT7lCNUL4/lkaPmFiiDyvaMpkQIDAQAB" ]; - }; - }; - }; - - security.acme.certs."${config.networking.fqdn}".reloadServices = [ - "postfix.service" - "dovecot2.service" - ]; - - services.nginx = { - enable = true; - virtualHosts = { - "${config.networking.fqdn}" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - }; - - "autoconfig.ctu.cx" = { - useACMEHost = "${config.networking.hostName}.${config.networking.domain}"; - forceSSL = true; - locations."= /mail/config-v1.1.xml".return = "200 '${mailAutoConfig}'"; - }; - }; - }; - - services.redis.servers.rspamd.bind = "::1"; - - services.dovecot2.sieve.extensions = [ - "editheader" - ]; - - mailserver = { - enable = true; - fqdn = config.networking.fqdn; - - openFirewall = true; - localDnsResolver = false; - virusScanning = false; - - redis.address = "[::1]"; - - certificateScheme = "manual"; - certificateFile = "${config.security.acme.certs.${config.networking.fqdn}.directory}/fullchain.pem"; - keyFile = "${config.security.acme.certs.${config.networking.fqdn}.directory}/key.pem"; - - enableManageSieve = true; - enableSubmission = true; - enableSubmissionSsl = true; - enableImap = true; - enableImapSsl = true; - enablePop3 = false; - enablePop3Ssl = false; - - mailDirectory = "/var/lib/mailboxes"; - sieveDirectory = "/var/lib/sieve"; - dkimKeyDirectory = "/var/lib/dkimKeys"; - - domains = [ - "ctu.cx" - "ctucx.de" - "katja.wtf" - "thein.ovh" - "zuggeschmack.de" - ]; - - loginAccounts = { - "katja@ctu.cx" = { - hashedPasswordFile = config.age.secrets.mail-password-katja.path; - sieveScript = builtins.readFile ./rules-katja.sieve; - aliases = [ - "@ctu.cx" - "@ctucx.de" - "@thein.ovh" - "@katja.wtf" - ]; - }; - - "vaultwarden@ctu.cx" = { - hashedPasswordFile = config.age.secrets.mail-password-vaultwarden.path; - }; - - "gts@ctu.cx" = { - hashedPasswordFile = config.age.secrets.mail-password-gts.path; - }; - - "gts@zuggeschmack.de" = { - hashedPasswordFile = config.age.secrets.mail-password-gts-zug.path; - }; - - "info@zuggeschmack.de" = { - hashedPasswordFile = config.age.secrets.mail-password-info-zug.path; - aliases = [ - "@zuggeschmack.de" - ]; - }; - }; - }; - - restic-backups.mail = { - passwordFile = config.age.secrets.restic-mail.path; - paths = [ - "/var/lib/mailboxes" - "/var/lib/dkimKeys" - "/var/lib/sieve" - ]; - }; - -}
diff --git a/machines/hector/mail/rules-katja.sieve b/machines/hector/mail/rules-katja.sieve @@ -1,123 +0,0 @@ -require [ - "variables", "date", "regex", - "fileinto", "mailbox", "editheader", - "imap4flags" -]; - - -if currentdate :matches "year" "*" { set "year" "${1}"; } -if currentdate :matches "month" "*" { set "month" "${1}"; } - - -if address :is "to" "le0nth3in@gmail.com" { - if header :matches "Subject" "*" { - set "subject" "${1}"; - } - - deleteheader "Subject"; - addheader :last "Subject" "[OLD GMAIL] ${subject}"; -} - -if address :contains "to" "@thein.ovh" { - if header :matches "Subject" "*" { - set "subject" "${1}"; - } - - deleteheader "Subject"; - addheader :last "Subject" "[OLD DOMAIN] ${subject}"; -} - -if address :contains "to" "leah" { - if header :matches "Subject" "*" { - set "subject" "${1}"; - } - - deleteheader "Subject"; - addheader :last "Subject" "[OLD NAME] ${subject}"; -} - -if header :contains "From" [ - "newsletter", - "ikea@hej.news.email.ikea.de", - "inside@cowboy.com", - "hello@cowboy.com", - "News@InsideApple.Apple.com", - "no-reply@newsletter.ab-in-die-box.de", - "info@join.netflix.com", - "marketing.support@porkbun.com", - "update@email.flixbus.com", - "telekom@email-telekom.de", - "rewe-bonus@mailing.rewe.de" -] { - fileinto :create "INBOX.Newsletters"; - stop; -} - -if header :contains "subject" [ "Fahrgastrechteanträge", "Fahrgastrechteantrag" ] { - fileinto :create "Archive.FGR${year}"; - stop; -} - -if header :contains "From" [ "ebon@mailing.rewe.de" ] { - fileinto :create "INBOX.REWE-Bons"; - stop; -} - -if header :contains "From" [ "@amazon.de", "@audible.de" ] { - fileinto :create "INBOX.Amazon"; - stop; -} - -if header :contains "From" [ "@apple.com", "@email.apple.com", "@id.apple.com" ] { - fileinto :create "INBOX.Apple"; - stop; -} - -if header :contains "From" [ "@bahn.de", "@mailing.bahn.de", "@mail.bahncard.bahn.de", "@deutschebahn.com" ] { - fileinto :create "INBOX.Bahn"; - stop; -} - -if header :contains "From" [ - "@bunq.com", "@hello.bunq.com", "@update.bunq.com", - "@gls.de", - "@paypal.de", "@paypal.com", "@emails.paypal.com" -] { - fileinto :create "INBOX.Banking"; - stop; -} - -if header :contains "From" [ - "@hetzner.com", - "@netcup.de", - "@ovh.de" -] { - fileinto :create "INBOX.Hosting"; - stop; -} - - -if header :contains "From" [ "@dhl.de", "@dhl.com" ] { - fileinto :create "INBOX.DHL"; - stop; -} - -if header :contains "From" [ "@duolingo.com" ] { - fileinto :create "INBOX.Duolingo"; - stop; -} - -if header :contains "From" [ "@ebay.de", "@ebay.com" ] { - fileinto :create "INBOX.eBay"; - stop; -} - -if header :contains "From" [ "@google.com", "@accounts.google.com" ] { - fileinto :create "INBOX.Google"; - stop; -} - -if header :contains "From" [ "@mein-grundeinkommen.de" ] { - fileinto :create "INBOX.MeinGrundeinkommen"; - stop; -}
diff --git a/machines/hector/matrix/default.nix b/machines/hector/matrix/default.nix @@ -1,10 +0,0 @@ -{ ... }: - -{ - - imports = [ - ./synapse.nix - ./mautrix-whatsapp.nix - ]; - -}- \ No newline at end of file
diff --git a/machines/hector/matrix/mautrix-whatsapp.nix b/machines/hector/matrix/mautrix-whatsapp.nix @@ -1,63 +0,0 @@ -{ config, pkgs, ... }: - -{ - - users.users.matrix-synapse.extraGroups = [ - "mautrix-whatsapp" - ]; - - services.mautrix-whatsapp = { - enable = true; - settings = { - homeserver.address = "https://matrix.ctu.cx"; - homeserver.domain = "ctu.cx"; - - metrics.enabled = true; - - whatsapp.os_name = "Mautrix-WhatsApp bridge (ctu.cx)"; - - appservice = { - address = "http://localhost:29318"; - hostname = "[::1]"; - port = 29318; - - id = "whatsapp"; - - database.type = "sqlite3-fk-wal"; - database.uri = "file:/var/lib/mautrix-whatsapp/mautrix-whatsapp.db?_txlock=immediate"; - }; - - bridge = { - command_prefix = "!wa"; - displayname_template = "{{if .BusinessName}}{{.BusinessName}}{{else if .PushName}}{{.PushName}}{{else}}{{.JID}}{{end}} (WA)"; - username_template = "whatsapp_{{.}}"; - - delivery_receipts = true; - message_status_events = true; - message_error_notices = true; - call_start_notices = true; - identity_change_notices = true; - user_avatar_sync = true; - personal_filtering_spaces = true; - - encryption.allow = true; - - permissions = { - "ctu.cx" = "user"; - }; - - history_sync = { - backfill = true; - message_count = 250; - request_full_sync = true; - }; - - relay = { - enabled = true; - }; - }; - - }; - }; - -}- \ No newline at end of file
diff --git a/machines/hector/syncthing.nix b/machines/hector/syncthing.nix @@ -1,9 +0,0 @@ -{ ctucxConfig, ... }: - -{ - - imports = [ ctucxConfig.services.syncthing ]; - - services.syncthing.dataDir = "/home/katja/syncthing"; - -}- \ No newline at end of file
diff --git a/machines/seifenkiste/default.nix b/machines/seifenkiste/default.nix @@ -15,7 +15,6 @@ boot = { loader.systemd-boot.enable = lib.mkForce false; - loader.efi.canTouchEfiVariables = true; lanzaboote = { enable = true; @@ -44,6 +43,8 @@ { id = "2c7c:030a"; path = "${pkgs.modemmanager}/share/ModemManager/fcc-unlock.available.d/2c7c"; } ]; + hardware.cpu.intel.updateMicrocode = true; + system.stateVersion = "24.11"; home-manager.users.katja.home.stateVersion = "24.11"; }
diff --git a/machines/seifenkiste/hardware-configuration.nix b/machines/seifenkiste/hardware-configuration.nix @@ -1,41 +1,21 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" ]; - boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/f81ba7a3-4b34-4c58-9588-78f8920b2f00"; - fsType = "ext4"; - }; + boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" ]; boot.initrd.luks.devices."root".device = "/dev/disk/by-uuid/b3184874-df78-4d02-9412-b060eb37e038"; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/9315-B4DE"; - fsType = "vfat"; - options = [ "fmask=0022" "dmask=0022" ]; - }; - - swapDevices = [ ]; + fileSystems."/" = { + device = "/dev/disk/by-uuid/f81ba7a3-4b34-4c58-9588-78f8920b2f00"; + fsType = "ext4"; + }; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; - # networking.interfaces.wwp0s20f0u2.useDHCP = lib.mkDefault true; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/9315-B4DE"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; }
diff --git a/machines/trabbi/default.nix b/machines/trabbi/default.nix @@ -16,31 +16,24 @@ age.secrets.restic-server-briefkasten.file = ../../secrets/restic-server/briefkasten.age; age.secrets.restic-server-wanderduene.file = ../../secrets/restic-server/wanderduene.age; - boot = { - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + port = 22; + hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; + authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); }; - initrd.network = { - enable = true; - ssh = { - enable = true; - port = 22; - hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; - authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); - }; - - postCommands = '' - ip link set dev ens3 up - ip addr add ${config.networking.primaryIP}/128 dev ens3 - ip route add default via fe80::1 dev ens3 onlink - - ip addr add ${config.networking.primaryIP4}/22 dev ens3 - ip route add default via ${config.networking.defaultGateway.address} dev ens3 onlink - echo 'cryptsetup-askpass' >> /root/.profile - ''; - }; + postCommands = '' + ip link set dev ens3 up + ip addr add ${config.networking.primaryIP}/128 dev ens3 + ip route add default via fe80::1 dev ens3 onlink + + ip addr add ${config.networking.primaryIP4}/22 dev ens3 + ip route add default via ${config.networking.defaultGateway.address} dev ens3 onlink + echo 'cryptsetup-askpass' >> /root/.profile + ''; }; networking = {
diff --git a/machines/trabbi/hardware-configuration.nix b/machines/trabbi/hardware-configuration.nix @@ -1,38 +1,22 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; - boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/83c8b9f3-d5e2-46ac-a4d8-5dd02a1fd757"; - fsType = "ext4"; - }; + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; boot.initrd.luks.devices."root".device = "/dev/disk/by-uuid/492ea477-0dc2-4c4d-a1e1-5cc1073126fa"; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/4751-075E"; - fsType = "vfat"; - }; - - swapDevices = [ ]; + fileSystems."/" = { + device = "/dev/disk/by-uuid/83c8b9f3-d5e2-46ac-a4d8-5dd02a1fd757"; + fsType = "ext4"; + }; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.ens3.useDHCP = lib.mkDefault true; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/4751-075E"; + fsType = "vfat"; + }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; }
diff --git a/machines/wanderduene/default.nix b/machines/wanderduene/default.nix @@ -12,12 +12,10 @@ ctucxConfig.services.dns-server ctucxConfig.websites."ip.ctu.cx" + ctucxConfig.websites."dendrite.ctucx.de" ./rclone-restic-server.nix - ./syncthing.nix - - ./dendrite.nix ]; documentation.nixos.enable = false; @@ -30,34 +28,27 @@ group = "systemd-network"; }; - boot = { - # Use the systemd-boot EFI boot loader. - loader.systemd-boot.enable = true; - loader.efi.canTouchEfiVariables = true; - - kernel.sysctl."net.ipv6.conf.all.proxy_ndp" = true; - - initrd.network = { - enable = true; - ssh = { - enable = true; - port = 22; - hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; - authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); - }; + boot.kernel.sysctl."net.ipv6.conf.all.proxy_ndp" = true; + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + port = 22; + hostKeys = [ /etc/ssh/ssh_host_rsa_key ]; + authorizedKeys = with lib; concatLists (mapAttrsToList (name: user: if elem "wheel" user.extraGroups then user.openssh.authorizedKeys.keys else []) config.users.users); + }; - postCommands = '' - ip link set dev ens3 up + postCommands = '' + ip link set dev ens3 up - ip addr add ${config.networking.primaryIP}/128 dev ens3 - ip route add default via fe80::1 dev ens3 onlink + ip addr add ${config.networking.primaryIP}/128 dev ens3 + ip route add default via fe80::1 dev ens3 onlink - ip addr add ${config.networking.primaryIP4}/22 dev ens3 - ip route add default via 194.36.144.1 dev ens3 onlink + ip addr add ${config.networking.primaryIP4}/22 dev ens3 + ip route add default via 194.36.144.1 dev ens3 onlink - echo 'cryptsetup-askpass' >> /root/.profile - ''; - }; + echo 'cryptsetup-askpass' >> /root/.profile + ''; }; networking = {
diff --git a/machines/wanderduene/dendrite.nix b/machines/wanderduene/dendrite.nix @@ -1,81 +0,0 @@ -{ pkgs, lib, config, ... }: - -{ - - dns.zones."ctu.cx".subdomains.dendrite.CNAME = [ "${config.networking.fqdn}." ]; - - age.secrets = { - # restic-matrix-synapse.file = ./. + "/../../../secrets/${config.networking.hostName}/restic/matrix-synapse.age"; - # matrix-sliding-sync-env.file = ./. + "/../../../secrets/${config.networking.hostName}/matrix-dendrite/sliding-sync-env.age"; - matrix-private-key = { - file = ./. + "/../../secrets/${config.networking.hostName}/matrix-dendrite/private-key.age"; - owner = "dendrite"; - }; - }; - - - services.matrix-synapse.sliding-sync = { - enable = false; - environmentFile = config.age.secrets.matrix-sliding-sync-env.path; - settings = { - SYNCV3_SERVER = "https://dendrite.ctu.cx"; - SYNCV3_BINDADDR = "[::1]:8009"; - }; - }; - - users.groups.dendrite = {}; - users.users.dendrite = { - isSystemUser = true; - home = "/var/lib/dendrite"; - group = "dendrite"; - }; - - systemd.services.dendrite.serviceConfig = { - DynamicUser = lib.mkForce false; - User = "dendrite"; - Group = "dendrite"; - }; - - services.dendrite = { - enable = true; - openRegistration = false; - settings = { - global.server_name = "dendrite.ctu.cx"; - global.private_key = config.age.secrets.matrix-private-key.path; - - global.well_known_server_name = "dendrite.ctu.cx:443"; - global.well_known_client_name = "https://dendrite.ctu.cx"; - - client_api.registration_disabled = true; - }; - }; - - services.nginx = { - enable = true; - virtualHosts = { - "dendrite.ctu.cx" = { - enableACME = true; - forceSSL = true; - kTLS = true; - locations = { - "/.well-known".proxyPass = "http://[::1]:8008"; - "/_matrix".proxyPass = "http://[::1]:8008"; - "/_matrix/client/unstable/org.matrix.msc3575/".proxyPass = "http://[::1]:8009/_matrix/client/unstable/org.matrix.msc3575/"; -# "/_synapse".proxyPass = "http://[::1]:8008"; -# "/admin/".alias = "${pkgs.synapse-admin}/"; - "/".root = pkgs.cinny.override { - conf = { - defaultHomeserver = 0; - homeserverList = [ - "dendrite.ctu.cx" - ]; - allowCustomHomesevrers = false; - }; - }; - }; - }; - - }; - }; - -}- \ No newline at end of file
diff --git a/machines/wanderduene/hardware-configuration.nix b/machines/wanderduene/hardware-configuration.nix @@ -1,38 +1,22 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. { config, lib, pkgs, modulesPath, ... }: { - imports = - [ (modulesPath + "/profiles/qemu-guest.nix") - ]; - boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/8db47ae4-c5e4-4297-aaec-31a6669f4dc4"; - fsType = "ext4"; - }; + imports = [ + (modulesPath + "/profiles/qemu-guest.nix") + ]; + boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "sr_mod" "virtio_blk" ]; boot.initrd.luks.devices."root".device = "/dev/disk/by-uuid/3b1fb60e-e443-4cf8-b5ea-acb5a502e3bd"; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/D496-A891"; - fsType = "vfat"; - }; - - swapDevices = [ ]; + fileSystems."/" = { + device = "/dev/disk/by-uuid/8db47ae4-c5e4-4297-aaec-31a6669f4dc4"; + fsType = "ext4"; + }; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.ens3.useDHCP = lib.mkDefault true; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/D496-A891"; + fsType = "vfat"; + }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; }
diff --git a/machines/wanderduene/rclone-restic-server.nix b/machines/wanderduene/rclone-restic-server.nix @@ -13,12 +13,12 @@ age.secrets = { rclone-config = { - file = ../../secrets/wanderduene/rclone-config.age; + file = ./. + "/../../secrets/${config.networking.hostName}/rclone-config.age"; owner = "rclone-restic-server"; }; restic-server-htpasswd = { - file = ../../secrets/wanderduene/restic-server-htpasswd.age; + file = ./. + "/../../secrets/${config.networking.hostName}/restic-server-htpasswd.age"; owner = "nginx"; }; }; @@ -69,5 +69,4 @@ }; }; - -}- \ No newline at end of file +}
diff --git a/secrets/hector/knot-keys.age b/secrets/hector/knot-keys.age @@ -1,35 +1,39 @@ -----BEGIN AGE ENCRYPTED FILE----- -YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkM3Rob242Z2IzYzZRQzVh -T0RsMHJaZTVsc0xWY3E3WTBNYTZrckhObDFZCjFsVjZPYzZIUkErVHlJQVcwVHQv -U1NSRE9DTWtrMVVCVnJudGFGRHhPRXMKLT4gc3NoLWVkMjU1MTkgeWFMSFNRIEZV -L1owZzIyK0tHQnp1SFk3cWlZUjcycThWSTNzZXJOTmtrUWp6SGZjMmcKNXlIVnBr -N3EvNzNEOVpMcWtVVEhuYzJCd1djZE94dGQyY0lXczNITTVkYwotPiBVM1YtZ3Jl -YXNlICs2dj4gdWsKeG1FdFpLWEx5UU9FT1hNbW9ZWTIvK0k1RXBpdTJGL1k5MHFi -US93THRjTzJMSERUclhIcXZEM25rOG5WaWdTeAo5QUlibzdSTnZOWExjSm1YUFND -bitRCi0tLSAvRFNubVU2VkUxTHhmbFIyYWZWbmdWcTAwK1FWZTZ0dFRHdEZLMVIw -M0c4Cv79lH/bA6fAx0nQSXvVvCwK5DbxqL1jcN/1/ISpRS7JVVtHxKV9R9Ka/N2F -oRMFsjeHZGIlBqVFz1KvtedJvJ92GOym0dY8rOvYvzJYbkMyf1FSayxVWv+7lrqB -tv51nWtK81wfR2I4W+Z7M3gPLE7JLRyGDQ/C1yiAqk7JpN/G4RwhU2E/7ODDJlVp -y2laCbPMl0xUZMHO0ZEsBMRBi30j8hlssOOJ4o/zN4Ny3/yKhQtNaD1ARi8ojBV8 -814wWaL4w4sGiNBcZWR62zo46WuckDrvhyXanLPwCip1LFTZqtTq5fhvNo+N/Ank -s1HFlfFveouweeTDJRsXQUDmsbfV99hZsDgC4qOnelVgMkrOOoMGOeehsujrdLqg -BZrnPIZLtIa9IKHe9NyBrL3u34B7jmRqmwq2lBQZHkBDqQ4zOm08Pg3NmjbcD9Y3 -DEBsVCZE6B6Kw9kbB2Rk0QQzaI4NG2jgAmO7RowuIymvyjFCq/EkUM6JFVyiEkYd -PCAf92VfILyuENrFYO37zwwi55VM13E0ozSu1+9jHcT49wikdZqT/n4fckeMj/SC -H4BkP0F7s1BIOJok5Sdk2bEcdqOZo75KylkIQIF2NOxiImJV5VI9l6+tT75bKcaX -sLttIRtyUkSRrAWtu/KCBSQvnoMRG3sCtY9g9YFx53Re1RdCTcxPMXUt86rknZT7 -bicLWQ2DW0xL+j8XUxz6RxQ8AYWNrETlpHuCA/cCf8YnThY1wuamfTzbsu6kXjlO -u+f1RzLmzpLJ3yfySHHmld42Dc+v3TY3mZC28KG4pkl6Pkp4/mHcUYg2zEPPXrgS -GN0dvL63gLGu4Z0KTFNudF2SSjckKNyiWSoFPpOnQ1lsm5mjPzOk2olV0KjA5gYM -bABBe0YwIs2OpXbt4Ikfue7XWuzFmY7QcIAYvNI9xtu/KXAwM7qKlrUjOf8y9Ea9 -Z5IlW/VukmvKfHiVYOnD0ca677MvMkSZpoSLdu1vkYfOdSFEqBTqWfxPhvyRCx3T -1/aA1es7mH7u6vVps+xLFmGhQIMMzdqt9jaAvn9xRU8xrhddD5MCM3B7p2aAgLLc -gDf+6D3lOMH/0+pl0LAxIvHOAmG8+y21ttK5PGoZtjwldLnhB+nJ4vnT38YlRWjD -7HJNVuvDZRnZODdV6nT5VQYz3EOPOWVe2kBeBZ+ItSYM8Ms1XnsWMI3oxMUZiQB9 -9adreq0gsnYyMRTnstqadZnPv1oz6Oo2zzfAcDsfMnJk6a7dAvY6hjcz/pCtLwKy -97aL1//w4j97ER/rhN6IO+tpOJHR5aVJJZ3IMbxC+hX9QUJCEu8Ewm9ANqWNIFt6 -c0PNQCmqxapPeFh6tbtfC3LSvkSXw/8koQ52dneR+I73df7Behe/REANyFB/gdS/ -yG9KX6zsplephttzlL9B0pAUJ+A96yE8Hb3qeAnQ+pvyyXvjauP92drGW7NER7sb -1kY3nOmVYhqRM9Ch+Tih/y6y/L1pi/OcE4beMVaAXIozdmoJXrTMVeathD+dmux1 -qSy7PAd/EH2ygNdgsBL81rQnsHeHQCdxLZWUiEu6QKVf9mZCR6l6RhKNWO37Glg= +YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnRWNUY3AxaThsbXI5VCto +bENnaGhXRkhIbVBPOXZJbkxJUUdpMjBsbVVnCmUyWVNhby9CLy8yclBhb0UzRmFn +VEtiL05lSGFhUkJub2Z2eC9Hc0ZlQ1kKLT4gc3NoLWVkMjU1MTkgeWFMSFNRIHZI +WXc0Zm5aSGhJRWJGSGd1WGRmaGFhMlpPVTZwNGpwZUlpdUZic29VQncKRkIwUGVj +OW5lMlFpRE1sbXI0cnExMVY3UFNZYVluUWdvaHE4dWRNM2NNWQotPiBBR09XNi1n +cmVhc2UKcGxiLzhpOEc0MmwwOUJ2aUllUzY5OVZYRlZHUFFpRXNkdGtyUFA1QzN0 +M2JIK0UKLS0tIFZVU1BEeTFXWVlPb1pSSGJ0OVptMzZwMUVDSm9Ed2JpSW5uOXRT +SDhxZGMKsp/ngseET20lP83j5KMO6bYZiQiHxdrPq3rCZnVNI0vXSykMLlJCqfBG +pAo/q+g903ywCzugu9oQnyz+PlH5naYs/lrNjU6DAqNDtWhcLbxOemTxsYnEo7z4 +ft0A0jqWBmqiJdDoe2Z2Tu/g3DNQKD/x6aIX9m0c9o4hgZYSuEhDMEsahEbcPPjl +OignpceSIgb9VYlhqo0uRIoSuXL+dYiFWZ5387Y2b+wqInDy3h+ya0H1tNw5tr2S +f7C70pywe4JysNLm+Z5hvElZoOfdH6kanzJTQDTkcSw0i5Xi3YPs3DtIICtihg30 +/X+ejava4eaZsWviExPHD2ulL+J7zkL8wc21HcN9yNsE/gGMma5N++15FcM6eGTW +1k99ts0T/ZtuJAy9Q3MlFowFOO8LwJaf0GgGIYQa7ygYb5iQV1PY5QRtcg/rfE0p +i+bCUh69Buq6HtQ1XU1+HT1j8/AZRD6pba2BEJSUboQ0nf7maA6/45DAF7HyfO5I +r8vo0p2+DVW5NOw4A29NcORpps1ZdcwQffaArNKTSZ8o+Qknxu0lAokncL8M0+qD +9kLZkCQ5hGt7Mln/Q4cw2NYkPmB1zQulGV90lI4DP3GTjlVqeNnEtiGdcAZ8fgjY +TJhc7f6XWNy3I2UPbSzE5H/fIbI8o2uztOQunkzLPYT6Au0U++qPrVnzTCjqJE8W +ZxDT8r9ONg1hIhBU/LL09jRutY+zbRwNQznWR0ZA4zxBFhrdcg85e4hjevRD6iRM +zaB5N66rAykSWm0HhekrD7vOj7cMG5P5ApmgH4379Z1+w+V4h1DY+0kDvAlMqaGm +KXptf0fzOO6xinjEUfLqpBKGjHmmUUgfvBlqxoX5KaLA8agiYXR9n+coANxV4XCj ++u64TF5q1jnxkiAeQzdM136nB+CA889MCcHwiXkPt6bwrLDOdX1njOxItljPoM1Q +dBgxLaxGF4uAMzgPATNpE29CdQQbhuM7NnuTf2qBpyIPcSLFr/c6rFCnokEzp3xt +TZk+DSZtkXEuEt5r2Ly5dR+OnDmk5oVXrZXU19dw/bA3AhHkaginFKx6Sd3LGjx9 +xpd/mqxNZoiLmx5bKrWXGjTqPkzCUziYp/3zdBG7s6pVHOxvg3IlzmEkJCh/KP7d +/RAVc/a4BJLNsJjy34bRBhnFMcJoWRA2MDeEKzuG7QbMPD9mMNwcEdOl6SETNhfB +tZOHDYJJ0mRikyMjpfrIjeg1MJ1nOGvwq0zGa1v/YgCfu/0cGAAV6UMB3enJ9PxY +NDx0FyPTSl8aNtx44Sus0vkpWoKcsb/iMKFv8AMgZSr0bdRXMhbRmjad61dJXEv+ +A8Z4CAWP6eUMEt9f/fAJAOK33NUuQWfcJDdrut0m/UISd9sg26skbGkF3CUJ8ajb +E7Bx9dNnMkcMtOc8hQ7d1rWjEfPsHyfyzVDyOpFC1WmtmKNaeQpTKyJudU0Z4j9r +gn15eBuG1Dpxvaxe2jNUz8+BfxNXwh79ALqzS6E08wVeueR9Dn6j2nhKZRCqBpsS +vD4cDSXtgQC06ecM3JA6uBboSxEUyDrdghZCj8vpH+sPL7RA1YO5fdnvsM81anUz +Lyxv0TIACf2MoYv1jFhCQixyLu3EOxLQQn9/GNip3J1KeXL39Epjofqi+2/y22G/ +lylbpMIGXhwxT5ER89WkvbEwuxv6D/wrjuWleFsNXXyYyajLcODrL4mktioVKKge +GUbEm3U6T8Fv6M425Je1Yl9bjmEnr1v2bPbWtAZrnk39xwSOFFNhoV/FNaB9lYlu +wnbY7gR71uB+K0VwBqxPbFJXBmtQCZ6uw+AZw9P4fuF2xSRVPm4im6Q8gLZqye3Z +5YHUyBVdErPdZW+hvAxy+YHP2S3unDnJJkJpF77BqKq81yoCrGwE2RWlAbFDQg== -----END AGE ENCRYPTED FILE-----