diff options
author | Linnnus <[email protected]> | 2023-10-01 22:43:58 +0200 |
---|---|---|
committer | Linnnus <[email protected]> | 2023-10-01 23:08:32 +0200 |
commit | 7e27f6f2250bd4e0faa5d5e626dce541a8bb22e4 (patch) | |
tree | 11eb68ec0ae6e1f9cd1f4d7b645cc55e582b1873 /modules/nixos | |
parent | 241bbaf27ad990d0630b7b48f3e9858e8f42b88f (diff) |
Use alejandra formatter
Diffstat (limited to 'modules/nixos')
-rw-r--r-- | modules/nixos/cloudflare-proxy/default.nix | 47 | ||||
-rw-r--r-- | modules/nixos/disable-screen/default.nix | 51 | ||||
-rw-r--r-- | modules/nixos/duksebot/default.nix | 24 | ||||
-rw-r--r-- | modules/nixos/on-demand-minecraft/default.nix | 342 |
4 files changed, 234 insertions, 230 deletions
diff --git a/modules/nixos/cloudflare-proxy/default.nix b/modules/nixos/cloudflare-proxy/default.nix index 87d3857..216a31d 100644 --- a/modules/nixos/cloudflare-proxy/default.nix +++ b/modules/nixos/cloudflare-proxy/default.nix @@ -1,38 +1,37 @@ # This module adds some extra configuration useful when running behid a Cloudflare Proxy. # - -{ config, lib, pkgs, ... }: - -let +{ + config, + lib, + pkgs, + ... +}: let inherit (lib) mkEnableOption mkIf; cfg = config.modules.cloudflare-proxy; -in -{ +in { options.modules.cloudflare-proxy.enable = mkEnableOption "Cloudflare proxy IP extraction for NGINX"; 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};"); - fileToList = x: lib.strings.splitString "\n" (builtins.readFile x); - cfipv4 = fileToList (pkgs.fetchurl { - url = "https://www.cloudflare.com/ips-v4"; - sha256 = "0ywy9sg7spafi3gm9q5wb59lbiq0swvf0q3iazl0maq1pj1nsb7h"; - }); - cfipv6 = fileToList (pkgs.fetchurl { - url = "https://www.cloudflare.com/ips-v6"; - sha256 = "1ad09hijignj6zlqvdjxv7rjj8567z357zfavv201b9vx3ikk7cy"; - }); - in - '' - ${realIpsFromList cfipv4} - ${realIpsFromList cfipv6} - real_ip_header CF-Connecting-IP; - ''; + services.nginx.commonHttpConfig = let + realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};"); + fileToList = x: lib.strings.splitString "\n" (builtins.readFile x); + cfipv4 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v4"; + sha256 = "0ywy9sg7spafi3gm9q5wb59lbiq0swvf0q3iazl0maq1pj1nsb7h"; + }); + cfipv6 = fileToList (pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v6"; + sha256 = "1ad09hijignj6zlqvdjxv7rjj8567z357zfavv201b9vx3ikk7cy"; + }); + in '' + ${realIpsFromList cfipv4} + ${realIpsFromList cfipv6} + real_ip_header CF-Connecting-IP; + ''; # TODO: Only allow incomming HTTP{,S} requests from non-Cloudflare IPs. }; diff --git a/modules/nixos/disable-screen/default.nix b/modules/nixos/disable-screen/default.nix index b70d80d..142507d 100644 --- a/modules/nixos/disable-screen/default.nix +++ b/modules/nixos/disable-screen/default.nix @@ -1,14 +1,14 @@ # 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 +{ + lib, + config, + ... +}: let inherit (lib) mkEnableOption mkOption types; cfg = config.disable-screen; -in -{ +in { options.disable-screen = { enable = mkEnableOption "disable screen"; @@ -27,38 +27,35 @@ in config = { # Disable sleep on lid close. - services.logind = - let - lidSwitchAction = "ignore"; - in - { - lidSwitchExternalPower = lidSwitchAction; - lidSwitchDocked = lidSwitchAction; - lidSwitch = lidSwitchAction; - }; + 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]" ]; + 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 - ''; - }; + 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 index 139bdfb..b0e8ad9 100644 --- a/modules/nixos/duksebot/default.nix +++ b/modules/nixos/duksebot/default.nix @@ -1,14 +1,16 @@ # 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 +{ + config, + lib, + pkgs, + modulesPath, + ... +}: let inherit (lib) mkIf mkOption mkEnableOption types; cfg = config.services.duksebot; -in -{ +in { options.services.duksebot = { enable = mkEnableOption "duksebot daily reminder"; @@ -28,7 +30,7 @@ in home = "/srv/duksebot"; createHome = true; }; - users.groups.duksebot = { }; + users.groups.duksebot = {}; age.secrets.duksebot-env = { file = ../../../secrets/duksebot.env.age; @@ -57,10 +59,10 @@ in # 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" ]; # FIXME: redundant? + wantedBy = ["timers.target"]; + partOf = ["duksebot.service"]; + after = ["network-online.target"]; + wants = ["network-online.target"]; # FIXME: redundant? timerConfig = { # OnCalendar = "*-*-* 7:00:00"; OnCalendar = "*:0/1"; diff --git a/modules/nixos/on-demand-minecraft/default.nix b/modules/nixos/on-demand-minecraft/default.nix index 65d51c4..2df6303 100644 --- a/modules/nixos/on-demand-minecraft/default.nix +++ b/modules/nixos/on-demand-minecraft/default.nix @@ -1,14 +1,16 @@ # 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 +{ + config, + lib, + pkgs, + modulesPath, + ... +}: let inherit (lib) mkIf mkOption mkEnableOption types; cfg = config.services.on-demand-minecraft; -in -{ +in { options.services.on-demand-minecraft = { enable = mkEnableOption "local minecraft server"; @@ -103,8 +105,8 @@ in `enable-rcon` will be forced on because the're required for the server to work. ''; - type = with types; attrsOf (oneOf [ bool int str ]); - default = { }; + type = with types; attrsOf (oneOf [bool int str]); + default = {}; example = lib.literalExpression '' { difficulty = 3; @@ -117,7 +119,7 @@ in jvm-options = mkOption { description = "JVM options for the Minecraft server. List of command line arguments."; type = types.listOf lib.types.str; - default = [ "-Xmx2048M" "-Xms2048M" ]; + default = ["-Xmx2048M" "-Xms2048M"]; }; }; @@ -130,12 +132,12 @@ in group = "minecrafter"; isSystemUser = true; }; - users.groups.minecrafter = { }; + 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" ]; + bindsTo = ["minecraft-server.service"]; socketConfig = { ListenFIFO = "/run/minecraft-server.stdin"; SocketMode = "0660"; @@ -147,105 +149,111 @@ in }; # Create a service which runs the server. - systemd.services.minecraft-server = - let - server-properties = cfg.server-properties // { + systemd.services.minecraft-server = let + server-properties = + cfg.server-properties + // { server-port = cfg.internal-port; enable-rcon = true; "rcon.password" = cfg.rcon-password; }; - 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" ('' + 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 + '' + + 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 - ''; + # 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 - # incompatabilities 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 "$@" - ''; + # HACK: Each server is given its own subdirectory so + # incompatabilities 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"; - }; + 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) ]; + wantedBy = ["sockets.target"]; + requires = ["network.target"]; + listenStreams = [(toString cfg.external-port)]; }; # This service is triggerd by a TCP connection on the public @@ -254,9 +262,9 @@ in # 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" ]; + 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} ''; @@ -268,36 +276,34 @@ in 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 nc -z 127.0.0.1 ${toString cfg.internal-port} >/dev/null; then - echo "Yay! ${toString cfg.internal-port} is not 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"; - }; + 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 nc -z 127.0.0.1 ${toString cfg.internal-port} >/dev/null; then + echo "Yay! ${toString cfg.internal-port} is not 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 @@ -310,50 +316,50 @@ in }; }; - systemd.services.stop-minecraft = - let - # Script that returns true (exit code 1) if the server can be shut - # down. It uses RCON to get the player list. It does not continue if - # the server was started less than `minimum-server-lifetime` seconds - # ago. - 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)" - exit 1 - fi - - PLAYERS="$(printf "list\n" | ${pkgs.rcon.out}/bin/rcon -m -H 127.0.0.1 -p 25575 -P ${cfg.rcon-password})" - if echo "$PLAYERS" | grep "are 0 of a"; 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 - ''; - }; + systemd.services.stop-minecraft = let + # Script that returns true (exit code 1) if the server can be shut + # down. It uses RCON to get the player list. It does not continue if + # the server was started less than `minimum-server-lifetime` seconds + # ago. + 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)" + exit 1 + fi + + PLAYERS="$(printf "list\n" | ${pkgs.rcon.out}/bin/rcon -m -H 127.0.0.1 -p 25575 -P ${cfg.rcon-password})" + if echo "$PLAYERS" | grep "are 0 of a"; 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 ]; + 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."; - }]; + 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."; + } + ]; }; } |