diff options
-rw-r--r-- | flake.lock | 75 | ||||
-rw-r--r-- | flake.nix | 4 | ||||
-rw-r--r-- | hosts/ahmed/cloudflare-ddns.nix | 7 | ||||
-rw-r--r-- | hosts/ahmed/configuration.nix | 21 | ||||
-rw-r--r-- | modules/default.nix | 1 | ||||
-rw-r--r-- | modules/linus.onl/default.nix | 20 | ||||
-rw-r--r-- | modules/notifications.linus.onl/default.nix | 42 | ||||
-rw-r--r-- | services/default.nix | 1 | ||||
-rw-r--r-- | services/on-demand-minecraft/default.nix | 2 | ||||
-rw-r--r-- | services/push-notification-api/default.nix | 67 |
10 files changed, 206 insertions, 34 deletions
@@ -44,6 +44,24 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -72,11 +90,11 @@ ] }, "locked": { - "lastModified": 1693208669, - "narHash": "sha256-hHFaaUsZ860wvppPeiu7nJn/nXZjJfnqAQEu9SPFE9I=", + "lastModified": 1695108154, + "narHash": "sha256-gSg7UTVtls2yO9lKtP0yb66XBHT1Fx5qZSZbGMpSn2c=", "owner": "nix-community", "repo": "home-manager", - "rev": "5bac4a1c06cd77cf8fc35a658ccb035a6c50cd2c", + "rev": "07682fff75d41f18327a871088d20af2710d4744", "type": "github" }, "original": { @@ -93,11 +111,11 @@ ] }, "locked": { - "lastModified": 1692248770, - "narHash": "sha256-tZeFpETKQGbgnaSIO1AGWD27IyTcBm4D+A9d7ulQ4NM=", + "lastModified": 1696043447, + "narHash": "sha256-VbJ1dY5pVH2fX1bS+cT2+4+BYEk4lMHRP0+udu9G6tk=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "511177ffe8226c78c9cf6a92a7b5f2df3684956b", + "rev": "792c2e01347cb1b2e7ec84a1ef73453ca86537d8", "type": "github" }, "original": { @@ -108,11 +126,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694048570, - "narHash": "sha256-PEQptwFCVaJ+jLFJgrZll2shQ9VI/7xVhrCYkJo8iIw=", + "lastModified": 1695825837, + "narHash": "sha256-4Ne11kNRnQsmSJCRSSNkFRSnHC4Y5gPDBIQGjjPfJiU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4f77ea639305f1de0a14d9d41eef83313360638c", + "rev": "5cfafa12d57374f48bcc36fda3274ada276cf69e", "type": "github" }, "original": { @@ -122,12 +140,49 @@ "type": "github" } }, + "push-notification-api": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1696078003, + "narHash": "sha256-h/g1YUfz6L3P3KCQ0ulOXfEqsigLAxghNLiLh+03Jhc=", + "owner": "linnnus", + "repo": "push-notification-api", + "rev": "1f8f8448e9b879e8e2938482055dd917019cb96f", + "type": "github" + }, + "original": { + "owner": "linnnus", + "repo": "push-notification-api", + "type": "github" + } + }, "root": { "inputs": { "agenix": "agenix", "home-manager": "home-manager_2", "nix-darwin": "nix-darwin", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "push-notification-api": "push-notification-api" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, @@ -15,6 +15,10 @@ url = "github:ryantm/agenix"; inputs.nixpkgs.follows = "nixpkgs"; }; + push-notification-api = { + url = "github:linnnus/push-notification-api"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { self, nixpkgs, home-manager, nix-darwin, agenix, ... }@inputs: diff --git a/hosts/ahmed/cloudflare-ddns.nix b/hosts/ahmed/cloudflare-ddns.nix index a46f76a..a118fa6 100644 --- a/hosts/ahmed/cloudflare-ddns.nix +++ b/hosts/ahmed/cloudflare-ddns.nix @@ -6,15 +6,10 @@ let in { - age.secrets.cloudflare-dyndns-api-token = { - file = ../../secrets/cloudflare-ddns-token.env.age; - # TODO: configure permissions - }; - + age.secrets.cloudflare-dyndns-api-token.file = ../../secrets/cloudflare-ddns-token.env.age; services.cloudflare-dyndns = { enable = true; apiTokenFile = config.age.secrets.cloudflare-dyndns-api-token.path; proxied = true; - domains = [ "linus.onl" ]; }; } diff --git a/hosts/ahmed/configuration.nix b/hosts/ahmed/configuration.nix index a1937b0..fc1cc9c 100644 --- a/hosts/ahmed/configuration.nix +++ b/hosts/ahmed/configuration.nix @@ -9,7 +9,6 @@ ./hardware-configuration.nix ./ssh.nix ./disable-screen.nix - ./cloudflare-ddns.nix ]; # Create the main user. @@ -45,13 +44,18 @@ openFirewall = true; }; + # Set up dukse server. Det er satme hårdt at være overduksepåmindelsesansvarlig. my.services.duksebot.enable = true; - # Host <https://linus.onl>. + # Virtual hosts. + services.nginx.enable = true; my.modules."linus.onl" = { enable = true; useACME = true; - openFirewall = true; + }; + my.modules."notifications.linus.onl" = { + enable = true; + useACME = true; }; # Configure ACME for various HTTPS services. @@ -60,6 +64,17 @@ defaults.email = "linusvejlo+${config.networking.hostName}[email protected]"; }; + # Configure DDNS. The website for each module is responsible for extending `services.cloudflare-dyndns.domains` with its domain. + age.secrets.cloudflare-dyndns-api-token.file = ../../secrets/cloudflare-ddns-token.env.age; + services.cloudflare-dyndns = { + enable = true; + apiTokenFile = config.age.secrets.cloudflare-dyndns-api-token.path; + proxied = true; + }; + + # Listen for HTTP connections. + networking.firewall.allowedTCPPorts = [ 80 443 ]; + # We are running behind CF proxy. my.modules.cloudflare-proxy.enable = true; diff --git a/modules/default.nix b/modules/default.nix index 61ef9cc..3015d59 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -4,6 +4,7 @@ imports = [ ./linus.onl + ./notifications.linus.onl ./cloudflare-proxy ./graphics ]; diff --git a/modules/linus.onl/default.nix b/modules/linus.onl/default.nix index f65bf0b..617865c 100644 --- a/modules/linus.onl/default.nix +++ b/modules/linus.onl/default.nix @@ -12,15 +12,6 @@ in enable = mkEnableOption "${domain} static site"; useACME = mkEnableOption "built-in HTTPS stuff"; - - openFirewall = mkOption { - description = '' - Open holes in the firewall so clients on LAN can connect. You must - set up port forwarding if you want to play over WAN. - ''; - type = types.bool; - default = false; - }; }; config = mkIf cfg.enable { @@ -91,16 +82,15 @@ in wantedBy = [ "nginx.service" ]; }; - networking.firewall = mkIf cfg.openFirewall { - allowedTCPPorts = [ 80 ] ++ (optional cfg.useACME 443); - }; + # Register domain name with ddns. + services.cloudflare-dyndns.domains = [ domain ]; - # Serve the generated page using NGINX. + # Register virtual host. services.nginx = { - enable = true; - virtualHosts."${domain}" = { + # NOTE: 'forceSSL' will cause an infite loop, if the cloudflare proxy does NOT connect over HTTPS. enableACME = cfg.useACME; + forceSSL = cfg.useACME; root = "/var/www/${domain}"; }; }; diff --git a/modules/notifications.linus.onl/default.nix b/modules/notifications.linus.onl/default.nix new file mode 100644 index 0000000..443853f --- /dev/null +++ b/modules/notifications.linus.onl/default.nix @@ -0,0 +1,42 @@ +{ pkgs, lib, config, ... }: + +let + inherit (lib) mkEnableOption mkOption types mkIf optional; + + domain = "notifications.linus.onl"; + + # TODO: Make option internal-port. + internal-port = 13082; + + cfg = config.my.modules."notifications.linus.onl"; +in +{ + options.my.modules."notifications.linus.onl" = { + enable = mkEnableOption "notifications.linus.onl static site"; + + useACME = mkEnableOption "built-in HTTPS stuff"; + }; + + config = mkIf cfg.enable { + my.services.push-notification-api = { + enable = true; + # host = "notifications.linus.onl"; + host = "0.0.0.0"; + port = internal-port; + openFirewall = false; # We're using NGINX reverse proxy. + }; + + # Register domain name. + services.cloudflare-dyndns.domains = [ "notifications.linus.onl" ]; + + # Serve the generated page using NGINX. + services.nginx.virtualHosts."notifications.linus.onl" = { + enableACME = cfg.useACME; + forceSSL = cfg.useACME; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://127.0.0.1:${toString internal-port}"; + }; + }; + }; +} diff --git a/services/default.nix b/services/default.nix index 995ca27..39e030b 100644 --- a/services/default.nix +++ b/services/default.nix @@ -9,5 +9,6 @@ [ ./on-demand-minecraft ./duksebot + ./push-notification-api ]; } diff --git a/services/on-demand-minecraft/default.nix b/services/on-demand-minecraft/default.nix index e811f39..541a624 100644 --- a/services/on-demand-minecraft/default.nix +++ b/services/on-demand-minecraft/default.nix @@ -50,6 +50,7 @@ in The internal port which the minecraft server will listen to. This port does not need to be exposed to the network. ''; + type = types.port; default = cfg.external-port + 1; }; @@ -63,6 +64,7 @@ in You may also have to set up port forwarding if you want to play with friends who are not on the same LAN. ''; + type = types.port; default = 25565; }; diff --git a/services/push-notification-api/default.nix b/services/push-notification-api/default.nix new file mode 100644 index 0000000..1897cd1 --- /dev/null +++ b/services/push-notification-api/default.nix @@ -0,0 +1,67 @@ +# Temporary definition for push-notification-api service. This will be moved +# into the flake once it's finished. + +{ pkgs, lib, config, flakeInputs, ... }: + +let + inherit (lib) mkEnableOption mkOption mkIf types; + cfg = config.my.services.push-notification-api; +in +{ + options.my.services.push-notification-api = { + enable = mkEnableOption "Push notification API"; + + package = mkOption { + description = "What package to use."; + default = flakeInputs.push-notification-api.packages.${pkgs.system}.default; + type = types.package; + }; + + host = mkOption { + description = "Host(name) to passed to server"; + type = types.nonEmptyStr; + default = "0.0.0.0"; + }; + + port = mkOption { + description = "Port to listen for requests on"; + type = types.port; + default = 8000; + }; + + openFirewall = mkEnableOption "Poke holes in the firewall to permit LAN connections."; + }; + + config = mkIf cfg.enable { + # Create a user to run the server under. + users.users.push-notification-api = { + description = "Runs daily dukse reminder"; + group = "push-notification-api"; + isSystemUser = true; + home = "/srv/push-notification-api"; + createHome = true; + }; + users.groups.push-notification-api = { }; + + # Create a service which runs the server. + systemd.services.push-notification-api = { + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "netowrk-online.target" ]; + wants = [ "network.target" ]; + + serviceConfig = { + Type = "simple"; + User = config.users.users.push-notification-api.name; + Group = config.users.users.push-notification-api.group; + WorkingDirectory = config.users.users.push-notification-api.home; + ExecStart = '' + "${cfg.package}"/bin/push-notification-api --port ${toString cfg.port} --host "${cfg.host}" + ''; + }; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.port ]; + }; + }; +} |