diff --git a/hosts/fw.cloonar.com/configuration.nix b/hosts/fw.cloonar.com/configuration.nix index 7c8d3ae..75c142b 100644 --- a/hosts/fw.cloonar.com/configuration.nix +++ b/hosts/fw.cloonar.com/configuration.nix @@ -22,6 +22,7 @@ ./modules/wireguard.nix ./modules/podman.nix ./modules/omada.nix + ./modules/ddclient.nix # git ./modules/gitea.nix @@ -38,6 +39,10 @@ ./modules/snapserver.nix # ./modules/deconz + # gaming + ./modules/palworld.nix + + ./hardware-configuration.nix ]; diff --git a/hosts/fw.cloonar.com/hardware-configuration.nix b/hosts/fw.cloonar.com/hardware-configuration.nix index dd76a74..edb9af5 100644 --- a/hosts/fw.cloonar.com/hardware-configuration.nix +++ b/hosts/fw.cloonar.com/hardware-configuration.nix @@ -3,7 +3,7 @@ boot.loader.systemd-boot.enable = true; boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "vmw_pvscsi" "xen_blkfront" ]; - boot.initrd.kernelModules = [ "nvme" ]; + boot.initrd.kernelModules = [ "nvme" "kvm-intel" ]; fileSystems."/boot" = { device = "/dev/disk/by-label/boot"; diff --git a/hosts/fw.cloonar.com/modules/avahi.nix b/hosts/fw.cloonar.com/modules/avahi.nix index 5ea51b3..9353735 100644 --- a/hosts/fw.cloonar.com/modules/avahi.nix +++ b/hosts/fw.cloonar.com/modules/avahi.nix @@ -3,8 +3,8 @@ enable = true; reflector = true; allowInterfaces = [ + "server" "lan" - "multimedia" ]; }; } diff --git a/hosts/fw.cloonar.com/modules/ddclient.nix b/hosts/fw.cloonar.com/modules/ddclient.nix new file mode 100644 index 0000000..c024a02 --- /dev/null +++ b/hosts/fw.cloonar.com/modules/ddclient.nix @@ -0,0 +1,21 @@ +{ config, ... }: +{ + services.ddclient = { + enable = true; + use = "if, if=wan"; + protocol = "hetzner"; + # server = "https://dns.hetzner.com/api/v1/"; + username = "dominik.polakovics@cloonar.com"; + passwordFile = config.sops.secrets.ddclient.path; + zone = "cloonar.com"; + domains = [ + "vpn.cloonar.com" + "git.cloonar.com" + "palworld.cloonar.com" + ]; + }; + + sops.secrets.ddclient = { + # owner = config.systemd.services.ddclient.serviceConfig.User; + }; +} diff --git a/hosts/fw.cloonar.com/modules/deconz.nix b/hosts/fw.cloonar.com/modules/deconz.nix index 5a8d07d..f4aea44 100644 --- a/hosts/fw.cloonar.com/modules/deconz.nix +++ b/hosts/fw.cloonar.com/modules/deconz.nix @@ -1,13 +1,4 @@ { config, pkgs, ... }: { - users.users.deconz = { - isSystemUser = true; - group = "omada"; - home = "/var/lib/deconz"; - createHome = true; - }; - users.groups.omada = { }; - - # TODO: check if we can run docker service as other user than root virtualisation = { oci-containers.containers = { deconz = { @@ -23,7 +14,7 @@ }; extraOptions = [ "--network=server" - "--mac-address=1a:c4:04:6e:29:02" + "--ip=10.42.97.22" "--device=/dev/ttyACM0" "--hostname=deconz" ]; diff --git a/hosts/fw.cloonar.com/modules/dhcp4.nix b/hosts/fw.cloonar.com/modules/dhcp4.nix index 2a8f87f..9e32d48 100644 --- a/hosts/fw.cloonar.com/modules/dhcp4.nix +++ b/hosts/fw.cloonar.com/modules/dhcp4.nix @@ -44,7 +44,7 @@ } { name = "domain-name-servers"; - data = "10.42.97.10"; + data = "10.42.96.1"; } ]; reservations = [ @@ -84,7 +84,7 @@ } { name = "domain-name-servers"; - data = "10.42.97.10"; + data = "10.42.97.1"; } ]; reservations = [ @@ -129,7 +129,7 @@ } { name = "domain-name-servers"; - data = "10.42.97.10"; + data = "10.42.101.1"; } ]; reservations = [ @@ -164,7 +164,7 @@ } { name = "domain-name-servers"; - data = "10.42.97.10"; + data = "10.42.99.1"; } ]; } @@ -206,7 +206,7 @@ } { name = "domain-name-servers"; - data = "10.42.97.10"; + data = "10.42.100.1"; } ]; reservations = [ diff --git a/hosts/fw.cloonar.com/modules/firewall.nix b/hosts/fw.cloonar.com/modules/firewall.nix index d0f6d22..09206c9 100644 --- a/hosts/fw.cloonar.com/modules/firewall.nix +++ b/hosts/fw.cloonar.com/modules/firewall.nix @@ -1,7 +1,8 @@ -{ ... }: { +{ pkgs, ... }: { networking = { + firewall.checkReversePath = false; nat.enable = false; - nftables = { + # nftables = { # enable = true; # tables = { # "cloonar-fw" = { @@ -102,7 +103,7 @@ # '' # }; # }; - }; + # }; nftables = { enable = true; ruleset = '' @@ -117,18 +118,38 @@ type filter hook output priority 100; policy accept; } + chain rpfilter { + type filter hook prerouting priority mangle + 10; policy drop; + meta nfproto ipv4 udp sport . udp dport { 68 . 67, 67 . 68 } accept comment "DHCPv4 client/server" + fib saddr . mark . iif oif exists accept + } + chain input { type filter hook input priority filter; policy drop; + iifname "lo" accept comment "trusted interfaces" + ct state vmap { invalid : drop, established : accept, related : accept, new : jump input-allow, untracked : jump input-allow } + tcp flags syn / fin,syn,rst,ack log prefix "refused connection: " level info + } + + chain input-allow { + iifname "wan" udp dport 51820 counter accept comment "Wireguard traffic" + + iifname "wg_cloonar" counter accept comment "test wireguard" + + # drop new connections over rate limit + udp dport != { 53, 5353 } ct state new limit rate over 1/second burst 10 packets drop # accept any localhost traffic iifname lo accept # Allow trusted networks to access the router + iifname { + "wg_cloonar" + } counter accept iifname { "server", "vserver", "lan", - "wg_cloonar" } counter accept # Allow networks to access dhcp @@ -137,29 +158,43 @@ "server", "vserver", "infrastructure", - "wg_cloonar", "smart", "podman*", "multimedia" } udp dport { 67, 68 } counter accept + # Allow networks to access dns + iifname { + "lan", + "server", + "vserver", + "infrastructure", + "smart", + "podman*", + "multimedia" + } udp dport { 53 } counter accept + + # allow audio system to access snapserver iifname { - "server" - } tcp dport { 1704 } counter accept + "server", + "smart", + "multimedia" + } tcp dport { 1704, 1705 } counter accept + # allow airplay access + iifname "lan" tcp dport { 5000, 5353 } counter accept + iifname "lan" udp dport { 5000, 5353, 6001 - 6011 } counter accept # Accept mDNS for avahi reflection - # iifname "multimedia" ip saddr tcp dport { llmnr } counter accept - # iifname "multimedia" ip saddr udp dport { mdns, llmnr } counter accept + iifname "server" ip saddr 10.42.97.20/32 tcp dport { llmnr } counter accept + iifname "server" ip saddr 10.42.97.20/32 udp dport { mdns, llmnr } counter accept + + # accept palword server + iifname { "wan", "lan" } udp dport { 8211, 27015 } counter accept # Allow all returning traffic ct state { established, related } counter accept - - # Allow returning traffic from wg_cloonar and drop everthing else - iifname "wg_cloonar" ct state { established, related } counter accept - iifname "wg_cloonar" drop - # Allow returning traffic from wrwks and drop everthing else iifname "wrwks" ct state { established, related } counter accept iifname "wrwks" drop @@ -176,29 +211,42 @@ iifname "wan" ct state { established, related } accept comment "Allow established traffic" iifname "wan" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP" iifname "wan" counter drop comment "Drop all other unsolicited traffic from wan" + + limit rate 60/minute burst 100 packets log prefix "Input - Drop: " comment "Log any unmatched traffic" } chain forward { type filter hook forward priority filter; policy drop; + iifname "wg_cloonar" counter accept comment "test wireguard" + + iifname "wg_cloonar" oifname lo counter accept comment "wireguard to server" + # enable flow offloading for better throughput # ip protocol { tcp, udp } flow offload @f # multimedia airplay iifname "multimedia" oifname { "lan" } counter accept + iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } counter accept + iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept + # avahi + iifname "server" ip saddr 10.42.97.20/32 oifname { "lan" } counter accept + + # smart home coap + iifname "smart" oifname "server" ip daddr 10.42.97.20/32 udp dport { 5683 } counter accept # Forward to git server oifname "server" ip daddr 10.42.97.50 tcp dport { 22, 80, 443 } counter accept - # Forward to dns server - oifname "server" ip daddr 10.42.97.10 udp dport { 53 } accept - # lan and vpn to any # TODO: disable wan when finished iifname { "lan", "server", "vserver", "wg_cloonar" } oifname { "lan", "vb-*", "server", "vserver", "infrastructure", "multimedia", "smart", "wg_cloonar" } counter accept iifname { "lan", "server", "wg_cloonar" } oifname { "wrwks", "wg_epicenter", "wg_ghetto_at" } counter accept iifname { "infrastructure" } oifname { "server", "vserver" } counter accept + # accept palword server + iifname { "wan", "lan" } oifname "podman0" udp dport { 8211, 27015 } counter accept + # allow all established, related ct state { established, related } accept comment "Allow established traffic" @@ -213,9 +261,13 @@ "wg_cloonar", "podman*", "guest", + "vb-*", + "ve-*", } oifname { "wan", } counter accept comment "Allow trusted LAN to WAN" + + limit rate 60/minute burst 100 packets log prefix "Forward - Drop: " comment "Log any unmatched traffic" } } @@ -228,11 +280,35 @@ # Setup NAT masquerading on external interfaces chain postrouting { type nat hook postrouting priority filter; policy accept; - oifname { "wan", "wrwks", "wg_epicenter", "wg_ghetto_at" } masquerade + oifname { "wan", "wg_cloonar", "wrwks", "wg_epicenter", "wg_ghetto_at" } masquerade ip daddr 10.42.97.50 masquerade } } ''; }; }; + + systemd.services.nftables-fix = { + description = "Delete nixos-fw table"; + after = [ "nftables.service" ]; + + serviceConfig = let + fixScript = pkgs.writeTextFile { + name = "nftables-fix"; + executable = true; + text = '' + #! ${pkgs.nftables}/bin/nft -f + delete table inet nixos-fw + ''; + }; + in { + Name = "nftables-fix"; + PartOf = "nftables.service"; + Type = "oneshot"; + ExecStart= [ fixScript ]; + StateDirectory = "nftables"; + }; + }; + + } diff --git a/hosts/fw.cloonar.com/modules/gitea.nix b/hosts/fw.cloonar.com/modules/gitea.nix index e3981ff..e0d8aa2 100644 --- a/hosts/fw.cloonar.com/modules/gitea.nix +++ b/hosts/fw.cloonar.com/modules/gitea.nix @@ -1,4 +1,4 @@ -{ config, ... }: +{ config, pkgs, ... }: let cids = import ../modules/staticids.nix; domain = "git.cloonar.com"; @@ -25,7 +25,10 @@ in containers.git = { autoStart = true; ephemeral = false; # because of ssh key - macvlans = [ "vserver" ]; + privateNetwork = true; + hostBridge = "server"; + hostAddress = "10.42.97.1"; + localAddress = "10.42.97.50/24"; bindMounts = { "/var/lib/gitea" = { hostPath = "/var/lib/gitea/"; @@ -41,16 +44,19 @@ in ../fleet.nix ]; + environment.systemPackages = with pkgs; [ + vim # my preferred editor + ]; + networking = { hostName = "git"; - nameservers = [ "10.42.97.10" ]; - interfaces.mv-vserver = { - useDHCP = true; - }; - firewall = { - enable = true; - allowedTCPPorts = [ 22 80 443 ]; + useHostResolvConf = false; + defaultGateway = { + address = "10.42.96.1"; + interface = "eth0"; }; + firewall.enable = false; + nameservers = [ "10.42.97.1" ]; }; services.nginx.enable = true; diff --git a/hosts/fw.cloonar.com/modules/home-assistant/ac.nix b/hosts/fw.cloonar.com/modules/home-assistant/ac.nix index bfc909f..99c6f74 100644 --- a/hosts/fw.cloonar.com/modules/home-assistant/ac.nix +++ b/hosts/fw.cloonar.com/modules/home-assistant/ac.nix @@ -1,6 +1,7 @@ { services.home-assistant.extraComponents = [ "daikin" + "enocean" ]; services.home-assistant.config = { diff --git a/hosts/fw.cloonar.com/modules/home-assistant/default.nix b/hosts/fw.cloonar.com/modules/home-assistant/default.nix index 2fdb848..4529ee4 100644 --- a/hosts/fw.cloonar.com/modules/home-assistant/default.nix +++ b/hosts/fw.cloonar.com/modules/home-assistant/default.nix @@ -28,7 +28,10 @@ in containers.hass = { autoStart = true; ephemeral = false; - macvlans = [ "vserver" ]; + privateNetwork = true; + hostBridge = "server"; + hostAddress = "10.42.97.1"; + localAddress = "10.42.97.20/24"; allowedDevices = [ { modifier = "rwm"; @@ -82,15 +85,13 @@ in networking = { hostName = "home-assistant"; - nameservers = [ "10.42.97.10" ]; - interfaces.mv-vserver = { - useDHCP = true; - }; - firewall = { - enable = true; - allowedTCPPorts = [ 80 443 ]; - allowedUDPPorts = [ 5683 ]; + useHostResolvConf = false; + defaultGateway = { + address = "10.42.96.1"; + interface = "eth0"; }; + firewall.enable = false; + nameservers = [ "10.42.97.1" ]; }; services.nginx.enable = true; @@ -145,6 +146,14 @@ in time_zone = "Europe/Vienna"; external_url = "https://${domain}"; }; + zone = { + name = "Home"; + latitude = "!secret home_latitude"; + longitude = "!secret home_longitude"; + radius = 35; + icon = "mdi:account-multiple"; + + }; automation = "!include automations.yaml"; frontend = { }; http = { diff --git a/hosts/fw.cloonar.com/modules/networking.nix b/hosts/fw.cloonar.com/modules/networking.nix index fd96ec7..1ac4777 100644 --- a/hosts/fw.cloonar.com/modules/networking.nix +++ b/hosts/fw.cloonar.com/modules/networking.nix @@ -23,7 +23,7 @@ networking = { useDHCP = false; # Define VLANS - nameservers = [ "10.42.97.10" ]; + nameservers = [ "10.42.97.1" ]; # resolvconf.enable = false; vlans = { infrastructure = { @@ -47,9 +47,14 @@ interface = "enp5s0"; }; }; - macvlans.server = { - interface = "vserver"; - mode = "bridge"; + # macvlans.server = { + # interface = "vserver"; + # mode = "bridge"; + # }; + bridges = { + server = { + interfaces = [ "vserver" ]; + }; }; interfaces = { diff --git a/hosts/fw.cloonar.com/modules/palworld.nix b/hosts/fw.cloonar.com/modules/palworld.nix new file mode 100644 index 0000000..0ba4009 --- /dev/null +++ b/hosts/fw.cloonar.com/modules/palworld.nix @@ -0,0 +1,25 @@ +{ config, pkgs, ... }: + +{ + virtualisation.oci-containers.backend = "podman"; + virtualisation.oci-containers.containers = { + palworld = { + image = "thijsvanloef/palworld-server-docker:v0.24.2"; + autoStart = true; + ports = [ + "8211:8211/udp" + "27015:27015/udp" + ]; + environmentFiles = [ + config.sops.secrets.palworld.path + ]; + volumes = [ + "/var/lib/palworld/:/palworld/" + ]; + }; + }; + + sops.secrets.palworld = { + # owner = config.systemd.services.ddclient.serviceConfig.User; + }; +} diff --git a/hosts/fw.cloonar.com/modules/podman.nix b/hosts/fw.cloonar.com/modules/podman.nix index 6fdbbbd..891d098 100644 --- a/hosts/fw.cloonar.com/modules/podman.nix +++ b/hosts/fw.cloonar.com/modules/podman.nix @@ -6,13 +6,13 @@ in { users.groups.podman.gid = cids.gids.podman; virtualisation = { containers.containersConf.settings = { - containers.dns_servers = [ "10.42.97.10" ]; + containers.dns_servers = [ "10.42.97.1" ]; }; podman = { enable = true; dockerCompat = true; defaultNetwork.settings = { - dns_enabled = false; # Enable DNS resolution in the podman network. + dns_enabled = true; # Enable DNS resolution in the podman network. }; }; }; @@ -21,37 +21,43 @@ in { source = json.generate "server.json" ({ name = "server"; id = "d3a55d6bcc28571c124b4e65cdf1831339045d296858f79e7130fa70da9c0904"; - driver = "macvlan"; + driver = "bridge"; network_interface = "server"; ipv6_enabled = false; internal = false; dns_enabled = false; + subnets = [ + { + subnet = "10.42.97.0/24"; + gateway = "10.42.97.1"; + } + ]; ipam_options = { - driver = "dhcp"; + driver = "host-local"; }; }); }; - - systemd.sockets."netavark-dhcp-proxy" = { - description = "Netavark DHCP proxy socket"; - socketConfig = { - ListenStream = "%t/podman/nv-proxy.sock"; - SocketMode = 0660; - }; - wantedBy = [ "sockets.target" ]; - }; - - systemd.services."netavark-dhcp-proxy" = { - description = "Netavark DHCP proxy service"; - after = [ "netavark-dhcp-proxy.socket" ]; - requires = [ "netavark-dhcp-proxy.socket" ]; - wantedBy = [ "multi-user.target" "netavark-dhcp-proxy.socket" ]; - path = [ pkgs.netavark ]; - startLimitIntervalSec = 0; - - serviceConfig = { - Type = "exec"; - ExecStart= "${pkgs.netavark}/bin/netavark dhcp-proxy -a 30"; - }; - }; + # + # systemd.sockets."netavark-dhcp-proxy" = { + # description = "Netavark DHCP proxy socket"; + # socketConfig = { + # ListenStream = "%t/podman/nv-proxy.sock"; + # SocketMode = 0660; + # }; + # wantedBy = [ "sockets.target" ]; + # }; + # + # systemd.services."netavark-dhcp-proxy" = { + # description = "Netavark DHCP proxy service"; + # after = [ "netavark-dhcp-proxy.socket" ]; + # requires = [ "netavark-dhcp-proxy.socket" ]; + # wantedBy = [ "multi-user.target" "netavark-dhcp-proxy.socket" ]; + # path = [ pkgs.netavark ]; + # startLimitIntervalSec = 0; + # + # serviceConfig = { + # Type = "exec"; + # ExecStart= "${pkgs.netavark}/bin/netavark dhcp-proxy -a 30"; + # }; + # }; } diff --git a/hosts/fw.cloonar.com/modules/snapserver.nix b/hosts/fw.cloonar.com/modules/snapserver.nix index 5a44b7b..a2846fd 100644 --- a/hosts/fw.cloonar.com/modules/snapserver.nix +++ b/hosts/fw.cloonar.com/modules/snapserver.nix @@ -1,128 +1,115 @@ { pkgs, config, python3Packages, ... }: let -shairport-sync = pkgs.shairport-sync.overrideAttrs (_: { - configureFlags = [ - "--with-alsa" "--with-pipe" "--with-pa" "--with-stdout" - "--with-avahi" "--with-ssl=openssl" "--with-soxr" - # "--with-mqtt-client" - "--without-configfiles" - "--sysconfdir=/etc" - "--with-metadata" - ]; - # buildInputs = [ - # pkgs.openssl - # pkgs.avahi - # pkgs.popt - # pkgs.libconfig - # pkgs.mosquitto - # pkgs.alsa-lib - # pkgs.libpulseaudio - # pkgs.pipewire - # pkgs.libjack2 - # pkgs.soxr - # ]; -}); + domain = "snapcast.cloonar.com"; in { - environment.etc = { - # Creates /etc/nanorc - shairport = { - text = '' - whatever you want to put in the file goes here. - metadata = - { - enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe - include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes". - cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems - pipe_name = "/tmp/shairport-sync-metadata"; - pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up - }; - - - mqtt = - { - enabled = "yes"; // set this to yes to enable the mqtt-metadata-service - hostname = "127.0.0.1"; // Hostname of the MQTT Broker - port = 1883; // Port on the MQTT Broker to connect to - username = "espresense"; //set this to a string to your username in order to enable username authentication - password = "insecure-password"; //set this to a string you your password in order to enable username & password authentication - topic = "shairport"; //MQTT topic where this instance of shairport-sync should publish. If not set, the general.name value is used. - // publish_raw = "no"; //whether to publish all available metadata under the codes given in the 'metadata' docs. - publish_parsed = "yes"; //whether to publish a small (but useful) subset of metadata under human-understandable topics - publish_cover = "yes"; //whether to publish the cover over mqtt in binary form. This may lead to a bit of load on the broker - // enable_remote = "no"; //whether to remote control via MQTT. RC is available under `topic`/remote. - }; - ''; - - # The UNIX file mode bits - mode = "0440"; - }; + security.acme.certs."${domain}" = { + group = "nginx"; }; - services.snapserver = { - enable = true; - codec = "flac"; - http.docRoot = "${pkgs.snapcast}/share/snapserver/snapweb"; - streams.mopidy = { - type = "pipe"; - location = "/run/snapserver/mopidy"; - }; - streams.airplay = { - type = "airplay"; - location = "${shairport-sync}/bin/shairport-sync"; - query = { - devicename = "Multi Room"; - port = "5000"; - params = "--mdns=avahi"; + containers.snapcast = { + autoStart = true; + ephemeral = false; # because of ssh key + privateNetwork = true; + hostBridge = "server"; + hostAddress = "10.42.97.1"; + localAddress = "10.42.97.21/24"; + bindMounts = { + "/var/lib/acme/snapcast/" = { + hostPath = "${config.security.acme.certs.${domain}.directory}"; + isReadOnly = true; }; }; - streams.mixed = { - type = "meta"; - location = "/airplay/mopidy"; + config = { lib, config, pkgs, python3Packages, ... }: + let + shairport-sync = pkgs.shairport-sync.overrideAttrs (_: { + configureFlags = [ + "--with-alsa" "--with-pipe" "--with-pa" "--with-stdout" + "--with-avahi" "--with-ssl=openssl" "--with-soxr" + "--without-configfiles" + "--sysconfdir=/etc" + "--with-metadata" + ]; + }); + in + { + networking = { + hostName = "snapcast"; + useHostResolvConf = false; + defaultGateway = { + address = "10.42.96.1"; + interface = "eth0"; + }; + nameservers = [ "10.42.97.1" ]; + firewall.enable = false; + }; + environment.etc = { + # Creates /etc/nanorc + shairport = { + text = '' + whatever you want to put in the file goes here. + metadata = + { + enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe + include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes". + cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems + pipe_name = "/tmp/shairport-sync-metadata"; + pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up + }; + ''; + + # The UNIX file mode bits + mode = "0440"; + }; + }; + + services.snapserver = { + enable = true; + codec = "flac"; + http.docRoot = "${pkgs.snapcast}/share/snapserver/snapweb"; + streams.mopidy = { + type = "pipe"; + location = "/run/snapserver/mopidy"; + }; + streams.airplay = { + type = "airplay"; + location = "${shairport-sync}/bin/shairport-sync"; + query = { + devicename = "Multi Room New"; + port = "5000"; + params = "--mdns=avahi"; + }; + }; + streams.mixed = { + type = "meta"; + location = "/airplay/mopidy"; + }; + }; + + services.avahi.enable = true; + services.avahi.publish.enable = true; + services.avahi.publish.userServices = true; + + services.nginx.virtualHosts."snapcast.cloonar.com" = { + sslCertificate = "/var/lib/acme/snapcast/fullchain.pem"; + sslCertificateKey = "/var/lib/acme/snapcast/key.pem"; + sslTrustedCertificate = "/var/lib/acme/snapcast/chain.pem"; + forceSSL = true; + extraConfig = '' + proxy_buffering off; + ''; + locations."/".extraConfig = '' + proxy_pass http://127.0.0.1:1780; + proxy_set_header Host $host; + proxy_redirect http:// https://; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + ''; + }; + + system.stateVersion = "23.05"; }; }; - - services.avahi.enable = true; - services.avahi.publish.enable = true; - services.avahi.publish.userServices = true; - - # services.shairport-sync = { - # enable = true; - # arguments = "-v -o=pipe -- pipe:name=/run/snapserver/airplay"; - # }; - - services.nginx.virtualHosts."snapcast.cloonar.com" = { - forceSSL = true; - enableACME = true; - acmeRoot = null; - extraConfig = '' - proxy_buffering off; - ''; - locations."/".extraConfig = '' - proxy_pass http://127.0.0.1:1780; - proxy_set_header Host $host; - proxy_redirect http:// https://; - proxy_http_version 1.1; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - ''; - }; - - - # networking.firewall.allowedTCPPorts = [ - # 80 # http - # 443 # https - # 1704 # snapcast - # 1705 # snapcast - # 5000 # airplay - # 5353 # airplay - # ]; - # networking.firewall.allowedUDPPorts = [ - # 5000 # airplay - # 5353 # airplay - # ]; - # networking.firewall.allowedUDPPortRanges = [ - # { from = 6001; to = 6011; } # airplay - # ]; } diff --git a/hosts/fw.cloonar.com/modules/unbound.nix b/hosts/fw.cloonar.com/modules/unbound.nix index 3cf9cd7..da6a417 100644 --- a/hosts/fw.cloonar.com/modules/unbound.nix +++ b/hosts/fw.cloonar.com/modules/unbound.nix @@ -19,7 +19,7 @@ let "10.42.101.0/24 allow" "0.0.0.0/0 allow" ]; - tls-cert-bundle = "/var/lib/acme/unbound/fullchain.pem"; + tls-cert-bundle = "/var/lib/acme/ns.cloonar.com/fullchain.pem"; local-zone = "\"cloonar.com\" transparent"; local-data = [ "\"localhost A 127.0.0.1\"" @@ -31,9 +31,11 @@ let "\"omada.cloonar.com IN A 10.42.97.2\"" "\"switch.cloonar.com IN A 10.42.97.10\"" - "\"mopidy.cloonar.com IN A 10.42.97.20\"" - "\"deconz.cloonar.com IN A 10.42.97.25\"" - "\"snapcast.cloonar.com IN A 10.42.97.20\"" + "\"mopidy.cloonar.com IN A 10.42.97.21\"" + "\"deconz.cloonar.com IN A 10.42.97.22\"" + "\"snapcast.cloonar.com IN A 10.42.97.21\"" + "\"home-assistant.cloonar.com IN A 10.42.97.20\"" + "\"git.cloonar.com IN A 10.42.97.50\"" "\"stage.wsw.at IN A 10.254.235.22\"" "\"prod.wsw.at IN A 10.254.217.23\"" @@ -88,7 +90,10 @@ let "\"127.0.0.1 localhost\"" "\"::1 localhost\"" "\"10.42.97.1 fw.cloonar.com\"" - "\"10.42.97.25 deconz.cloonar.com\"" + "\"10.42.97.20 home-assistant.cloonar.com\"" + "\"10.42.97.21 snapcast.cloonar.com\"" + "\"10.42.97.22 deconz.cloonar.com\"" + "\"10.42.97.50 git.cloonar.com\"" "\"10.254.235.22 stage.wsw.at\"" "\"10.254.217.23 prod.wsw.at\"" @@ -154,105 +159,65 @@ in { security.acme.certs."${domain}" = { group = "unbound"; }; + security.acme.certs."fw.cloonar.com" = { + group = "unbound"; + }; - containers.ns = { - autoStart = true; - ephemeral = true; - macvlans = [ "vserver" ]; - bindMounts = { - "/var/lib/acme/unbound/" = { - hostPath = "${config.security.acme.certs.${domain}.directory}"; - isReadOnly = true; - }; - "/var/lib/kea" = { - hostPath = "/var/lib/kea"; - isReadOnly = true; - }; - }; - config = { lib, config, pkgs, ... }: { - networking = { - hostName = "ns"; - defaultGateway = { - address = "10.42.97.1"; - interface = "mv-vserver"; - }; - interfaces.mv-vserver = { - ipv4.addresses = [{ - address = "10.42.97.10"; - prefixLength = 24; - }]; - }; - firewall = { - enable = true; - allowedUDPPorts = [ 53 ]; - allowedTCPPorts = [ 853 ]; - }; - }; - users.users.unbound = { - group = "unbound"; - isSystemUser = true; - uid = cids.uids.unbound; - }; - users.groups.unbound = { - gid = cids.gids.unbound; - }; - services.unbound = { - enable = true; - settings = cfg; - }; - systemd.services.unbound-sync = { - enable = true; - path = with pkgs; [ unbound inotify-tools ]; - script = '' - function readFile() { - if [[ "''\$2" == "A" ]] ; then - cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context - do - echo "''\${address},''\${hostname}" - done - else - cat "''\$1" | tail -n +2 | while IFS=, read -r address duid valid_lifetime expire subnet_id pref_lifetime lease_type iaid prefix_len fqdn_fwd fqdn_rev hostname hwaddr state user_context hwtype hwaddr_source - do - echo "''\${address},''\${hostname}" - done - fi - } - - function readFileUnique() { - readFile "''\$1" ''\$2 | uniq | while IFS=, read -r address hostname - do - if [[ "''\${hostname}" == *.cloonar.com ]] ; then - echo ''\${hostname} ''\$2 ''\${address} - unbound-control local_data ''\${hostname} ''\$2 ''\${address} - if [[ "''\$2" == "A" ]] ; then - echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3 - do - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} - unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} - done - fi - fi - done - } + + services.unbound = { + enable = true; + settings = cfg; + }; + systemd.services.unbound-sync = { + enable = true; + path = with pkgs; [ unbound inotify-tools ]; + script = '' + function readFile() { + if [[ "''\$2" == "A" ]] ; then + cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context + do + echo "''\${address},''\${hostname}" + done + else + cat "''\$1" | tail -n +2 | while IFS=, read -r address duid valid_lifetime expire subnet_id pref_lifetime lease_type iaid prefix_len fqdn_fwd fqdn_rev hostname hwaddr state user_context hwtype hwaddr_source + do + echo "''\${address},''\${hostname}" + done + fi + } - function syncFile() { - # readFileUnique "''\$1" "''\$2" - while true; do - readFileUnique "''\$1" "''\$2" - sleep 10 - done - } + function readFileUnique() { + readFile "''\$1" ''\$2 | uniq | while IFS=, read -r address hostname + do + if [[ "''\${hostname}" == *.cloonar.com ]] ; then + echo ''\${hostname} ''\$2 ''\${address} + unbound-control local_data ''\${hostname} ''\$2 ''\${address} + if [[ "''\$2" == "A" ]] ; then + echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3 + do + unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname} + unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname} + done + fi + fi + done + } + + function syncFile() { + # readFileUnique "''\$1" "''\$2" + while true; do + readFileUnique "''\$1" "''\$2" + sleep 10 + done + } - syncFile "/var/lib/kea/dhcp4.leases" A & - # syncFile "/var/lib/kea/dhcp6.leases" AAAA & - wait - ''; - wants = [ "network-online.target" "unbound.service" ]; - after = [ "network-online.target" "unbound.service" ]; - partOf = [ "unbound.service" ]; - wantedBy = [ "multi-user.target" ]; - }; - system.stateVersion = "23.05"; - }; + syncFile "/var/lib/kea/dhcp4.leases" A & + # syncFile "/var/lib/kea/dhcp6.leases" AAAA & + wait + ''; + wants = [ "network-online.target" "unbound.service" ]; + after = [ "network-online.target" "unbound.service" ]; + partOf = [ "unbound.service" ]; + wantedBy = [ "multi-user.target" ]; }; } diff --git a/hosts/fw.cloonar.com/modules/wireguard.nix b/hosts/fw.cloonar.com/modules/wireguard.nix index 575b04a..0935151 100644 --- a/hosts/fw.cloonar.com/modules/wireguard.nix +++ b/hosts/fw.cloonar.com/modules/wireguard.nix @@ -4,6 +4,8 @@ sops.secrets.wg_epicenter_works_psk = {}; sops.secrets.wg_ghetto_at_key = {}; + # https://wiki.archlinux.org/title/WireGuard#Loop_routing + networking.wireguard.interfaces = { wg_cloonar = { ips = [ "10.42.98.1/24" ]; diff --git a/hosts/fw.cloonar.com/secrets.yaml b/hosts/fw.cloonar.com/secrets.yaml index 247693d..1287f97 100644 --- a/hosts/fw.cloonar.com/secrets.yaml +++ b/hosts/fw.cloonar.com/secrets.yaml @@ -1,5 +1,6 @@ borg-passphrase: ENC[AES256_GCM,data:jHb+yXK0RqNdVYtWiueztZFlHC/xQ6ZiAOUcLt6BxmZQewuL3mh4AZ+lQdmA/4EaaTTIhVMR3xFx5fU6b2CtNLiGb/0=,iv:IW09B1EE1OupMCOvv13MXRYiMsD4VmIfyYONUyrPX1c=,tag:3ankeLOaDJkwRUGCd72DuA==,type:str] borg-ssh-key: ENC[AES256_GCM,data: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,iv:9E1uiPqM3Hh4KWtL8haxm6PRm2VPc+DggrA135FvfB8=,tag:QSOgzVH9IBMgZxJvUhvY2w==,type:str] +ddclient: ENC[AES256_GCM,data:EaXjXS/bwL3S/Fr+rzQ7dXA1eIzeFpHH7H+SvoNhVSg=,iv:3BzjnJG5yT1W8ob2nm0oUlr+sSJ73W/ctl48xyxeeWM=,tag:TqKSwfxF0V1v5T8VT/qblw==,type:str] wrwks_vpn_key: ENC[AES256_GCM,data:gGipXC8JJO59b4KWMSo0+r761raQl7RzgBuUbXmPEKlZR21bs5XRAQalzDCFNtjcpNkXiGqAHCLkDTtjPagMsw==,iv:MH1EBJEOdQDEgm9E0F884fynhsH8KiS5QSc605XbASQ=,tag:FUM1eptHS0rpt6ILyQjGOg==,type:str] wg_cloonar_key: ENC[AES256_GCM,data:Dtp6I5J0jU5LLVwEFU4DFCpUngPRmFMebGXnk2oSwsKtsir/DtRBFG7ictM=,iv:1Abx/EAZRJrRQURljofzUYDgJpuREriX0nSrFbH5Npw=,tag:l4uFl9Uc+W0XeLVfLGmgZA==,type:str] wg_epicenter_works_key: ENC[AES256_GCM,data:LeLjfwfaz+loWyHYRgIMIPzHzlOnhl9tluKcQFgdes6r+deft1JfnUzDuF0=,iv:DKrc3I+U2hWDH8nnc8ZQeaVtA1eVXu7SXdTn1fxHoH4=,tag:V0PL0GrL2NEPVslAZa801A==,type:str] @@ -9,6 +10,7 @@ gitea-runner-token: ENC[AES256_GCM,data:Nd0vsnuJficsdZaqeBZXa9vD7PLMdDtV9sMX0TxU drone: ENC[AES256_GCM,data:S8WTZqGHfcdpSojavZ87GdE5dagcTAdHBVQEbHHgnB4V7aczS6c5QdEJxK920Pjpf6o54OOQYniVsPiiXSxwjExDKPzhs/DG2hfigmf8RgfkP+3tF2W0KiPmV2jxog8w226ZKnI+hSBs8tuIfJBhrpY7Y/YNmTPfq+cnnLS8ibYqytcpzoogI9I8THzHCu3r+yejoGSyTMs9L4gPhOjz5aK4UV6V,iv:zqN/aSBI3xGGNDnpHPGyQnQP2YZOGUk6dAGtON/QlHU=,tag:o9YFDKAB5uR9lPmChyxB8g==,type:str] home-assistant-ldap: ENC[AES256_GCM,data:uZEPbSnkgQYSd8ev6FD8TRHWWr+vusadtMcvP7KKL2AZAV0h1hga5fODN6I5u0DNL9hq2pNM+FwU0E/svWLRww==,iv:IhmUgSu34NaAY+kUZehx40uymydUYYAyte1aGqQ33/8=,tag:BKFCJPr7Vz4EG78ry/ZD7g==,type:str] home-assistant-secrets.yaml: ENC[AES256_GCM,data:m7uOVo7hPk/RmqqRS6y7NKoMKsR9Bdi1ntatsZdDOAbJMjZmZL2FgPEHi/zF73zCfRfTOca3dwpulR3WXZ9Ic1sbUIggmusJMg4Gellw1CUhx7SbQN5nieAbPbB9GVxMuV4OakD1u7Swz8JggDT6IwojSnuD5omCRCyUH1wvKB+Re59q6EStderlm5MJNVFlVrbKVbLKLcw4yRgTh34BGnTTjcJmgSlQjO1ciu2B7YQmdl0Fw6d8AdbEzgB5TFG5ONc85UhJDE8Wlw==,iv:GCtpcVChN2UMWtfnWURozCfVj2YbRPqp/bH4Jjntybs=,tag:pcxP7gTBtXMNT5iyW5YXTw==,type:str] +palworld: ENC[AES256_GCM,data:93LMjHr7zEI67ZDHNr/MErZ+EIey8YccvemvwVbnql7WaJ3ynMMkowmJALCwsD8DfvHqSSLzR1Uz3roIx3FEhBBhiAXY0uDEvuvlG3LB4XS2FefTnuDAxyRKe9S8E7zMH3U5lYEMFhmXdkH3ctXqhZWdB0aSXJesAQQ00EC3igMfezS2fa8=,iv:2Nd+PoCtNhTypGs2iAzFEZ8XTusFtvCDwCqyh9mn+D8=,tag:yVJ6bfU8YnKza0l3+b+stg==,type:str] sops: kms: [] gcp_kms: [] @@ -33,8 +35,8 @@ sops: Tlo3NHBlMkJEaXNOZkxSKytGSDNEMWcKquNuAzbPWwAjqc65BcAA/DMltFjC6Ayb CKmJ7kaYFFUAIuBXhksvlH2b7vRZLT1QlwqUcRIRjxe+mZnsMIqE7w== -----END AGE ENCRYPTED FILE----- - lastmodified: "2023-12-09T21:02:39Z" - mac: ENC[AES256_GCM,data:fgpga0FpOsVvBOOkx5mr7U/mcQ/2o3+SED8/Iv9LuGkdg2MBAloIvUWOTgw9AP/OHIj41KMQUYlapNWHXDFd4hd3Vib1Fsk4x856v3sL7TgtwJW6/cvP1D99rV76NolJ3cNH9GNDdI50Bx/prZCB8E/Izyu4jwKWmck8ByRGkZE=,iv:mBGOvop4oLX1an4D6R08p8502EWsMBWFrnrM52T7pB4=,tag:uWtJjQ3iUj1/3BOOyD6nhw==,type:str] + lastmodified: "2024-02-09T22:05:20Z" + mac: ENC[AES256_GCM,data:6vieCZv+E6wHG+vkTg6V+fzuGlRBG91sWUrfIvAY1qSZ7sm1OdRsEhnjCJXnYwO8FCHx/GZRZDJqmDl6Iz21tbGQkul8rn3VV0qgslBWEHYCvKiULVfa78Ep3uDEu3Mqtsr3dNbQS6faTPNgpZIVFdZZzcKJfoaQVzzS98fJEno=,iv:pKpRATCTAe6zTXC7fl9uh6NIB+BKtdxOmfa+j7wftWU=,tag:4PYkA3ILTgHcj5HjOCeFgQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.8.1 diff --git a/hosts/nb-01.cloonar.com/configuration.nix b/hosts/nb-01.cloonar.com/configuration.nix index 4f847d5..a8b6524 100644 --- a/hosts/nb-01.cloonar.com/configuration.nix +++ b/hosts/nb-01.cloonar.com/configuration.nix @@ -75,6 +75,7 @@ networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. networking.extraHosts = '' 10.25.0.25 archive.zeichnemit.at + 5.9.131.26 old.epicenter.works # 10.25.0.25 epicenter.works en.epicenter.works 127.0.0.1 wohnservice.local mieterhilfe.local wohnpartner.local wohnberatung.local wienbautvor.local wienwohntbesser.local 127.0.0.1 wohnservice-wien.local mieterhilfe.local wohnpartner-wien.local wohnberatung-wien.local wienbautvor.local wienwohntbesser.local @@ -121,6 +122,7 @@ winetricks git-filter-repo ykfde + nix-prefetch-git ]; environment.variables = { @@ -192,27 +194,28 @@ ip46tables -t mangle -D nixos-fw-rpfilter -p udp -m udp --dport 51820 -j RETURN || true ''; }; - # networking.wireguard.interfaces = { - # wg0 = { - # # Determines the IP address and subnet of the client's end of the tunnel interface. - # ips = [ "10.42.98.201/32" ]; - # # Path to the private key file. - # # - # # Note: The private key can also be included inline via the privateKey option, - # # but this makes the private key world-readable; thus, using privateKeyFile is - # # recommended. - # privateKeyFile = config.sops.secrets.wg-cloonar-key.path; - # - # peers = [ - # { - # publicKey = "TKQVDmBnf9av46kQxLQSBDhAeaK8r1zh8zpU64zuc1Q="; - # allowedIPs = [ "10.42.97.0/20" "10.14.0.0/16" "10.25.0.0/16" ]; - # endpoint = "vpn.cloonar.com:51820"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577 - # persistentKeepalive = 25; - # } - # ]; - # }; - # }; + networking.wireguard.interfaces = { + wg0 = { + # Determines the IP address and subnet of the client's end of the tunnel interface. + ips = [ "10.42.98.201/32" ]; + # Path to the private key file. + # + # Note: The private key can also be included inline via the privateKey option, + # but this makes the private key world-readable; thus, using privateKeyFile is + # recommended. + # publicKey: YdlRGsjh4hS3OMJI+t6SZ2eGXKbs0wZBXWudHW4NyS8= + privateKeyFile = config.sops.secrets.wg-cloonar-key.path; + + peers = [ + { + publicKey = "TKQVDmBnf9av46kQxLQSBDhAeaK8r1zh8zpU64zuc1Q="; + allowedIPs = [ "10.42.96.0/20" "10.14.0.0/16" "10.25.0.0/16" ]; + endpoint = "vpn.cloonar.com:51820"; # ToDo: route to endpoint not automatically configured https://wiki.archlinux.org/index.php/WireGuard#Loop_routing https://discourse.nixos.org/t/solved-minimal-firewall-setup-for-wireguard-client/7577 + persistentKeepalive = 25; + } + ]; + }; + }; # Facial recognition "Windows hello" # services.ir-toggle.enable = true; diff --git a/raspberry/README.md b/raspberry/README.md index 8e10430..fd52e33 100644 --- a/raspberry/README.md +++ b/raspberry/README.md @@ -1,4 +1,4 @@ # Raspberry Pi Multiroom audio client - change hostname in sd-card.nix - add wifi psk -- nix-build '' -A config.system.build.sdImage -I nixos-config=./sd-card.nix --argstr system aarch64-linux --argstr hostname music-piano +- nix-build '' -A config.system.build.sdImage -I nixos-config=./sd-card.nix --argstr system aarch64-linux diff --git a/raspberry/sd-card-zero.nix b/raspberry/sd-card-zero.nix new file mode 100644 index 0000000..c4604b8 --- /dev/null +++ b/raspberry/sd-card-zero.nix @@ -0,0 +1,81 @@ +{ + config, + lib, + pkgs, + ... +}: +let + hostName = "music-"; + outputDevice = "Headphones"; + snapserverHost = "snapcast.cloonar.com"; +in +{ + nixpkgs.crossSystem.system = "aarch64-linux"; + imports = [ + + ]; + + networking.hostName = hostName; + networking.wireless = { + enable = true; + networks = { + "Cloonar-Multimedia" = { + hidden = true; + psk = "K2MC28Zhk$4zsx6Y"; + }; + }; + }; + + boot = { + loader.raspberryPi.firmwareConfig = '' + dtparam=audio=on + ''; + extraModprobeConfig = '' + options snd_bcm2835 enable_headphones=1 + ''; + }; + + # hardware.raspberry-pi."4" = { + # fkms-3d.enable = true; + # audio.enable = true; + # dwc2.enable = true; + # }; + + sound.enable = true; + + systemd.services.snapclient = { + description = "Snapcast client"; + wantedBy = ["multi-user.target"]; + wants = ["network-online.target"]; + after = ["network-online.target"]; + + serviceConfig = { + Type = "forking"; + ExecStart = "${pkgs.snapcast}/bin/snapclient --daemon --hostID ${config.networking.hostName} -h ${snapserverHost} --player alsa -s ${outputDevice}"; + PIDFile = "/run/snapclient/pid"; + Restart = "on-failure"; + RestartSec = "5s"; + DynamicUser = true; + SupplementaryGroups = "audio"; + RuntimeDirectory = "snapclient"; + }; + }; + + services.openssh.enable = true; + users = { + mutableUsers = false; + users.root = { + hashedPassword = lib.mkForce "$6$7IKExnDde920x.YH$ggegnnKJYdmg1Wt33fxuPpM.MmIaX32LXVyjL8ed7ohT385lKotFGzRpitncQ3pd9Lci1QCFGRn2tVJGxkFAm0"; + openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius" + ]; + }; + }; + + system.stateVersion = "22.05"; + + sdImage = { + compressImage = false; + }; +} diff --git a/raspberry/sd-card.nix b/raspberry/sd-card.nix index beaa97e..0ab4515 100644 --- a/raspberry/sd-card.nix +++ b/raspberry/sd-card.nix @@ -3,30 +3,39 @@ lib, pkgs, ... -}: { +}: +let + hostName = "music-bed"; + outputDevice = "snd_rpi_hifiberry_dacplus"; + snapserverHost = "snapcast.cloonar.com"; +in +{ nixpkgs.crossSystem.system = "aarch64-linux"; imports = [ ]; - networking.hostName = "music-piano"; + networking.hostName = hostName; networking.wireless = { enable = true; networks = { - "Cloonar-Smart" = { + "Cloonar-Multimedia" = { hidden = true; - psk = "0m6sY7Ue3G31"; + psk = ""; }; }; }; boot = { loader.raspberryPi.firmwareConfig = '' - dtparam=audio=on - ''; - extraModprobeConfig = '' - options snd_bcm2835 enable_headphones=1 + dtoverlay=vc4-kms-v3d,noaudio + dtoverlay=hifiberry-dacplus + force_eeprom_read=0 + dtdebug=1 ''; + # extraModprobeConfig = '' + # options snd_bcm2835 enable_headphones=1 + # ''; }; # hardware.raspberry-pi."4" = { @@ -45,7 +54,7 @@ serviceConfig = { Type = "forking"; - ExecStart = "${pkgs.snapcast}/bin/snapclient --daemon --hostID ${config.networking.hostName} -h fw.cloonar.com --player alsa -s Headphones"; + ExecStart = "${pkgs.snapcast}/bin/snapclient --daemon --hostID ${config.networking.hostName} -h ${snapserverHost} --player alsa -s ${outputDevice}"; PIDFile = "/run/snapclient/pid"; Restart = "on-failure"; RestartSec = "5s"; diff --git a/utils/pkgs/bento/default.nix b/utils/pkgs/bento/default.nix index 7e860d8..ac97d0a 100644 --- a/utils/pkgs/bento/default.nix +++ b/utils/pkgs/bento/default.nix @@ -6,8 +6,8 @@ stdenv.mkDerivation rec { src = fetchgit { url = "https://github.com/dpolakovics/bento.git"; - rev = "5379043e253ffe80bc7fd31e30ef455097612119"; - sha256 = "sha256-hwkdE/zH68vgEerzS29Qm6P6+S/4Dvfw+4wl8v8tdVM="; + rev = "8d911a02dc9af222ffb5892bbddd4a3895893959"; + sha256 = "sha256-9R3glZcjc+t8LKvo5HOAo+HzXFQ6GOtzehJpb7GjmYM="; }; buildInputs = [ ];