diff --git a/nixarr/ddns/default.nix b/nixarr/ddns/default.nix index bb4a75c..bfe70e5 100644 --- a/nixarr/ddns/default.nix +++ b/nixarr/ddns/default.nix @@ -6,9 +6,66 @@ }: with lib; let cfg = config.nixarr.ddns; + ddns-njalla = pkgs.writeShellApplication { + name = "ddns-njalla"; + + runtimeInputs = with pkgs; [ curl jq ]; + + # Thanks chatgpt... + text = '' + # Path to the JSON file + json_file="${cfg.njalla.keysFile}" + + # Convert the JSON object into a series of tab-separated key-value pairs using jq + # - `to_entries[]`: Convert the object into an array of key-value pairs. + # - `[.key, .value]`: For each pair, create an array containing the key and the value. + # - `@tsv`: Convert the array to a tab-separated string. + # The output will be a series of lines, each containing a key and a value separated by a tab. + jq_command='to_entries[] | [.key, .value] | @tsv' + + # Read the converted output line by line + # - `IFS=$'\t'`: Use the tab character as the field separator. + # - `read -r key val`: For each line, split it into `key` and `val` based on the tab separator. + while IFS=$'\t' read -r key val; do + # For each key-value pair, execute the curl command + # Replace `''${key}` and `''${val}` in the URL with the actual key and value. + curl -s "https://njal.la/update/?h=''${key}&k=''${val}&auto" + done < <(jq -r "$jq_command" "$json_file") + ''; + }; in { options.nixarr.ddns = { njalla = { + vpn = { + enable = mkOption { + type = types.bool; + default = false; + example = true; + description = '' + **Required options:** + + - [`nixarr.ddns.njalla.keysFile`](#nixarr.ddns.njalla.keysfile) + - [`nixarr.vpn.enable`](#nixarr.vpn.enable) + + Whether or not to enable DDNS over VPN for a + [Njalla](https://njal.la/) domain. Setting this will point to + the public ip of your VPN. Useful if you're running services + over VPN and want a domain that points to the corresponding ip. + + **Note:** You can enable both this and the regular njalla DDNS + service. + ''; + }; + + keysFile = mkOption { + type = with types; nullOr path; + default = null; + example = "/data/.secret/njalla/keys-file.json"; + description = '' + See [`nixarr.ddns.njalla.keysFile`](#nixarr.ddns.njalla.keysfile) + ''; + }; + }; enable = mkOption { type = types.bool; default = false; @@ -60,60 +117,70 @@ in { nixarr.ddns.njalla.keysFile option to be set, but it was not. ''; } + { + assertion = cfg.njalla.vpn.enable -> ( + cfg.njalla.vpn.keysFile != null && + nixarr.vpn.enable + ); + message = '' + The nixarr.ddns.njalla.enable option requires the + nixarr.vpn.enable option to be set, but it was not. + ''; + } ]; - systemd.timers = mkIf cfg.njalla.enable { - ddnsNjalla = { - description = "Timer for setting the Njalla DDNS records"; + systemd.timers = mkMerge [ + (mkIf cfg.njalla.enable { + ddnsNjalla = { + description = "Timer for setting the Njalla DDNS records"; - timerConfig = { - OnBootSec = "30"; # Run 30 seconds after system boot - OnCalendar = "hourly"; - Persistent = true; # Run service immediately if last window was missed - RandomizedDelaySec = "5min"; # Run service OnCalendar +- 5min + timerConfig = { + OnBootSec = "30"; # Run 30 seconds after system boot + OnCalendar = "hourly"; + Persistent = true; # Run service immediately if last window was missed + RandomizedDelaySec = "5min"; # Run service OnCalendar +- 5min + }; + + wantedBy = ["multi-user.target"]; }; + }) + (mkIf cfg.njalla.vpn.enable { + ddnsNjallaVpn = { + description = "Timer for setting the Njalla DDNS records over VPN"; - wantedBy = ["multi-user.target"]; - }; - }; + timerConfig = { + OnBootSec = "30"; # Run 30 seconds after system boot + OnCalendar = "hourly"; + Persistent = true; # Run service immediately if last window was missed + RandomizedDelaySec = "5min"; # Run service OnCalendar +- 5min + }; - systemd.services = let - ddns-njalla = pkgs.writeShellApplication { - name = "ddns-njalla"; - - runtimeInputs = with pkgs; [ curl jq ]; - - # Thanks chatgpt... - text = '' - # Path to the JSON file - json_file="${cfg.njalla.keysFile}" - - # Convert the JSON object into a series of tab-separated key-value pairs using jq - # - `to_entries[]`: Convert the object into an array of key-value pairs. - # - `[.key, .value]`: For each pair, create an array containing the key and the value. - # - `@tsv`: Convert the array to a tab-separated string. - # The output will be a series of lines, each containing a key and a value separated by a tab. - jq_command='to_entries[] | [.key, .value] | @tsv' - - # Read the converted output line by line - # - `IFS=$'\t'`: Use the tab character as the field separator. - # - `read -r key val`: For each line, split it into `key` and `val` based on the tab separator. - while IFS=$'\t' read -r key val; do - # For each key-value pair, execute the curl command - # Replace `''${key}` and `''${val}` in the URL with the actual key and value. - curl -s "https://njal.la/update/?h=''${key}&k=''${val}&auto" - done < <(jq -r "$jq_command" "$json_file") - ''; - }; - in mkIf cfg.njalla.enable { - ddnsNjalla = { - description = "Sets the Njalla DDNS records"; - - serviceConfig = { - ExecStart = getExe ddns-njalla; - Type = "oneshot"; + wantedBy = ["multi-user.target"]; }; - }; - }; + }) + ]; + + systemd.services = mkMerge [ + (mkIf cfg.njalla.enable { + ddnsNjalla = { + description = "Sets the Njalla DDNS records"; + + serviceConfig = { + ExecStart = getExe ddns-njalla; + Type = "oneshot"; + }; + }; + }) + (mkIf cfg.njalla.vpn.enable { + ddnsNjallaVpn = { + description = "Sets the Njalla DDNS records over VPN"; + + serviceConfig = { + ExecStart = getExe ddns-njalla; + Type = "oneshot"; + }; + }; + }) + ]; }; } diff --git a/nixarr/jellyfin/default.nix b/nixarr/jellyfin/default.nix index 9a0f079..bb0e4fb 100644 --- a/nixarr/jellyfin/default.nix +++ b/nixarr/jellyfin/default.nix @@ -244,7 +244,10 @@ in with lib; { # Port mappings # TODO: openports if expose.vpn vpnnamespaces.wg = mkIf cfg.vpn.enable { - portMappings = [{ from = defaultPort; to = defaultPort; }]; + portMappings = [{ From = defaultPort; To = defaultPort; }]; + openVPNPorts = optionalString cfg.expose.vpn.enable [ + { port = cfg.expose.vpn.port; protocol = "tcp"; } + ]; }; }; } diff --git a/nixarr/nixarr.nix b/nixarr/nixarr.nix index 09e2377..fd115c4 100644 --- a/nixarr/nixarr.nix +++ b/nixarr/nixarr.nix @@ -203,8 +203,11 @@ in { ]; # TODO: wtf to do about openports - vpnnamespaces.wg = { - enable = cfg.vpn.enable ; + vpnnamespaces.wg = mkIf cfg.vpn.enable { + enable = true; + openVPNPorts = optionalList cfg.vpn.vpnTestService.enable [ + { port = cfg.vpn.vpnTestService.port; protocol = "tcp"; } + ]; accessibleFrom = [ "192.168.1.0/24" "127.0.0.1" @@ -213,8 +216,9 @@ in { }; # TODO: openports - systemd.services.vpn-test-service = { - enable = cfg.vpn.vpnTestService.enable; + systemd.services.vpn-test-service = mkIf cfg.vpn.vpnTestService.enable { + enable = true; + vpnconfinement = { enable = true; vpnnamespace = "wg"; diff --git a/nixarr/openssh/default.nix b/nixarr/openssh/default.nix index 5e737ce..bdcac94 100644 --- a/nixarr/openssh/default.nix +++ b/nixarr/openssh/default.nix @@ -83,9 +83,9 @@ in { }; # Port mappings - # TODO: openports vpnnamespaces.wg = { - portMappings = [{ from = defaultPort; to = defaultPort; }]; + portMappings = [{ From = defaultPort; To = defaultPort; }]; + openVPNPorts = map (x: { port = x; protocol = "both"; }) services.openssh.ports; }; }; } diff --git a/nixarr/transmission/default.nix b/nixarr/transmission/default.nix index aafa578..d318c3d 100644 --- a/nixarr/transmission/default.nix +++ b/nixarr/transmission/default.nix @@ -335,11 +335,11 @@ in { }; # Port mappings - # TODO: open peerPort vpnnamespaces.wg = mkIf cfg.vpn.enable { - portMappings = [{ from = cfg.uiPort; to = cfg.uiPort; }]; - openVPNPorts = [{ port = 24745; protocol = "both"; }]; - #openTcpPorts = [cfg.peerPort]; + portMappings = [{ From = cfg.uiPort; To = cfg.uiPort; }]; + openVPNPorts = [ + { port = cfg.peerPort; protocol = "both"; } + ]; }; services.nginx = mkIf cfg.vpn.enable {