From e6b171f9f1d975ffe34e7a34743b5e92e8593847 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Wed, 11 Jun 2025 13:57:24 +0530 Subject: Add service router + nsd server --- build.sh | 17 +++++++-- configuration.nix | 21 ++++++++++- flake.lock | 37 +++++++++++++++++++ flake.nix | 7 +++- modules/dashboard/bacchus-dashboard.service.nix | 2 +- modules/dashboard/dashboard-template.nix | 19 +++++++--- modules/dashboard/default.nix | 22 ++++++++--- modules/media/default.nix | 2 +- modules/network/default.nix | 4 +- modules/service-router.service.nix | 49 +++++++++++++++++++++++++ notes.org | 4 +- settings.nix | 1 + 12 files changed, 163 insertions(+), 22 deletions(-) create mode 100644 modules/service-router.service.nix diff --git a/build.sh b/build.sh index cd67bbe..20fe342 100755 --- a/build.sh +++ b/build.sh @@ -21,15 +21,23 @@ waittostart() { echo -e "\nReady to connect"; } +copy_in() { copy "$1" "$SSH_TARGET:$2"; } +copy_out() { copy "$SSH_TARGET:$1" "$2"; } + config_sync() { - copy "$SSH_TARGET:~/nixos/flake.lock" .; - copy . "$SSH_TARGET:~/nixos"; + copy_out '~/nixos/flake.lock' .; + copy_in . '~/nixos'; } rebuild() { run_ssh sudo nixos-rebuild switch --flake 'path:/home/bacchus/nixos#bacchus'; } +update_system() { + run_ssh nix flake update --flake 'path:/home/bacchus/nixos'; + rebuild; +} + restart() { run_ssh sudo systemctl reboot; } chaincmds() { @@ -41,7 +49,7 @@ chaincmds() { gen_test_dash() { nix eval --impure \ - --expr 'import ./modules/dashboard/dashboard-template.nix { title = "Dashboard"; links = [{ title = "Google"; url = "https://google.com"; key = "g"; } { title = "DuckDuckGo"; url = "https://duckduckgo.com"; key = "d"; color = "#4c82cf"; }]; }' \ + --expr 'import ./modules/dashboard/dashboard-template.nix { title = "Dashboard"; links = [{ title = "Google"; url = "https://google.com"; altUrl = "http://foobar.com"; key = "g"; } { title = "DuckDuckGo"; url = "https://duckduckgo.com"; key = "d"; color = "#4c82cf"; } { title = "Google"; url = "https://google.com"; altUrl = "http://foobar.com"; key = "g"; } { title = "Google"; url = "https://google.com"; altUrl = "http://foobar.com"; key = "g"; }]; }' \ | jq -r > index.ignore.html } open_test_dash() { brave "file://$PWD/index.ignore.html"; } @@ -51,6 +59,7 @@ case "$cmd" in sync) config_sync ;; run) run_ssh "$@" ;; build) rebuild ;; + update) update_system ;; restart) restart && sleep 3 && waittostart ;; wait) waittostart ;; clean) run_ssh sudo nix-collect-garbage -d ;; @@ -59,6 +68,8 @@ case "$cmd" in test-dash) gen_test_dash ;; open-test-dash) open_test_dash ;; dash) brave "http://$HOME_HOST" ;; + copy_in) copy_in "$@" ;; + copy_out) copy_out "$@" ;; _) chaincmds "$@" ;; *) echo "Invalid cmd: $cmd" && exit 1 ;; esac diff --git a/configuration.nix b/configuration.nix index 45b34ab..048164f 100644 --- a/configuration.nix +++ b/configuration.nix @@ -2,8 +2,12 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). -{ pkgs, ... }: - +{ pkgs, lib, ... }: +let + settings = import ./settings.nix { inherit lib; }; + ports = settings.network.ports; + host = settings.network.host; +in { imports = [ ./modules/hardware.nix @@ -11,8 +15,20 @@ ./modules/network ./modules/media ./modules/dashboard + ./modules/service-router.service.nix ]; + services.service-router = { + enable = true; + routes = { + "home.local" = { inherit host; port = ports.dashboard; }; + "sonarr.local" = { inherit host; port = ports.sonarr; }; + "radarr.local" = { inherit host; port = ports.radarr; }; + "prowlarr.local" = { inherit host; port = ports.prowlarr; }; + "jellyfin.local" = { inherit host; port = ports.jellyfin; }; + }; + }; + nixpkgs.config.allowUnfree = true; environment.systemPackages = with pkgs; [ @@ -21,6 +37,7 @@ neovim lf util-linux + dig ]; systemd.extraConfig = ''DefaultLimitNOFILE=65536''; diff --git a/flake.lock b/flake.lock index 1b18fec..6d6d850 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,41 @@ { "nodes": { + "dns": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1737653493, + "narHash": "sha256-qTbv8Pm9WWF63M5Fj0Od9E54/lsbMSQUBHw/s30eFok=", + "owner": "kirelagin", + "repo": "dns.nix", + "rev": "96e548ae8bd44883afc5bddb9dacd0502542276d", + "type": "github" + }, + "original": { + "owner": "kirelagin", + "repo": "dns.nix", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1614513358, + "narHash": "sha256-LakhOx3S1dRjnh0b5Dg3mbZyH0ToC9I8Y2wKSkBaTzU=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5466c5bbece17adaab2d82fae80b46e807611bf3", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1749195551, @@ -33,6 +69,7 @@ }, "root": { "inputs": { + "dns": "dns", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs" } diff --git a/flake.nix b/flake.nix index d7154c2..b5163e9 100644 --- a/flake.nix +++ b/flake.nix @@ -2,11 +2,16 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixos-hardware.url = "github:NixOS/nixos-hardware"; + dns = { + url = "github:kirelagin/dns.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = { self, nixpkgs, nixos-hardware, ... }: { + outputs = { self, nixpkgs, nixos-hardware, dns, ... }: { nixosConfigurations.bacchus = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; + specialArgs = { inherit dns; }; modules = [ "${nixos-hardware}/lenovo/ideapad" ./configuration.nix diff --git a/modules/dashboard/bacchus-dashboard.service.nix b/modules/dashboard/bacchus-dashboard.service.nix index c14111b..12161c5 100644 --- a/modules/dashboard/bacchus-dashboard.service.nix +++ b/modules/dashboard/bacchus-dashboard.service.nix @@ -32,7 +32,7 @@ in config = { services.nginx = mkIf cfg.enable { enable = true; - virtualHosts."${cfg.host}" = { + virtualHosts.${cfg.host} = { listen = [ { addr = toString cfg.port; } ]; locations."/" = { root = pageDir; diff --git a/modules/dashboard/dashboard-template.nix b/modules/dashboard/dashboard-template.nix index a1df813..5a99e20 100644 --- a/modules/dashboard/dashboard-template.nix +++ b/modules/dashboard/dashboard-template.nix @@ -5,12 +5,11 @@ let if hasAttr attr link then value else def; linkHTML = link: '' -
- - ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""} - - -
+ + ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""} + + ${if hasAttr "altUrl" link then '''' else ""} + ''; script = '' @@ -86,6 +85,14 @@ let padding-top: 1em; color: gray; } + button { + background: none; + padding: 0; + text-decoration: underline; + color: gray; + margin: 0; + border: 0; + } ''; headerHTML = '' diff --git a/modules/dashboard/default.nix b/modules/dashboard/default.nix index 54db0d9..9e434c2 100644 --- a/modules/dashboard/default.nix +++ b/modules/dashboard/default.nix @@ -9,32 +9,44 @@ in services.bacchus-dashboard = { enable = true; openFirewall = true; - title = "Dashboard"; + port = ports.dashboard; + title = "Bacchus Dashboard"; links = [ { title = "Jellyfin"; key = "j"; - url = "http://${settings.network.host}:${toString ports.jellyfin}"; + url = "http://jellyfin.local"; + altUrl = "http://${settings.network.host}:${toString ports.jellyfin}"; color = "#AA5CC3"; } { title = "Sonarr"; key = "s"; - url = "http://${settings.network.host}:${toString ports.sonarr}"; + url = "http://sonarr.local"; + altUrl = "http://${settings.network.host}:${toString ports.sonarr}"; color = "#4c82cf"; } { title = "Radarr"; key = "r"; - url = "http://${settings.network.host}:${toString ports.radarr}"; + url = "http://radarr.local"; + altUrl = "http://${settings.network.host}:${toString ports.radarr}"; color = "#fcbd00"; } { title = "Prowlarr"; key = "p"; - url = "http://${settings.network.host}:${toString ports.prowlarr}"; + url = "http://prowlarr.local"; + altUrl = "http://${settings.network.host}:${toString ports.prowlarr}"; color = "#ff9a7e"; } + { + title = "Syncthing"; + key = "y"; + url = "http://syncthing.local"; + altUrl = "http://${settings.network.host}:${toString ports.syncthing}"; + color = "#0891d1"; + } ]; }; } diff --git a/modules/media/default.nix b/modules/media/default.nix index 4c8edaa..aad65d0 100644 --- a/modules/media/default.nix +++ b/modules/media/default.nix @@ -11,7 +11,7 @@ in "d ${settings.media.tvDir} 0770 sonarr ${settings.media.group} - -" "d ${settings.media.moviesDir} 0770 radarr ${settings.media.group} - -" ]; - users.groups."${settings.media.group}" = { }; + users.groups.${settings.media.group} = { }; users.users.bacchus.extraGroups = [ settings.media.group ]; services.sonarr = { diff --git a/modules/network/default.nix b/modules/network/default.nix index 5a18f37..ee3462c 100644 --- a/modules/network/default.nix +++ b/modules/network/default.nix @@ -3,7 +3,9 @@ let settings = import ../../settings.nix { inherit lib; }; in { - imports = [ ./ssh.nix ]; + imports = [ + ./ssh.nix + ]; networking = { hostName = "bacchus"; diff --git a/modules/service-router.service.nix b/modules/service-router.service.nix new file mode 100644 index 0000000..0b9a873 --- /dev/null +++ b/modules/service-router.service.nix @@ -0,0 +1,49 @@ +{ config, lib, dns, ... }: +with lib; +let + cfg = config.services.service-router; + domainAZone = domain: record: { + A = [ record ]; + SOA = { + nameServer = "ns.${domain}."; + adminEmail = "dont@email.me"; + serial = 2019030800; + }; + NS = [ "ns.${domain}." ]; + }; +in { + options.services.service-router = { + enable = mkEnableOption "enable router"; + routes = mkOption { + type = types.attrsOf (types.submodule { options = { + port = mkOption { type = types.int; }; + host = mkOption { type = types.str; default = "127.0.0.1"; }; + protocol = mkOption { type = types.str; default = "http"; }; + }; }); + default = {}; + }; + }; + + config = lib.mkIf cfg.enable { + services.nginx = { + enable = true; + virtualHosts = lib.mapAttrs (_: val: { + locations."/" = { + proxyPass = "${val.protocol}://${val.host}:${toString val.port}"; + }; + }) cfg.routes; + }; + + services.nsd = { + enable = true; + interfaces = [ "0.0.0.0" ]; + zones = lib.mapAttrs (domain: val: { + data = dns.lib.toString domain (domainAZone domain val.host); + }) cfg.routes; + }; + networking.firewall.allowedTCPPorts = [ 53 ]; + networking.firewall.allowedUDPPorts = [ 53 ]; + + networking.hosts."127.0.0.1" = lib.mapAttrsToList (name: _: name) cfg.routes; + }; +} diff --git a/notes.org b/notes.org index 7efeff1..880b707 100644 --- a/notes.org +++ b/notes.org @@ -1,9 +1,9 @@ ** Current -- [ ] DNS server (dnsmasq, bind, octodns, nsd, [[https://github.com/nix-community/dns.nix]]) - [ ] Syncthing +- [ ] Jellyfin library for photos (shared/private) +- [ ] Jellyfin library for music? ** Later -- [ ] Jellyfin library for photos (shared/private) - [ ] NAS - [ ] [[https://ntfy.sh]] - [ ] Think of where to place the server diff --git a/settings.nix b/settings.nix index 92d3165..43a4804 100644 --- a/settings.nix +++ b/settings.nix @@ -4,6 +4,7 @@ let in lib.recursiveUpdate privateSettings rec { network = { ports = { + dashboard = 80; ssh = 22; radarr = 7878; sonarr = 8989; -- cgit v1.3.1