diff options
| author | Akshay Nair <phenax5@gmail.com> | 2025-06-14 16:40:48 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2025-06-14 16:40:48 +0530 |
| commit | 42df69164dbc74e5ddb54f5a7a01fd66260fef57 (patch) | |
| tree | bc8b19c39df9edf16ca6827005b3d5e1ef564764 /services | |
| parent | 58519ea7b12e8ad58c0f97d9636d30572a789b41 (diff) | |
| download | homeserver-nixos-config-42df69164dbc74e5ddb54f5a7a01fd66260fef57.tar.gz homeserver-nixos-config-42df69164dbc74e5ddb54f5a7a01fd66260fef57.zip | |
Switch to coredns + refactor dns hosts mapping into service + more refactor
Diffstat (limited to 'services')
| -rw-r--r-- | services/bacchus-dashboard/bacchus-dashboard.service.nix | 47 | ||||
| -rw-r--r-- | services/bacchus-dashboard/dashboard-template.nix | 136 | ||||
| -rw-r--r-- | services/bacchus-dns.service.nix | 39 | ||||
| -rw-r--r-- | services/service-router.service.nix | 47 |
4 files changed, 269 insertions, 0 deletions
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: '' + <a href="${link.url}" class="card" style="${withLinkAttr link "color" "" "--color-card-accent: ${link.color}"}"> + ${link.title} ${if hasAttr "key" link then "(${link.key})" else ""} + <div class="card-link">${link.url}</div> + ${if hasAttr "altUrl" link then ''<div class="card-link">(Alt: ${link.altUrl})</div>'' else ""} + </a> + ''; + + 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 = '' + <header>${title}</header> + ''; +in +'' +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <title>${title}</title> + <style>${styles}</style> + </head> + <body> + ${headerHTML} + <section class="links-container"> + ${concatStringsSep "" (map linkHTML links)} + </section> + ${if embedLink == null then "" else '' + <section class="stats-container"> + <iframe src="${embedLink}"></iframe> + </section> + ''} + <script>${script}</script> + </body> +</html> +'' 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; + }; + }; +} |
