From 42df69164dbc74e5ddb54f5a7a01fd66260fef57 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 14 Jun 2025 16:40:48 +0530 Subject: Switch to coredns + refactor dns hosts mapping into service + more refactor --- configuration.nix | 4 +- flake.lock | 37 ------ flake.nix | 7 +- modules/dashboard/bacchus-dashboard.service.nix | 47 ------- modules/dashboard/dashboard-template.nix | 136 --------------------- modules/dashboard/default.nix | 2 +- modules/hardware.nix | 73 ----------- modules/hardware/default.nix | 49 ++++++++ modules/hardware/fs.nix | 27 ++++ modules/network/default.nix | 19 ++- modules/network/service-router.service.nix | 59 --------- modules/users.nix | 21 ---- modules/users/default.nix | 21 ++++ .../bacchus-dashboard.service.nix | 47 +++++++ services/bacchus-dashboard/dashboard-template.nix | 136 +++++++++++++++++++++ services/bacchus-dns.service.nix | 39 ++++++ services/service-router.service.nix | 47 +++++++ 17 files changed, 384 insertions(+), 387 deletions(-) delete mode 100644 modules/dashboard/bacchus-dashboard.service.nix delete mode 100644 modules/dashboard/dashboard-template.nix delete mode 100644 modules/hardware.nix create mode 100644 modules/hardware/default.nix create mode 100644 modules/hardware/fs.nix delete mode 100644 modules/network/service-router.service.nix delete mode 100644 modules/users.nix create mode 100644 modules/users/default.nix create mode 100644 services/bacchus-dashboard/bacchus-dashboard.service.nix create mode 100644 services/bacchus-dashboard/dashboard-template.nix create mode 100644 services/bacchus-dns.service.nix create mode 100644 services/service-router.service.nix diff --git a/configuration.nix b/configuration.nix index f1af667..ec0f1a0 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,8 +1,8 @@ { pkgs, ... }: { imports = [ - ./modules/hardware.nix - ./modules/users.nix + ./modules/hardware + ./modules/users ./modules/network ./modules/media ./modules/dashboard diff --git a/flake.lock b/flake.lock index f1c7fdc..ea98cc1 100644 --- a/flake.lock +++ b/flake.lock @@ -1,41 +1,5 @@ { "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, @@ -69,7 +33,6 @@ }, "root": { "inputs": { - "dns": "dns", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs" } diff --git a/flake.nix b/flake.nix index b5163e9..d7154c2 100644 --- a/flake.nix +++ b/flake.nix @@ -2,16 +2,11 @@ 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, dns, ... }: { + outputs = { self, nixpkgs, nixos-hardware, ... }: { 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 deleted file mode 100644 index 8b0fcb9..0000000 --- a/modules/dashboard/bacchus-dashboard.service.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ config, lib, pkgs, ... }: -with lib; -let - cfg = config.services.bacchus-dashboard; - - rootHTML = import ./dashboard-template.nix cfg; - indexHTMLFile = pkgs.writeText "index.html" rootHTML; - - pageDir = pkgs.stdenv.mkDerivation { - pname = "dashboard-page"; - version = "0.0.0"; - unpackPhase = "true"; # no source - installPhase = '' - mkdir -p $out; - cp ${indexHTMLFile} $out/index.html; - ''; - }; -in -{ - options.services.bacchus-dashboard = { - enable = mkEnableOption "Enable dashboard"; - title = mkOption { type = types.str; default = "Dashboard"; }; - links = mkOption { - type = types.listOf (types.attrs); - default = []; - }; - embedLink = mkOption { type = types.str; }; - openFirewall = mkEnableOption "Open firewall ports"; - host = mkOption { type = types.str; default = "_"; }; - port = mkOption { type = types.int; default = 80; }; - }; - - config = { - services.nginx = mkIf cfg.enable { - enable = true; - virtualHosts.${cfg.host} = { - listen = [ { addr = toString cfg.port; } ]; - locations."/" = { - root = pageDir; - tryFiles = "$uri /index.html"; - }; - }; - }; - - networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 80 ]; - }; -} diff --git a/modules/dashboard/dashboard-template.nix b/modules/dashboard/dashboard-template.nix deleted file mode 100644 index 9883a1d..0000000 --- a/modules/dashboard/dashboard-template.nix +++ /dev/null @@ -1,136 +0,0 @@ -{ title, links ? [], embedLink ? null, ... }: -with builtins; -let - withLinkAttr = link: attr: def: value: - if hasAttr attr link then value else def; - - linkHTML = link: '' - - ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""} - - ${if hasAttr "altUrl" link then '''' else ""} - - ''; - - script = '' - window.addEventListener('keydown', (event) => { - const noMod = !event.ctrlKey && !event.altKey; - ${concatStringsSep "\n" (map (link: - withLinkAttr link "key" "" '' - if (event.key.toLowerCase() == ${toJSON link.key} && noMod) { - event.preventDefault(); - if (event.shiftKey) - window.open(${toJSON link.url}); - else - window.location.href = ${toJSON link.url}; - return; - } - '' - ) links)} - }); - ''; - - styles = '' - :root { - font-size: 16px; - color: #dbe0f9; - font-family: JetBrains Mono, monospace; - --color-gray: #1a1824; - } - html, body { - background-color: #0f0c19; - padding: 0; - margin: 0; - } - body * { box-sizing: border-box; } - header { - padding: 1rem 2rem; - background-color: #000; - } - .links-container { - display: grid; - gap: 1rem; - grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); - padding: 0 1rem; - width: 100%; - margin: 1rem auto 2rem; - } - .card { - --color-card-accent: #8e7ae3; - display: block; - padding: 1rem 1.5rem; - font-size: 1.2rem; - color: var(--color-card-accent); - text-decoration: none; - border: 2px solid var(--color-gray); - position: relative; - } - .card::before { - content: " "; - position: absolute; - left: 0; top: 0; - width: 4px; height: 100%; - background-color: var(--color-card-accent); - } - .card:hover { - border-color: var(--color-card-accent); - background-color: rgba(255,255,255,0.05); - } - .card:focus { - border-color: var(--color-card-accent); - outline: none; - } - .card-link { - font-size: 0.5em; - padding-top: 1em; - color: gray; - } - button { - background: none; - padding: 0; - text-decoration: underline; - color: gray; - margin: 0; - border: 0; - } - .stats-container { - padding: 1rem; - border-top: 1px solid var(--color-gray); - } - .stats-container iframe { - width: 100%; - display: block; - min-height: 1100px; - height: 100%; - border: 2px solid var(--color-gray); - border-radius: 5px; - } - ''; - - headerHTML = '' -
${title}
- ''; -in -'' - - - - - - ${title} - - - - ${headerHTML} - - ${if embedLink == null then "" else '' -
- -
- ''} - - - -'' diff --git a/modules/dashboard/default.nix b/modules/dashboard/default.nix index 196eab1..c1de246 100644 --- a/modules/dashboard/default.nix +++ b/modules/dashboard/default.nix @@ -4,7 +4,7 @@ let ports = settings.network.ports; in { - imports = [ ./bacchus-dashboard.service.nix ]; + imports = [ ../../services/bacchus-dashboard/bacchus-dashboard.service.nix ]; services.bacchus-dashboard = { enable = true; diff --git a/modules/hardware.nix b/modules/hardware.nix deleted file mode 100644 index 7b11ca6..0000000 --- a/modules/hardware.nix +++ /dev/null @@ -1,73 +0,0 @@ -{ lib, modulesPath, ... }: -{ - imports = [ - (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd = { - availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ]; - kernelModules = [ ]; - }; - boot.kernelModules = [ - "kvm-intel" - "sd_mod" - ]; - hardware = { - enableAllFirmware = true; - cpu.intel.updateMicrocode = true; - }; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - - # Power/power state - powerManagement = { - enable = true; - cpuFreqGovernor = "powersave"; - }; - services.acpid.enable = true; - services.logind = { - powerKey = "ignore"; - rebootKey = "ignore"; - lidSwitch = "ignore"; - lidSwitchDocked = "ignore"; - lidSwitchExternalPower = "ignore"; - hibernateKey = "ignore"; - suspendKey = "ignore"; - }; - - # Bootloader - boot.loader = { - systemd-boot = { - enable = true; - configurationLimit = 30; - }; - timeout = 1; - efi.canTouchEfiVariables = true; - }; - - # File system - fileSystems = { - "/" = { - device = "/dev/disk/by-label/nixos"; - fsType = "ext4"; - }; - "/boot" = { - device = "/dev/disk/by-label/boot"; - fsType = "vfat"; - }; - "/media" = { - device = "/dev/disk/by-label/media"; - fsType = "ext4"; - options = [ "rw" "nofail" "x-systemd.automount" "x-systemd.mount-timeout=30s" ]; - }; - }; - swapDevices = [{ device = "/dev/disk/by-label/swap"; }]; - - networking.useDHCP = lib.mkDefault true; - - systemd.extraConfig = ''DefaultLimitNOFILE=65536''; - systemd.user.extraConfig = ''DefaultLimitNOFILE=65536''; - boot.kernel.sysctl."fs.inotify.max_user_instances" = 8192; - security.pam.loginLimits = [ - { domain = "*"; type = "-"; item = "nofile"; value = "65536"; } - ]; -} diff --git a/modules/hardware/default.nix b/modules/hardware/default.nix new file mode 100644 index 0000000..098b3cc --- /dev/null +++ b/modules/hardware/default.nix @@ -0,0 +1,49 @@ +{ lib, modulesPath, ... }: +{ + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ./fs.nix + ]; + + boot.initrd = { + availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ]; + kernelModules = [ ]; + }; + boot.kernelModules = [ + "kvm-intel" + "sd_mod" + ]; + hardware = { + enableAllFirmware = true; + cpu.intel.updateMicrocode = true; + }; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + + # Power/power state + powerManagement = { + enable = true; + cpuFreqGovernor = "powersave"; + }; + services.acpid.enable = true; + services.logind = { + powerKey = "ignore"; + rebootKey = "ignore"; + lidSwitch = "ignore"; + lidSwitchDocked = "ignore"; + lidSwitchExternalPower = "ignore"; + hibernateKey = "ignore"; + suspendKey = "ignore"; + }; + + # Bootloader + boot.loader = { + systemd-boot = { + enable = true; + configurationLimit = 30; + }; + timeout = 1; + efi.canTouchEfiVariables = true; + }; + + networking.useDHCP = lib.mkDefault true; +} diff --git a/modules/hardware/fs.nix b/modules/hardware/fs.nix new file mode 100644 index 0000000..aaf67d6 --- /dev/null +++ b/modules/hardware/fs.nix @@ -0,0 +1,27 @@ +{ ... }: +{ + fileSystems = { + "/" = { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + }; + "/boot" = { + device = "/dev/disk/by-label/boot"; + fsType = "vfat"; + }; + "/media" = { + device = "/dev/disk/by-label/media"; + fsType = "ext4"; + options = [ "rw" "nofail" "x-systemd.automount" "x-systemd.mount-timeout=30s" ]; + }; + }; + swapDevices = [{ device = "/dev/disk/by-label/swap"; }]; + + # Set high limits for file watching/file handles + systemd.extraConfig = ''DefaultLimitNOFILE=65536''; + systemd.user.extraConfig = ''DefaultLimitNOFILE=65536''; + boot.kernel.sysctl."fs.inotify.max_user_instances" = 8192; + security.pam.loginLimits = [ + { domain = "*"; type = "-"; item = "nofile"; value = "65536"; } + ]; +} diff --git a/modules/network/default.nix b/modules/network/default.nix index 290c291..78fac75 100644 --- a/modules/network/default.nix +++ b/modules/network/default.nix @@ -8,9 +8,15 @@ in imports = [ ./wireless.nix ./ssh.nix - ./service-router.service.nix + ../../services/service-router.service.nix + ../../services/bacchus-dns.service.nix ]; + networking = { + hostName = "bacchus"; + firewall.enable = true; + }; + services.service-router = { enable = true; routes = { @@ -23,12 +29,15 @@ in "syncthing.local" = { inherit host; port = ports.syncthing; }; "lidarr.local" = { inherit host; port = ports.lidarr; }; "ntfy.local" = { inherit host; port = ports.ntfy; }; - "grafana.local" = { inherit host; port = ports.grafana; extraOptions.recommendedProxySettings = true; }; + "grafana.local" = { inherit host; port = ports.grafana; extraNginxOptions.recommendedProxySettings = true; }; }; }; - networking = { - hostName = "bacchus"; - firewall.enable = true; + # Host mappings defined by service-router + services.bacchus-dns = { + enable = true; + port = 53; + openFirewall = true; + fallback = [ "1.1.1.1" "8.8.8.8" ]; }; } diff --git a/modules/network/service-router.service.nix b/modules/network/service-router.service.nix deleted file mode 100644 index 14fc1b2..0000000 --- a/modules/network/service-router.service.nix +++ /dev/null @@ -1,59 +0,0 @@ -{ 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"; }; - basePath = mkOption { type = types.str; default = ""; }; - nginx = mkOption { type = types.attrs; default = {}; }; - extraOptions = mkOption { type = types.attrs; default = {}; }; - }; }); - default = {}; - }; - }; - - config = lib.mkIf cfg.enable { - services.nginx = { - enable = true; - recommendedOptimisation = true; - virtualHosts = lib.mapAttrs (_: val: - let - opts = if hasAttr "extraOptions" val then val.extraOptions else {}; - in { - locations."/" = if val.nginx == {} then { - proxyPass = - "${val.protocol}://${val.host}:${toString val.port}${val.basePath}"; - proxyWebsockets = true; - } // opts else val.nginx; - } - ) 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/modules/users.nix b/modules/users.nix deleted file mode 100644 index 223a2f8..0000000 --- a/modules/users.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ pkgs, lib, ... }: -let - settings = import ../settings.nix { inherit lib; }; -in -{ - users.users.root.password = settings.passwords.root; - - users.users.bacchus = { - isNormalUser = true; - shell = pkgs.bash; - extraGroups = [ - "wheel" - "input" - "networkmanager" - "git" - "docker" - "transmission" - "multimedia" - ]; - }; -} diff --git a/modules/users/default.nix b/modules/users/default.nix new file mode 100644 index 0000000..7969496 --- /dev/null +++ b/modules/users/default.nix @@ -0,0 +1,21 @@ +{ pkgs, lib, ... }: +let + settings = import ../../settings.nix { inherit lib; }; +in +{ + users.users.root.password = settings.passwords.root; + + users.users.bacchus = { + isNormalUser = true; + shell = pkgs.bash; + extraGroups = [ + "wheel" + "input" + "networkmanager" + "git" + "docker" + "transmission" + "multimedia" + ]; + }; +} diff --git a/services/bacchus-dashboard/bacchus-dashboard.service.nix b/services/bacchus-dashboard/bacchus-dashboard.service.nix new file mode 100644 index 0000000..8b0fcb9 --- /dev/null +++ b/services/bacchus-dashboard/bacchus-dashboard.service.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.bacchus-dashboard; + + rootHTML = import ./dashboard-template.nix cfg; + indexHTMLFile = pkgs.writeText "index.html" rootHTML; + + pageDir = pkgs.stdenv.mkDerivation { + pname = "dashboard-page"; + version = "0.0.0"; + unpackPhase = "true"; # no source + installPhase = '' + mkdir -p $out; + cp ${indexHTMLFile} $out/index.html; + ''; + }; +in +{ + options.services.bacchus-dashboard = { + enable = mkEnableOption "Enable dashboard"; + title = mkOption { type = types.str; default = "Dashboard"; }; + links = mkOption { + type = types.listOf (types.attrs); + default = []; + }; + embedLink = mkOption { type = types.str; }; + openFirewall = mkEnableOption "Open firewall ports"; + host = mkOption { type = types.str; default = "_"; }; + port = mkOption { type = types.int; default = 80; }; + }; + + config = { + services.nginx = mkIf cfg.enable { + enable = true; + virtualHosts.${cfg.host} = { + listen = [ { addr = toString cfg.port; } ]; + locations."/" = { + root = pageDir; + tryFiles = "$uri /index.html"; + }; + }; + }; + + networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [ 80 ]; + }; +} diff --git a/services/bacchus-dashboard/dashboard-template.nix b/services/bacchus-dashboard/dashboard-template.nix new file mode 100644 index 0000000..9883a1d --- /dev/null +++ b/services/bacchus-dashboard/dashboard-template.nix @@ -0,0 +1,136 @@ +{ title, links ? [], embedLink ? null, ... }: +with builtins; +let + withLinkAttr = link: attr: def: value: + if hasAttr attr link then value else def; + + linkHTML = link: '' + + ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""} + + ${if hasAttr "altUrl" link then '''' else ""} + + ''; + + script = '' + window.addEventListener('keydown', (event) => { + const noMod = !event.ctrlKey && !event.altKey; + ${concatStringsSep "\n" (map (link: + withLinkAttr link "key" "" '' + if (event.key.toLowerCase() == ${toJSON link.key} && noMod) { + event.preventDefault(); + if (event.shiftKey) + window.open(${toJSON link.url}); + else + window.location.href = ${toJSON link.url}; + return; + } + '' + ) links)} + }); + ''; + + styles = '' + :root { + font-size: 16px; + color: #dbe0f9; + font-family: JetBrains Mono, monospace; + --color-gray: #1a1824; + } + html, body { + background-color: #0f0c19; + padding: 0; + margin: 0; + } + body * { box-sizing: border-box; } + header { + padding: 1rem 2rem; + background-color: #000; + } + .links-container { + display: grid; + gap: 1rem; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + padding: 0 1rem; + width: 100%; + margin: 1rem auto 2rem; + } + .card { + --color-card-accent: #8e7ae3; + display: block; + padding: 1rem 1.5rem; + font-size: 1.2rem; + color: var(--color-card-accent); + text-decoration: none; + border: 2px solid var(--color-gray); + position: relative; + } + .card::before { + content: " "; + position: absolute; + left: 0; top: 0; + width: 4px; height: 100%; + background-color: var(--color-card-accent); + } + .card:hover { + border-color: var(--color-card-accent); + background-color: rgba(255,255,255,0.05); + } + .card:focus { + border-color: var(--color-card-accent); + outline: none; + } + .card-link { + font-size: 0.5em; + padding-top: 1em; + color: gray; + } + button { + background: none; + padding: 0; + text-decoration: underline; + color: gray; + margin: 0; + border: 0; + } + .stats-container { + padding: 1rem; + border-top: 1px solid var(--color-gray); + } + .stats-container iframe { + width: 100%; + display: block; + min-height: 1100px; + height: 100%; + border: 2px solid var(--color-gray); + border-radius: 5px; + } + ''; + + headerHTML = '' +
${title}
+ ''; +in +'' + + + + + + ${title} + + + + ${headerHTML} + + ${if embedLink == null then "" else '' +
+ +
+ ''} + + + +'' diff --git a/services/bacchus-dns.service.nix b/services/bacchus-dns.service.nix new file mode 100644 index 0000000..d6f45f9 --- /dev/null +++ b/services/bacchus-dns.service.nix @@ -0,0 +1,39 @@ +{ lib, config, ... }: +with lib; +let + cfg = config.services.bacchus-dns; +in +{ + options.services.bacchus-dns = { + enable = mkEnableOption "dns server mappings"; + port = mkOption { type = types.int; default = 53; }; + openFirewall = mkEnableOption "open required ports in firewall"; + ttl = mkOption { type = types.int; default = 3600; }; + fallback = mkOption { type = types.listOf types.str; default = [ "1.1.1.1" ]; }; + hosts = mkOption { type = types.attrsOf types.str; default = {}; }; + }; + + config = { + services.coredns = mkIf cfg.enable { + enable = true; + extraArgs = [ "-dns.port=${toString cfg.port}" ]; + config = '' + . { + hosts { + ${concatStringsSep "\n" ( + mapAttrsToList (domain: target: "${target} ${domain}") cfg.hosts)} + fallthrough + } + forward . ${concatStringsSep " " cfg.fallback} + cache ${toString cfg.ttl} + errors + } + ''; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + allowedUDPPorts = [ cfg.port ]; + }; + }; +} diff --git a/services/service-router.service.nix b/services/service-router.service.nix new file mode 100644 index 0000000..e52280f --- /dev/null +++ b/services/service-router.service.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: +with lib; +let + cfg = config.services.service-router; +in { + imports = [ + ./bacchus-dns.service.nix + ]; + + 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"; }; + basePath = mkOption { type = types.str; default = ""; }; + extraNginxOptions = mkOption { type = types.attrs; default = {}; }; + }; }); + default = {}; + }; + }; + + config = lib.mkIf cfg.enable { + services.nginx = { + enable = true; + recommendedOptimisation = true; + virtualHosts = lib.mapAttrs (_: val: + let + opts = if hasAttr "extraNginxOptions" val then val.extraNginxOptions else {}; + in { + locations."/" = { + proxyPass = + "${val.protocol}://${val.host}:${toString val.port}${val.basePath}"; + proxyWebsockets = true; + } // opts; + } + ) cfg.routes; + }; + + # Hostname mapping + services.bacchus-dns = { + enable = true; + hosts = mapAttrs (_: val: val.host) cfg.routes; + }; + }; +} -- cgit v1.3.1