summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/nixos/cloudflare-proxy/default.nix109
-rw-r--r--modules/nixos/default.nix19
-rw-r--r--modules/nixos/disable-screen/default.nix61
-rw-r--r--modules/nixos/duksebot/default.nix72
-rw-r--r--modules/nixos/forsvarsarper/default.nix65
-rw-r--r--modules/nixos/forsvarsarper/script.py28
-rw-r--r--modules/nixos/git.linus.onl/about.html5
-rw-r--r--modules/nixos/git.linus.onl/default.nix95
-rw-r--r--modules/nixos/graphics/default.nix37
-rw-r--r--modules/nixos/hellohtml.linus.onl/default.nix60
-rw-r--r--modules/nixos/hellohtml/default.nix121
-rw-r--r--modules/nixos/linus.onl/default.nix100
-rw-r--r--modules/nixos/nofitications.linus.onl/default.nix34
-rw-r--r--modules/nixos/on-demand-minecraft/default.nix355
14 files changed, 0 insertions, 1161 deletions
diff --git a/modules/nixos/cloudflare-proxy/default.nix b/modules/nixos/cloudflare-proxy/default.nix
deleted file mode 100644
index 657722d..0000000
--- a/modules/nixos/cloudflare-proxy/default.nix
+++ /dev/null
@@ -1,109 +0,0 @@
-# This module adds some extra configuration useful when running behid a Cloudflare Proxy.
-#
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- inherit (lib.options) mkEnableOption mkOption;
- inherit (lib.modules) mkIf;
- inherit (lib.types) listOf nonEmptyStr port;
-
- # 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=";
- });
-
- cfg = config.modules.cloudflare-proxy;
-in {
- options.modules.cloudflare-proxy = {
- enable = mkEnableOption "Cloudflare proxy IP extraction for NGINX";
-
- firewall = {
- IPv4Whitelist = mkOption {
- description = "List of IPv4 addresses (or ranges) added to the whitelist.";
- type = listOf nonEmptyStr;
- default = [];
- };
-
- IPv6Whitelist = mkOption {
- description = "List of IPv6 addresses (or ranges) added to the whitelist.";
- type = listOf nonEmptyStr;
- default = [];
- };
- };
- };
-
- config = mkIf cfg.enable {
- # 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
- # TEMP: Removed 2>/dev/null
- ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} || true
- ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} || 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" cfg.firewall.IPv4Whitelist}
- ${allow-ip "ip6tables" cfg.firewall.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
- # TEMP: Removed 2>/dev/null
- ip46tables --delete INPUT --protocol tcp --destination-port 80 --syn --jump ${chain} || true
- ip46tables --delete INPUT --protocol tcp --destination-port 443 --syn --jump ${chain} || true
- '';
- };
- };
-}
diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix
deleted file mode 100644
index 1393627..0000000
--- a/modules/nixos/default.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- # These components are
- general = {
- on-demand-minecraft = import ./on-demand-minecraft;
- cloudflare-proxy = import ./cloudflare-proxy;
- disable-screen = import ./disable-screen;
- hellohtml = import ./hellohtml;
- };
-
- personal = {
- duksebot = import ./duksebot;
- graphics = import ./graphics;
- "linus.onl" = import ./linus.onl;
- "notifications.linus.onl" = import ./nofitications.linus.onl;
- "git.linus.onl" = import ./git.linus.onl;
- "hellohtml.linus.onl" = import ./hellohtml.linus.onl;
- forsvarsarper = import ./forsvarsarper;
- };
-}
diff --git a/modules/nixos/disable-screen/default.nix b/modules/nixos/disable-screen/default.nix
deleted file mode 100644
index 638437a..0000000
--- a/modules/nixos/disable-screen/default.nix
+++ /dev/null
@@ -1,61 +0,0 @@
-# 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/modules/nixos/duksebot/default.nix b/modules/nixos/duksebot/default.nix
deleted file mode 100644
index 4c10cd8..0000000
--- a/modules/nixos/duksebot/default.nix
+++ /dev/null
@@ -1,72 +0,0 @@
-# This module defines an on-demand minecraft server service which turns off the
-# server when it's not being used.
-{
- config,
- lib,
- pkgs,
- modulesPath,
- ...
-}: let
- inherit (lib) mkIf mkOption mkEnableOption types;
-
- cfg = config.services.duksebot;
-in {
- options.services.duksebot = {
- enable = mkEnableOption "duksebot daily reminder";
-
- package = mkOption {
- description = "What package to use";
- default = pkgs.duksebot;
- type = types.package;
- };
- };
-
- config = mkIf cfg.enable {
- # 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 "${cfg.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/modules/nixos/forsvarsarper/default.nix b/modules/nixos/forsvarsarper/default.nix
deleted file mode 100644
index 7052f04..0000000
--- a/modules/nixos/forsvarsarper/default.nix
+++ /dev/null
@@ -1,65 +0,0 @@
-# This module defines an on-demand minecraft server service which turns off the
-# server when it's not being used.
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- inherit (lib) mkIf mkEnableOption;
-
- cfg = config.services.forsvarsarper;
-in {
- options.services.forsvarsarper.enable = mkEnableOption "daily scan for tests";
-
- config = mkIf cfg.enable {
- # 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/modules/nixos/forsvarsarper/script.py b/modules/nixos/forsvarsarper/script.py
deleted file mode 100644
index 7f12508..0000000
--- a/modules/nixos/forsvarsarper/script.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import requests
-import os
-
-URL = "https://karriere.forsvaret.dk/varnepligt/varnepligten/cybervarnepligt/"
-TARGET_PHRASE = "Der er p&aring; nuv&aelig;rende tidspunkt ikke planlagt nogen afpr&oslash;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/modules/nixos/git.linus.onl/about.html b/modules/nixos/git.linus.onl/about.html
deleted file mode 100644
index 2d18ca4..0000000
--- a/modules/nixos/git.linus.onl/about.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<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/modules/nixos/git.linus.onl/default.nix b/modules/nixos/git.linus.onl/default.nix
deleted file mode 100644
index 88e4f6f..0000000
--- a/modules/nixos/git.linus.onl/default.nix
+++ /dev/null
@@ -1,95 +0,0 @@
-{
- lib,
- config,
- pkgs,
- options,
- metadata,
- ...
-}: let
- inherit (lib) mkEnableOption mkOption types mkIf;
-
- git-shell = "${pkgs.gitMinimal}/bin/git-shell";
-
- cfg = config.modules."git.linus.onl";
-in {
- options.modules."git.linus.onl" = {
- enable = mkEnableOption "git.linus.onl static site";
-
- useACME = mkEnableOption "built-in HTTPS stuff";
-
- location = mkOption {
- description = "Where repositories will be stored.";
- type = types.path;
- default = "/srv/git";
- };
- };
-
- config = mkIf cfg.enable {
- # 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 = cfg.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.
- # See: https://git.zx2c4.com/cgit/about/faq#why-doesnt-cgit-findshow-my-repo
- system.activationScripts.create-cgit-scan-path = mkIf (cfg.location == options.modules."git.linus.onl".location.default) ''
- mkdir -p ${cfg.location}
- chown ${toString config.users.users.git.name} ${cfg.location}
- chgrp ${toString config.users.groups.git.name} ${cfg.location}
- chmod 755 ${cfg.location}
- '';
-
- # Public git viewer.
- services.cgit."git.linus.onl" = {
- enable = true;
- scanPath = cfg.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 = cfg.useACME;
- forceSSL = cfg.useACME;
- };
- };
-}
diff --git a/modules/nixos/graphics/default.nix b/modules/nixos/graphics/default.nix
deleted file mode 100644
index f54d043..0000000
--- a/modules/nixos/graphics/default.nix
+++ /dev/null
@@ -1,37 +0,0 @@
-# This module configures a basic graphical environment. I use this sometimes for
-# ahmed when muhammed is being repaired.
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- inherit (lib) mkEnableOption mkIf;
-
- cfg = config.modules.graphics;
-in {
- options.modules.graphics.enable = mkEnableOption "basic graphical environment";
-
- config = mkIf cfg.enable {
- services.xserver.enable = true;
-
- # Match console keyboard layout but swap capslock and escape.
- # TODO: Create a custom keymap with esc/capslock swap so console can use it.
- services.xserver.layout = config.console.keyMap;
- services.xserver.xkbOptions = "caps:swapescape";
-
- # Enable touchpad support.
- services.xserver.libinput.enable = true;
-
- services.xserver.windowManager.dwm.enable = true;
-
- # Enable sound.
- sound.enable = true;
- hardware.pulseaudio.enable = true;
-
- environment.systemPackages = with pkgs; [
- st # suckless terminal - dwm is pretty sucky without this
- dmenu # application launcher
- ];
- };
-}
diff --git a/modules/nixos/hellohtml.linus.onl/default.nix b/modules/nixos/hellohtml.linus.onl/default.nix
deleted file mode 100644
index feb56ba..0000000
--- a/modules/nixos/hellohtml.linus.onl/default.nix
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- lib,
- config,
- ...
-}: let
- inherit (lib) mkEnableOption mkIf;
-
- cfg = config.modules."hellohtml.linus.onl";
-in {
- options.modules."hellohtml.linus.onl" = {
- enable = mkEnableOption "hellohtml.linus.onl site";
-
- useACME = mkEnableOption "built-in HTTPS stuff";
- };
-
- config = mkIf cfg.enable {
- # 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 = cfg.useACME;
- forceSSL = cfg.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/modules/nixos/hellohtml/default.nix b/modules/nixos/hellohtml/default.nix
deleted file mode 100644
index cc15779..0000000
--- a/modules/nixos/hellohtml/default.nix
+++ /dev/null
@@ -1,121 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}:
-# FIXME: It is wasteful to always run the service. We should run on-demand instead.
-# This is usually achieved using SystemD sockets [4] but we are blocked on missing
-# features in Deno [1, 5].
-#
-# We have to be able to listen on a socket that's already been created by binding
-# an open file descriptor (or listening on stdin) [3]. This is not possible in Deno
-# as it is now [1, 2, 6].
-#
-# Once it becomes a possibility, we should mirror the way push-notification-api works
-# as of b9ed407 [8, 7].
-#
-# [1]: https://github.com/denoland/deno/issues/6529
-# [2]: https://github.com/denoland/deno/blob/1dd1aba2448c6c8a5a0370c4066a68aca06b859b/ext/net/ops_unix.rs#L207C34-L207C34
-# [3]: https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html#Description:~:text=Note%20that%20the,the%20service%20file).
-# [4]: https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html#Description:~:text=Socket%20units%20may%20be%20used%20to%20implement%20on%2Ddemand%20starting%20of%20services%2C%20as%20well%20as%20parallelized%20starting%20of%20services.%20See%20the%20blog%20stories%20linked%20at%20the%20end%20for%20an%20introduction.
-# [5]: https://github.com/denoland/deno/issues/14214
-# [6]: https://github.com/tokio-rs/tokio/issues/5678
-# [7]: https://github.com/benoitc/gunicorn/blob/660fd8d850f9424d5adcd50065e6060832a200d4/gunicorn/arbiter.py#L142-L155
-# [8]: https://github.com/linnnus/push-notification-api/tree/b9ed4071a4500a26b3b348a7f5fbc549e9694562
-let
- cfg = config.services.hellohtml;
-in {
- options.services.hellohtml = {
- enable = lib.mkEnableOption "hellohtml service";
-
- port = lib.mkOption {
- description = "The port where hellohtml should listen.";
- type = lib.types.port;
- default = 8538;
- };
- };
-
- config = lib.mkIf cfg.enable {
- # Create a user for running service.
- users.users.hellohtml = {
- group = "hellohtml";
- description = "Runs hellohtml service";
- isSystemUser = true;
- home = "/srv/hellohtml";
- createHome = true; # Store DB here.
- };
- users.groups.hellohtml = {};
-
- # Create hellohtml service.
- systemd.services.hellohtml = {
- description = "HelloHTML server!!!";
-
- wantedBy = ["multi-user.target"];
- after = ["network.target"];
-
- serviceConfig = let
- src = pkgs.fetchFromGitHub {
- owner = "linnnus";
- repo = "hellohtml";
- rev = "97f00500712d8551d7bbf497ec442083c63384d0";
- hash = "sha256-6nbL2B26dc83F2gSLXadyfS8etuPhhlFy9ivG5l6Tog";
- };
-
- hellohtml-vendor = pkgs.stdenv.mkDerivation {
- name = "hellohtml-vendor";
- nativeBuildInputs = [pkgs.unstable.deno];
- inherit src;
- buildCommand = ''
- # Deno wants to create cache directories.
- HOME="$(mktemp -d)"
- # Thought this wasn't necessary???
- cd $src
- # Build directory containing offline deps + import map.
- deno vendor --output=$out ./src/server.ts
- '';
- outputHashAlgo = "sha256";
- outputHashMode = "recursive";
- outputHash = "sha256-0TGLkEvJaBpI7IlTyuYRzA20Bw/TMSMz3q8wm5oPsBM";
- };
-
- hellohtml-drv = pkgs.writeShellScript "hellohtml" ''
- export HELLOHTML_DB_PATH="${config.users.users.hellohtml.home}"/hello.db
- export HELLOHTML_PORT=${toString cfg.port}
- export HELLOHTML_BASE_DIR="${src}"
-
- ${pkgs.unstable.deno}/bin/deno run \
- --allow-read=$HELLOHTML_BASE_DIR,$HELLOHTML_DB_PATH,. \
- --allow-write=$HELLOHTML_DB_PATH \
- --allow-net=0.0.0.0:$HELLOHTML_PORT \
- --allow-env \
- --no-prompt \
- --unstable-kv \
- --import-map=${hellohtml-vendor}/import_map.json \
- --no-remote \
- ${src}/src/server.ts
- '';
- in {
- Type = "simple";
- User = config.users.users.hellohtml.name;
- Group = config.users.users.hellohtml.group;
- ExecStart = "${hellohtml-drv}";
-
- # Harden service
- # NoNewPrivileges = "yes";
- # PrivateTmp = "yes";
- # PrivateDevices = "yes";
- # DevicePolicy = "closed";
- # ProtectControlGroups = "yes";
- # ProtectKernelModules = "yes";
- # ProtectKernelTunables = "yes";
- # RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
- # RestrictNamespaces = "yes";
- # RestrictRealtime = "yes";
- # RestrictSUIDSGID = "yes";
- # MemoryDenyWriteExecute = "yes";
- # LockPersonality = "yes";
- };
- };
- };
-}
diff --git a/modules/nixos/linus.onl/default.nix b/modules/nixos/linus.onl/default.nix
deleted file mode 100644
index 52703fe..0000000
--- a/modules/nixos/linus.onl/default.nix
+++ /dev/null
@@ -1,100 +0,0 @@
-{
- pkgs,
- lib,
- config,
- ...
-}: let
- inherit (lib) mkEnableOption mkOption types mkIf optional;
-
- domain = "linus.onl";
-
- cfg = config.modules."${domain}";
-in {
- options.modules."${domain}" = {
- enable = mkEnableOption "${domain} static site";
-
- useACME = mkEnableOption "built-in HTTPS stuff";
- };
-
- config = mkIf cfg.enable {
- # 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 = cfg.useACME;
- forceSSL = cfg.useACME;
- root = "/var/www/${domain}";
- };
- };
- };
-}
diff --git a/modules/nixos/nofitications.linus.onl/default.nix b/modules/nixos/nofitications.linus.onl/default.nix
deleted file mode 100644
index c050ef4..0000000
--- a/modules/nixos/nofitications.linus.onl/default.nix
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- lib,
- config,
- ...
-}: let
- inherit (lib) mkEnableOption mkIf;
-
- cfg = config.modules."notifications.linus.onl";
-in {
- options.modules."notifications.linus.onl" = {
- enable = mkEnableOption "notifications.linus.onl static site";
-
- useACME = mkEnableOption "built-in HTTPS stuff";
- };
-
- config = mkIf cfg.enable {
- 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 = cfg.useACME;
- forceSSL = cfg.useACME;
- locations."/" = {
- recommendedProxySettings = true;
- proxyPass = "http://unix:/run/push-notification-api.sock";
- };
- };
- };
-}
diff --git a/modules/nixos/on-demand-minecraft/default.nix b/modules/nixos/on-demand-minecraft/default.nix
deleted file mode 100644
index 3ccbec9..0000000
--- a/modules/nixos/on-demand-minecraft/default.nix
+++ /dev/null
@@ -1,355 +0,0 @@
-# This module defines an on-demand minecraft server service which turns off the
-# server when it's not being used.
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- inherit (lib) mkIf mkOption mkEnableOption types;
-
- cfg = config.services.on-demand-minecraft;
-in {
- options.services.on-demand-minecraft = {
- enable = mkEnableOption "local minecraft server";
-
- eula = mkOption {
- description = ''
- Whether you agree to [Mojangs EULA](https://account.mojang.com/documents/minecraft_eula).
- This option must be set to `true` to run a Minecraft™️ server (??).
- '';
- type = types.bool;
- default = false;
- };
-
- frequency-check-players = mkOption {
- description = ''
- How often to check the number of players using the server. If
- no players are using the server, it is shut down.
-
- This should be a valid value for systemd's `onCalendar`
- property.
- '';
- type = types.nonEmptyStr;
- default = "*-*-* *:*:0/20";
- };
-
- minimum-server-lifetime = mkOption {
- description = ''
- Minimum required time to pass from the server is started
- before it is allowed to be killed. This should ensure the
- server has time to start up before it is killed.
-
- The option is specified as a number of seconds.
- '';
- type = types.ints.positive;
- default = 300;
- };
-
- internal-port = mkOption {
- description = ''
- 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;
- };
-
- external-port = mkOption {
- description = ''
- The external port of the socket which is forwarded to the
- Minecraft server. This is the one users will connect to. You
- will need to add it to `networking.firewall.allowedTCPPorts`
- to open it in the firewall.
-
- 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;
- };
-
- 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 = true;
- };
-
- package = mkOption {
- description = "What Minecraft server to run.";
- default = pkgs.minecraft-server;
- type = types.package;
- };
-
- server-properties = mkOption {
- description = ''
- Minecraft server properties for the server.properties file. See
- <https://minecraft.gamepedia.com/Server.properties#Java_Edition_3>
- for documentation on these values. Note that some options like
- `server-port` will be forced on because they are required for the
- server to work.
- '';
- type = with types; attrsOf (oneOf [bool int str]);
- default = {};
- example = lib.literalExpression ''
- {
- difficulty = 3;
- gamemode = 1;
- motd = "My NixOS server!";
- }
- '';
- };
-
- jvm-options = mkOption {
- description = "JVM options for the Minecraft server. List of command line arguments.";
- type = types.listOf lib.types.str;
- default = ["-Xmx2048M" "-Xms2048M"];
- };
- };
-
- config = mkIf cfg.enable {
- # Create a user to run the server under.
- users.users.minecrafter = {
- description = "On-demand minecraft server service user";
- home = "/srv/minecrafter";
- createHome = true;
- group = "minecrafter";
- isSystemUser = true;
- };
- users.groups.minecrafter = {};
-
- # Create an internal socket and hook it up to minecraft-server process as
- # stdin. That way we can send commands to it.
- systemd.sockets.minecraft-server = {
- bindsTo = ["minecraft-server.service"];
- socketConfig = {
- ListenFIFO = "/run/minecraft-server.stdin";
- SocketMode = "0660";
- SocketUser = "minecrafter";
- SocketGroup = "minecrafter";
- RemoveOnStop = true;
- FlushPending = true;
- };
- };
-
- # Create a service which runs the server.
- systemd.services.minecraft-server = let
- server-properties =
- cfg.server-properties
- // {
- server-port = cfg.internal-port;
- };
- cfg-to-str = v:
- if builtins.isBool v
- then
- (
- if v
- then "true"
- else "false"
- )
- else toString v;
- server-properties-file = pkgs.writeText "server.properties" (''
- # server.properties managed by NixOS configuration.
- ''
- + lib.concatStringsSep "\n" (lib.mapAttrsToList
- (n: v: "${n}=${cfg-to-str v}")
- server-properties));
-
- # We don't allow eula=false anyways
- eula-file = builtins.toFile "eula.txt" ''
- # eula.txt managed by NixOS Configuration
- eula=true
- '';
-
- # HACK: Each server is given its own subdirectory so
- # incompatibilities between servers don't cause complaints.
- start-server = pkgs.writeShellScript "minecraft-server-start" ''
- # Switch to runtime directory.
- export RUNTIME_DIR="${config.users.users.minecrafter.home}/${cfg.package.name}/"
- ${pkgs.busybox}/bin/mkdir -p "$RUNTIME_DIR"
- ${pkgs.busybox}/bin/chown minecrafter:minecrafter "$RUNTIME_DIR"
- cd "$RUNTIME_DIR"
-
- # Set up/update environment for server
- ln -sf ${eula-file} eula.txt
- cp -f ${server-properties-file} server.properties
- chmod u+w server.properties # Must be writable because server regenerates it.
-
- exec ${cfg.package}/bin/minecraft-server "$@"
- '';
-
- stop-server = pkgs.writeShellScript "minecraft-server-stop" ''
- # Send the 'stop' command to the server. It listens for commands on stdin.
- echo stop > ${config.systemd.sockets.minecraft-server.socketConfig.ListenFIFO}
- # Wait for the PID of the minecraft server to disappear before
- # returning, so systemd doesn't attempt to SIGKILL it.
- while kill -0 "$1" 2> /dev/null; do
- sleep 1s
- done
- '';
- in {
- description = "Actually runs the Minecraft server";
- requires = ["minecraft-server.socket"];
- after = ["networking.target" "minecraft-server.socket"];
- wantedBy = []; # TEMP: Does this do anything?
-
- serviceConfig = {
- ExecStart = "${start-server} ${lib.escapeShellArgs cfg.jvm-options}";
- ExecStop = "${stop-server} $MAINPID";
- Restart = "always";
-
- User = "minecrafter";
- Group = "minecrafter";
-
- StandardInput = "socket";
- StandardOutput = "journal";
- StandardError = "journal";
-
- # Hardening
- CapabilityBoundingSet = [""];
- DeviceAllow = [""];
- LockPersonality = true;
- PrivateDevices = true;
- PrivateTmp = true;
- PrivateUsers = true;
- ProtectClock = true;
- ProtectControlGroups = true;
- ProtectHome = true;
- ProtectHostname = true;
- ProtectKernelLogs = true;
- ProtectKernelModules = true;
- ProtectKernelTunables = true;
- ProtectProc = "invisible";
- RestrictAddressFamilies = ["AF_INET" "AF_INET6"];
- RestrictNamespaces = true;
- RestrictRealtime = true;
- RestrictSUIDSGID = true;
- SystemCallArchitectures = "native";
- UMask = "0077";
- };
- };
-
- # This socket listens for connections on the public port and
- # triggers `listen-minecraft.service` when a connection is made.
- systemd.sockets.listen-minecraft = {
- enable = true;
- wantedBy = ["sockets.target"];
- requires = ["network.target"];
- listenStreams = [(toString cfg.external-port)];
- };
-
- # This service is triggered by a TCP connection on the public
- # port. It starts hook-minecraft.service if it is not running
- # already and waits for it to return (using `after`). Then it proxifies the TCP
- # connection to the real (local) Minecraft port.
- systemd.services.listen-minecraft = {
- enable = true;
- path = with pkgs; [systemd];
- requires = ["hook-minecraft.service" "listen-minecraft.socket"];
- after = ["hook-minecraft.service" "listen-minecraft.socket"];
- serviceConfig.ExecStart = ''
- ${pkgs.systemd.out}/lib/systemd/systemd-socket-proxyd 127.0.0.1:${toString cfg.internal-port}
- '';
- };
-
- # This starts Minecraft if required and waits for it to be
- # available over TCP to unlock the `listen-minecraft.service`
- # proxy.
- systemd.services.hook-minecraft = {
- enable = true;
- # Add tools used by scripts to path.
- path = with pkgs; [systemd libressl busybox];
- serviceConfig = let
- # Start the Minecraft server and the timer regularly
- # checking whether it should stop.
- start-mc = pkgs.writeShellScriptBin "start-mc" ''
- echo "Starting server and stop-timer..."
- systemctl start minecraft-server.service
- systemctl start stop-minecraft.timer
- '';
- # Wait for the internal port to be accessible for max.
- # 60 seconds before complaining.
- wait-tcp = pkgs.writeShellScriptBin "wait-tcp" ''
- echo "Waiting for server to start listening on port ${toString cfg.internal-port}..."
- for i in `seq 60`; do
- if ${pkgs.netcat.nc}/bin/nc -z 127.0.0.1 ${toString cfg.internal-port} >/dev/null; then
- echo "Yay! ${toString cfg.internal-port} is now available. hook-minecraft is finished."
- exit 0
- fi
- sleep 1
- done
- echo "${toString cfg.internal-port} did not become available in time."
- exit 1
- '';
- in {
- # First we start the server, then we wait for it to become available.
- ExecStart = "${start-mc}/bin/start-mc";
- ExecStartPost = "${wait-tcp}/bin/wait-tcp";
- };
- };
-
- # This timer runs the service of the same name, that checks if
- # the server needs to be stopped.
- systemd.timers.stop-minecraft = {
- enable = true;
- timerConfig = {
- OnCalendar = cfg.frequency-check-players;
- #Unit = "stop-minecraft.service";
- };
- };
-
- systemd.services.stop-minecraft = let
- # Script that returns true (exit code 0) if the server can be shut
- # down. It uses mcping to get the player list. It does not continue if
- # the server was started less than `minimum-server-lifetime` seconds
- # ago.
- #
- # NOTE: `pkgs.mcping` is declared my personal monorepo. Hopefully
- # everything just works out through the magic of flakes, but if you are
- # getting errors like "missing attribute 'mcping'" that's probably why.
- no-player-connected = pkgs.writeShellScriptBin "no-player-connected" ''
- servicestartsec="$(date -d "$(systemctl show --property=ActiveEnterTimestamp minecraft-server.service | cut -d= -f2)" +%s)"
- serviceelapsedsec="$(( $(date +%s) - servicestartsec))"
-
- if [ $serviceelapsedsec -lt ${toString cfg.minimum-server-lifetime} ]; then
- echo "Server is too young to be stopped (minimum lifetime is ${toString cfg.minimum-server-lifetime}s, current is ''${serviceelapsedsec}s)"
- exit 1
- fi
-
- PLAYERS="$(${pkgs.mcping}/bin/mcping 127.0.0.1 ${toString cfg.internal-port} | ${pkgs.jq}/bin/jq .players.online)"
- echo "There are $PLAYERS active players"
- if [ $PLAYERS -eq 0 ]; then
- exit 0
- else
- exit 1
- fi
- '';
- in {
- enable = true;
- serviceConfig.Type = "oneshot";
- script = ''
- if ${no-player-connected}/bin/no-player-connected; then
- echo "Stopping minecraft server..."
- systemctl stop minecraft-server.service
- systemctl stop hook-minecraft.service
- systemctl stop stop-minecraft.timer
- fi
- '';
- };
-
- networking.firewall = mkIf cfg.openFirewall {
- allowedUDPPorts = [cfg.external-port];
- allowedTCPPorts = [cfg.external-port];
- };
-
- assertions = [
- {
- assertion = cfg.eula;
- message = "You must agree to Mojangs EULA to run minecraft-server. Read https://account.mojang.com/documents/minecraft_eula and set `services.minecraft-server.eula` to `true` if you agree.";
- }
- ];
- };
-}