diff options
author | Linnnus <[email protected]> | 2024-02-20 19:00:53 +0100 |
---|---|---|
committer | Linnnus <[email protected]> | 2024-02-20 19:01:44 +0100 |
commit | 274e08f50faffe1b8e4a760811b0a12450eae719 (patch) | |
tree | 393449e81f21b6f6b1ea7a701cef0f740cc3b757 /hosts/ahmed | |
parent | 1bbdd3f63a9d8c46b1772cbf2ad9fd83d7ef213b (diff) |
Merge 'reorg' into 'main'
This patch moves in the reorganizational work done on the reorg branch,
mainly:
* Move host-specific modules into hosts/<host>/<module>
* Break up HM config
See the reorg branch for the individual commits.
Diffstat (limited to 'hosts/ahmed')
-rw-r--r-- | hosts/ahmed/cloudflare-proxy/default.nix | 88 | ||||
-rw-r--r-- | hosts/ahmed/configuration.nix | 43 | ||||
-rw-r--r-- | hosts/ahmed/disable-screen/default.nix | 61 | ||||
-rw-r--r-- | hosts/ahmed/duksebot/default.nix | 61 | ||||
-rw-r--r-- | hosts/ahmed/forsvarsarper/default.nix | 58 | ||||
-rw-r--r-- | hosts/ahmed/forsvarsarper/script.py | 28 | ||||
-rw-r--r-- | hosts/ahmed/git.linus.onl/about.html | 5 | ||||
-rw-r--r-- | hosts/ahmed/git.linus.onl/default.nix | 84 | ||||
-rw-r--r-- | hosts/ahmed/hellohtml.linus.onl/default.nix | 51 | ||||
-rw-r--r-- | hosts/ahmed/home/default.nix | 9 | ||||
-rw-r--r-- | hosts/ahmed/linus.onl/default.nix | 93 | ||||
-rw-r--r-- | hosts/ahmed/nofitications.linus.onl/default.nix | 24 | ||||
-rw-r--r-- | hosts/ahmed/ssh/default.nix (renamed from hosts/ahmed/ssh.nix) | 0 |
13 files changed, 575 insertions, 30 deletions
diff --git a/hosts/ahmed/cloudflare-proxy/default.nix b/hosts/ahmed/cloudflare-proxy/default.nix new file mode 100644 index 0000000..45ccaa6 --- /dev/null +++ b/hosts/ahmed/cloudflare-proxy/default.nix @@ -0,0 +1,88 @@ +# This module adds some extra configuration useful when running behid a Cloudflare Proxy. +# Mainly, it blocks all incomming conncections on relevant ports that aren't +# coming from an official CloudFlare domain. +{ + config, + lib, + pkgs, + metadata, + ... +}: let + # TODO: What happens when these get out of date??? Huh??? You little pissbaby + fileToList = x: lib.strings.splitString "\n" (builtins.readFile x); + cfipv4 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v4"; + hash = "sha256-8Cxtg7wBqwroV3Fg4DbXAMdFU1m84FTfiE5dfZ5Onns="; + }); + cfipv6 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v6"; + hash = "sha256-np054+g7rQDE3sr9U8Y/piAp89ldto3pN9K+KCNMoKk="; + }); + + IPv4Whitelist = [metadata.hosts.muhammed.ipAddress]; + IPv6Whitelist = []; +in { + config = { + # Teach NGINX how to extract the proxied IP from proxied requests. + # + # See: https://nixos.wiki/wiki/Nginx#Using_realIP_when_behind_CloudFlare_or_other_CDN + services.nginx.commonHttpConfig = let + realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};"); + in '' + ${realIpsFromList cfipv4} + ${realIpsFromList cfipv6} + real_ip_header CF-Connecting-IP; + ''; + + # Block non-Cloudflare IP addresses. + networking.firewall = let + chain = "cloudflare-whitelist"; + in { + extraCommands = let + allow-interface = lib.strings.concatMapStringsSep "\n" (i: ''ip46tables --append ${chain} --in-interface ${i} --jump RETURN''); + allow-ip = cmd: lib.strings.concatMapStringsSep "\n" (r: ''${cmd} --append ${chain} --source ${r} --jump RETURN''); + in '' + # Flush the old firewall rules. This behavior mirrors the default firewall service. + # See: https://github.com/NixOS/nixpkgs/blob/ac911bf685eecc17c2df5b21bdf32678b9f88c92/nixos/modules/services/networking/firewall-iptables.nix#L59-L66 + ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} 2>/dev/null || true + ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} 2>/dev/null || true + ip46tables --flush ${chain} || true + ip46tables --delete-chain ${chain} || true + + # Create a chain that only allows whitelisted IPs through. + ip46tables --new-chain ${chain} + + # Allow trusted interfaces through. + ${allow-interface config.networking.firewall.trustedInterfaces} + + # Allow local whitelisted IPs through + ${allow-ip "iptables" IPv4Whitelist} + ${allow-ip "ip6tables" IPv6Whitelist} + + # Allow Cloudflare's IP ranges through. + ${allow-ip "iptables" cfipv4} + ${allow-ip "ip6tables" cfipv6} + + # Everything else is dropped. + # + # TODO: I would like to use `nixos-fw-log-refuse` here, but I keep + # running into weird issues when reloading the firewall. + # Something about the table not being deleted properly. + ip46tables --append ${chain} --jump DROP + + # Inject our chain as the first check in INPUT (before nixos-fw). + # We want to capture any new incomming TCP connections. + ip46tables --insert INPUT 1 --protocol tcp --destination-port 80 --syn --jump ${chain} + ip46tables --insert INPUT 1 --protocol tcp --destination-port 443 --syn --jump ${chain} + ''; + extraStopCommands = '' + # Clean up added rulesets (${chain}). This mirrors the behavior of the + # default firewall at the time of writing. + # + # See: https://github.com/NixOS/nixpkgs/blob/ac911bf685eecc17c2df5b21bdf32678b9f88c92/nixos/modules/services/networking/firewall-iptables.nix#L218-L219 + ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} 2>/dev/null || true + ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} 2>/dev/null || true + ''; + }; + }; +} diff --git a/hosts/ahmed/configuration.nix b/hosts/ahmed/configuration.nix index e0eb202..27c35eb 100644 --- a/hosts/ahmed/configuration.nix +++ b/hosts/ahmed/configuration.nix @@ -3,12 +3,21 @@ { config, pkgs, - metadata, ... }: { imports = [ ./hardware-configuration.nix - ./ssh.nix + + ./cloudflare-proxy + ./disable-screen + ./duksebot + ./forsvarsarper + ./git.linus.onl + ./hellohtml.linus.onl + ./linus.onl + ./nofitications.linus.onl + ./ssh + ./home ]; # Create the main user. @@ -47,31 +56,11 @@ }; services.cloudflare-dyndns.domains = ["minecraft.linus.onl"]; - # Set up dukse server. Det er satme hårdt at være overduksepåmindelsesansvarlig. - services.duksebot.enable = true; - # Virtual hosts. + # Each module for a HTTP service will register a virtual host. services.nginx.enable = true; - modules."linus.onl" = { - enable = true; - useACME = true; - }; - modules."notifications.linus.onl" = { - enable = true; - useACME = true; - }; - modules."git.linus.onl" = { - enable = true; - useACME = true; - }; - modules."hellohtml.linus.onl" = { - enable = true; - useACME = true; - }; - - services.forsvarsarper.enable = true; - # Configure ACME for various HTTPS services. + # Configure ACME. This is used by various HTTP services through the NGINX virtual hosts. security.acme = { acceptTerms = true; defaults.email = "linusvejlo+${config.networking.hostName}[email protected]"; @@ -94,12 +83,6 @@ # Listen for HTTP connections. networking.firewall.allowedTCPPorts = [80 443]; - # We are running behind CF proxy. - modules.cloudflare-proxy = { - enable = true; - firewall.IPv4Whitelist = [metadata.hosts.muhammed.ipAddress]; - }; - # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions # on your system were taken. It's perfectly fine and recommended to leave diff --git a/hosts/ahmed/disable-screen/default.nix b/hosts/ahmed/disable-screen/default.nix new file mode 100644 index 0000000..638437a --- /dev/null +++ b/hosts/ahmed/disable-screen/default.nix @@ -0,0 +1,61 @@ +# This file defines some configuration options which disable the screen. This +# is only relevant because this host is an old laptop running as a server. +{ + lib, + config, + ... +}: let + inherit (lib) mkEnableOption mkOption mkIf types; + + cfg = config.services.disable-screen; +in { + options.services.disable-screen = { + enable = mkEnableOption "disable screen"; + + device-path = mkOption { + description = "Path to the device in the `/sys` file system."; + type = types.str; + example = "/sys/class/backlight/intel_backlight"; + }; + + device-unit = mkOption { + description = "The systemd device unit that corresponds to the device speciefied in `device-path`."; + type = types.str; + example = "sys-devices-pci...-intel_backligt.device"; + }; + }; + + config = mkIf cfg.enable { + # Disable sleep on lid close. + services.logind = let + lidSwitchAction = "ignore"; + in { + lidSwitchExternalPower = lidSwitchAction; + lidSwitchDocked = lidSwitchAction; + lidSwitch = lidSwitchAction; + }; + + # Don't store screen brightness between boots. We always want to turn off the + # screen. + # + # See: https://wiki.archlinux.org/title/backlight#Save_and_restore_functionality + # See: https://github.com/NixOS/nixpkgs/blob/990398921f677615c0732d704857484b84c6c888/nixos/modules/system/boot/systemd.nix#L97-L101 + systemd.suppressedSystemUnits = ["[email protected]"]; + + # FIXME: Figure out how to enable screen when on-device debugging is necessary. + # Create a new service which turns off the display on boot. + # + # See: https://nixos.wiki/wiki/Backlight#.2Fsys.2Fclass.2Fbacklight.2F... + # See: https://superuser.com/questions/851846/how-to-write-a-systemd-service-that-depends-on-a-device-being-present + systemd.services.disable-screen = { + requires = [cfg.device-unit]; + after = [cfg.device-unit]; + wantedBy = [cfg.device-unit]; + + serviceConfig.Type = "oneshot"; + script = '' + tee ${cfg.device-path}/brightness <<<0 + ''; + }; + }; +} diff --git a/hosts/ahmed/duksebot/default.nix b/hosts/ahmed/duksebot/default.nix new file mode 100644 index 0000000..f15b0ff --- /dev/null +++ b/hosts/ahmed/duksebot/default.nix @@ -0,0 +1,61 @@ +# This module defines systemd unit which runs a script that sends Discrord +# messages. I use it to notify my classmates about who's on cleaning duty. You +# are probably not interested in this. + +{ + config, + pkgs, + ... +}: let + # What script to run. + package = pkgs.duksebot; +in { + config = { + # Create a user to run the server under. + users.users.duksebot = { + description = "Runs daily dukse reminder"; + group = "duksebot"; + isSystemUser = true; + home = "/srv/duksebot"; + createHome = true; + }; + users.groups.duksebot = {}; + + age.secrets.duksebot-env = { + file = ../../../secrets/duksebot.env.age; + owner = config.users.users.duksebot.name; + group = config.users.users.duksebot.group; + mode = "0440"; + }; + + # Create a service which simply runs script. This will be invoked by our timer. + systemd.services.duksebot = { + serviceConfig = { + # We only want to run this once every time the timer triggers it. + Type = "oneshot"; + # Run as the user we created above. + User = "duksebot"; + Group = "duksebot"; + WorkingDirectory = config.users.users.duksebot.home; + }; + script = '' + # Load the secret environment variables. + export $(grep -v '^#' ${config.age.secrets.duksebot-env.path} | xargs) + # Kick off. + exec "${package}"/bin/duksebot + ''; + }; + + # Create a timer to activate our oneshot service. + systemd.timers.duksebot = { + wantedBy = ["timers.target"]; + partOf = ["duksebot.service"]; + after = ["network-online.target"]; + wants = ["network-online.target"]; + timerConfig = { + OnCalendar = "*-*-* 7:00:00"; + Unit = "duksebot.service"; + }; + }; + }; +} diff --git a/hosts/ahmed/forsvarsarper/default.nix b/hosts/ahmed/forsvarsarper/default.nix new file mode 100644 index 0000000..c1c6163 --- /dev/null +++ b/hosts/ahmed/forsvarsarper/default.nix @@ -0,0 +1,58 @@ +# This module defines an on-demand minecraft server service which turns off the +# server when it's not being used. +{ + config, + pkgs, + ... +}:{ + config = { + # Create a user to run the server under. + users.users.forsvarsarper = { + description = "Runs daily scan for tests"; + group = "forsvarsarper"; + isSystemUser = true; + home = "/srv/forsvarsarper"; + createHome = true; + }; + users.groups.forsvarsarper = {}; + + age.secrets.forsvarsarper-env = { + file = ../../../secrets/forsvarsarper.env.age; + owner = config.users.users.forsvarsarper.name; + group = config.users.users.forsvarsarper.group; + mode = "0440"; + }; + + # Create a service which simply runs script. This will be invoked by our timer. + systemd.services.forsvarsarper = { + serviceConfig = { + # We only want to run this once every time the timer triggers it. + Type = "oneshot"; + # Run as the user we created above. + User = "forsvarsarper"; + Group = "forsvarsarper"; + WorkingDirectory = config.users.users.forsvarsarper.home; + }; + script = let + python3' = pkgs.python3.withPackages (ps: [ps.requests]); + in '' + # Load the secret environment variables. + export $(grep -v '^#' ${config.age.secrets.forsvarsarper-env.path} | xargs) + # Kick off. + exec ${python3'}/bin/python3 ${./script.py} + ''; + }; + + # Create a timer to activate our oneshot service. + systemd.timers.forsvarsarper = { + wantedBy = ["timers.target"]; + partOf = ["forsvarsarper.service"]; + after = ["network-online.target"]; + wants = ["network-online.target"]; + timerConfig = { + OnCalendar = "*-*-* 8:00:00"; + Unit = "forsvarsarper.service"; + }; + }; + }; +} diff --git a/hosts/ahmed/forsvarsarper/script.py b/hosts/ahmed/forsvarsarper/script.py new file mode 100644 index 0000000..7f12508 --- /dev/null +++ b/hosts/ahmed/forsvarsarper/script.py @@ -0,0 +1,28 @@ +import requests +import os + +URL = "https://karriere.forsvaret.dk/varnepligt/varnepligten/cybervarnepligt/" +TARGET_PHRASE = "Der er på nuværende tidspunkt ikke planlagt nogen afprøvninger." + +try: + response = requests.get(URL); + print(f"Forespørgsel til {URL} gav status {response.status_code}") +except: + message = "nejj den er ødelagt" +else: + if TARGET_PHRASE in response.text: + message = "der er stadig ikke planlagt nogle afprøvninger" + else: + message = "noget har ændret sig på siden!!" + print(response.text) + +token = os.getenv("TOKEN") +data = { + "title": "forsvaret status", + "message": message, + "url": URL, +} +response = requests.post(f"https://notifications.linus.onl/api/send-notification/{token}", json=data) +print(f"Forespørgsel til at sende notifikation gav status {response.status_code}") +response.raise_for_status() + diff --git a/hosts/ahmed/git.linus.onl/about.html b/hosts/ahmed/git.linus.onl/about.html new file mode 100644 index 0000000..2d18ca4 --- /dev/null +++ b/hosts/ahmed/git.linus.onl/about.html @@ -0,0 +1,5 @@ +<p>Welcome! This is where i keep my public repositories.</p> +<br> +<br> +<p>idk.</p> +<p>what do i say here?</p> diff --git a/hosts/ahmed/git.linus.onl/default.nix b/hosts/ahmed/git.linus.onl/default.nix new file mode 100644 index 0000000..46c74e9 --- /dev/null +++ b/hosts/ahmed/git.linus.onl/default.nix @@ -0,0 +1,84 @@ +{ + config, + pkgs, + metadata, + ... +}: let + git-shell = "${pkgs.gitMinimal}/bin/git-shell"; + + # Enables HTTPS stuff. + useACME = true; + + # Where repositories will be stored. + location = "/srv/git"; +in { + config = { + # Create a user which + # See: https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server + users.users.git = { + description = "Git server user"; + isSystemUser = true; + group = "git"; + + # FIXME: Is serving the home-directory of a user (indirectly through CGit) a bad idea? + home = location; + createHome = false; + + # Restrict this user to Git-related activities. + # See: https://git-scm.com/docs/git-shell + shell = git-shell; + + # List of users who can ssh into this server and write to stuff. We add + # some restrictions on what users can do on the server. This works in + # tandem with the custom shell. + openssh.authorizedKeys.keys = + map (key: "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ${key}") + [ + metadata.hosts.muhammed.sshPubKey + ]; + }; + users.groups.git = {}; + + environment.shells = [git-shell]; + + # Create repo directory. It must be readable to NGINX. + # NOTE: If location != "/srv/git" you may want to change this! + # See: https://git.zx2c4.com/cgit/about/faq#why-doesnt-cgit-findshow-my-repo + system.activationScripts.create-cgit-scan-path = '' + mkdir -p ${location} + chown ${toString config.users.users.git.name} ${location} + chgrp ${toString config.users.groups.git.name} ${location} + chmod 755 ${location} + ''; + + # Public git viewer. + services.cgit."git.linus.onl" = { + enable = true; + scanPath = location; + settings = { + root-title = "Linus' public projects"; + root-desc = "hello yes this is the git server"; + root-readme = toString ./about.html; + }; + extraConfig = '' + readme=:README.md + readme=:README.rst + readme=:README.text + readme=:README.txt + readme=:readme.md + readme=:readme.rst + readme=:readme.text + readme=:readme.txt + ''; + }; + + # Register domain name. + services.cloudflare-dyndns.domains = ["git.linus.onl"]; + + # The CGit service creates the virtual host, but it does not enable ACME. + services.nginx.virtualHosts."git.linus.onl" = { + enableACME = useACME; + forceSSL = useACME; + }; + }; +} diff --git a/hosts/ahmed/hellohtml.linus.onl/default.nix b/hosts/ahmed/hellohtml.linus.onl/default.nix new file mode 100644 index 0000000..2d09788 --- /dev/null +++ b/hosts/ahmed/hellohtml.linus.onl/default.nix @@ -0,0 +1,51 @@ +# This module defines the HelloHTML web server. It extends the NGINX config +# with a virtual server that proxies the local HelloHTML service. + +{ ... }: let + useACME = true; +in { + config = { + # Start service listening on socket /tmp/hellohtml.sock + services.hellohtml = { + enable = true; + }; + + # Register domain name. + services.cloudflare-dyndns.domains = ["hellohtml.linus.onl"]; + + # Use NGINX as reverse proxy. + services.nginx.virtualHosts."hellohtml.linus.onl" = { + enableACME = useACME; + forceSSL = useACME; + locations."/" = rec { + proxyPass = "http://localhost:8538"; + # Disable settings that might mess with the text/event-stream response of the /listen/:id endpoint. + # NOTE: These settings work in tanden with Cloudflare Proxy settings descibed here: + # https://blog.devops.dev/implementing-server-sent-events-with-fastapi-nginx-and-cloudflare-10ede1dffc18 + extraConfig = '' + location /listen/ { + # Have to duplicate this here, as this directive is not inherited. + # See: https://blog.martinfjordvald.com/understanding-the-nginx-configuration-inheritance-model/ + # See: https://serverfault.com/q/1082562 + proxy_pass ${proxyPass}; + # Disable connection header. + # See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection + # See: https://www.nginx.com/blog/avoiding-top-10-nginx-configuration-mistakes/#no-keepalives + proxy_set_header Connection \'\'; + # Disable buffering. This is crucial for SSE to ensure that + # messages are sent immediately without waiting for a buffer to + # fill. + proxy_buffering off; + # Disable caching to ensure that all messages are sent and received + # in real-time without being cached by the proxy. + proxy_cache off; + # Set a long timeout for reading from the proxy to prevent the + # connection from timing out. You may need to adjust this value + # based on your specific requirements. + proxy_read_timeout 86400; + } + ''; + }; + }; + }; +} diff --git a/hosts/ahmed/home/default.nix b/hosts/ahmed/home/default.nix new file mode 100644 index 0000000..a031e96 --- /dev/null +++ b/hosts/ahmed/home/default.nix @@ -0,0 +1,9 @@ +# Here we extend the HM user defined in `home/default.nix`. All the global HM +# stuff is defined in there. The only imports here are specific to this host. +{...}: { + home-manager.users.linus = { + imports = [ + # empty for now + ]; + }; +} diff --git a/hosts/ahmed/linus.onl/default.nix b/hosts/ahmed/linus.onl/default.nix new file mode 100644 index 0000000..c31eb73 --- /dev/null +++ b/hosts/ahmed/linus.onl/default.nix @@ -0,0 +1,93 @@ +{ + pkgs, + lib, + ... +}: let + # The domain to serve. Also kinda embedded in the name of the module?? + domain = "linus.onl"; + + # Enable HTTPS stuff. + useACME = true; +in { + config = { + # Create a user to run the build script under. + users.users."${domain}-builder" = { + description = "builds ${domain}"; + group = "${domain}-builder"; + isSystemUser = true; + }; + users.groups."${domain}-builder" = {}; + + # Create the output directory. + system.activationScripts."${domain}-create-www" = lib.stringAfter ["var"] '' + mkdir -p /var/www/${domain} + chown ${domain}-builder /var/www/${domain} + chgrp ${domain}-builder /var/www/${domain} + chmod 0755 /var/www/${domain} + ''; + + # Create a systemd service which rebuild the site regularly. + # + # This can't be done using Nix because the site relies on the git build and + # there are some inherent difficulties with including .git/ in the + # inputSource for derivations. + # + # See: https://github.com/NixOS/nix/issues/6900 + # See: https://github.com/NixOS/nixpkgs/issues/8567 + # + # TODO: Integrate rebuilding with GitHub webhooks to rebuild on push. + systemd.services."${domain}-source" = { + description = "generate https://${domain} source"; + + serviceConfig = { + Type = "oneshot"; + User = "${domain}-builder"; + Group = "${domain}-builder"; + }; + startAt = "*-*-* *:00/5:00"; + + path = with pkgs; [ + git + rsync + coreutils-full + tcl-8_5 + gnumake + ]; + environment.TCLLIBPATH = "$TCLLIBPATH ${pkgs.tcl-cmark}/lib/tclcmark1.0"; + script = '' + set -ex + tmpdir="$(mktemp -d -t linus.onl-source.XXXXXXXXXXXX)" + cd "$tmpdir" + trap 'rm -rf $tmpdir' EXIT + # TODO: Only do minimal possible cloning + git clone https://github.com/linnnus/${domain} . + make _build + rsync --archive --delete _build/ /var/www/${domain} + ''; + + # TODO: Harden service + + # Network must be online for us to check. + after = ["network-online.target"]; + requires = ["network-online.target"]; + + # We must generate some files for NGINX to serve, so this should be run + # before NGINX. + before = ["nginx.service"]; + wantedBy = ["nginx.service"]; + }; + + # Register domain name with ddns. + services.cloudflare-dyndns.domains = [domain]; + + # Register virtual host. + services.nginx = { + virtualHosts."${domain}" = { + # NOTE: 'forceSSL' will cause an infite loop, if the cloudflare proxy does NOT connect over HTTPS. + enableACME = useACME; + forceSSL = useACME; + root = "/var/www/${domain}"; + }; + }; + }; +} diff --git a/hosts/ahmed/nofitications.linus.onl/default.nix b/hosts/ahmed/nofitications.linus.onl/default.nix new file mode 100644 index 0000000..f3ab04f --- /dev/null +++ b/hosts/ahmed/nofitications.linus.onl/default.nix @@ -0,0 +1,24 @@ +{ ... }: let + # Enable HTTPS stuff. + useACME = true; +in { + config = { + # Start the proxied service. + services.push-notification-api = { + enable = true; + }; + + # Register domain name. + services.cloudflare-dyndns.domains = ["notifications.linus.onl"]; + + # Use NGINX as reverse proxy. + services.nginx.virtualHosts."notifications.linus.onl" = { + enableACME = useACME; + forceSSL = useACME; + locations."/" = { + recommendedProxySettings = true; + proxyPass = "http://unix:/run/push-notification-api.sock"; + }; + }; + }; +} diff --git a/hosts/ahmed/ssh.nix b/hosts/ahmed/ssh/default.nix index 3c6b7ad..3c6b7ad 100644 --- a/hosts/ahmed/ssh.nix +++ b/hosts/ahmed/ssh/default.nix |