diff options
18 files changed, 693 insertions, 0 deletions
diff --git a/users/sterni/machines/.skip-subtree b/users/sterni/machines/.skip-subtree new file mode 100644 index 000000000000..a79762853edd --- /dev/null +++ b/users/sterni/machines/.skip-subtree @@ -0,0 +1 @@ +Subdirectories are manually reexposed by default.nix as the contain NixOS modules diff --git a/users/sterni/machines/default.nix b/users/sterni/machines/default.nix new file mode 100644 index 000000000000..4a859a337a22 --- /dev/null +++ b/users/sterni/machines/default.nix @@ -0,0 +1,77 @@ +{ depot, lib, pkgs, ... }: + +let + bins = depot.nix.getBins pkgs.nq [ "fq" "nq" ]; + + machines = lib.mapAttrs + (name: _: + depot.ops.nixos.nixosFor (import (./. + ("/" + name))) + ) + (lib.filterAttrs (_: type: type == "directory") (builtins.readDir ./.)); + + # TODO(sterni): share code with rebuild-system + localDeployScriptFor = { system, ... }: + pkgs.writeShellScript "local-deploy-${system.name}" '' + set -eu + nix-env -p /nix/var/nix/profiles/system --set "${system}" + "${system}/bin/switch-to-configuration" switch + ''; + + # Builds the system on the remote machine + deployScriptFor = { system, ... }@machine: + pkgs.writeShellScript "remote-deploy-${system.name}" '' + set -eu + + if [ $# != 1 ]; then + printf 'usage: %s [USER@]HOST' "$0" + exit 100 + fi + + readonly TARGET_HOST="$1" + readonly DEPLOY_DRV="${ + builtins.unsafeDiscardOutputDependency ( + # Wrapper script around localDeployScriptFor that merely starts the + # local deploy script using and nq and then waits using fq. This means + # we can't Ctrl-C the deploy and it won't be terminated by a lost + # connection. + pkgs.writeShellScript "queue-deploy-${system.name}" '' + readonly STATE_DIR="''${XDG_STATE_HOME:-$HOME/.local/state}/sterni-deploy" + mkdir -p "$STATE_DIR" + + export NQDIR="$STATE_DIR" + + "${bins.nq}" "${localDeployScriptFor machine}" + "${bins.fq}" + '' + ).drvPath + }" + + nix-copy-closure -s --gzip --to "$TARGET_HOST" "$DEPLOY_DRV" + + readonly DEPLOY_OUT="$(ssh "$TARGET_HOST" "nix-store -r '$DEPLOY_DRV'")" + + ssh "$TARGET_HOST" "$DEPLOY_OUT" + ''; + +in + +depot.nix.readTree.drvTargets ( + # this somehow becomes necessarily ugly with nixpkgs-fmt + machines // { inherit deployScriptFor; } // + + lib.mapAttrs' + (name: _: { + name = "${name}System"; + value = machines.${name}.system; + }) + machines + + // + + lib.mapAttrs' + (name: _: { + name = "${name}Deploy"; + value = deployScriptFor machines.${name}; + }) + machines +) diff --git a/users/sterni/machines/edwin/default.nix b/users/sterni/machines/edwin/default.nix new file mode 100644 index 000000000000..40700ea1e91b --- /dev/null +++ b/users/sterni/machines/edwin/default.nix @@ -0,0 +1,77 @@ +{ config, lib, pkgs, depot, ... }: + +{ + imports = [ + # Third party modules we use + "${depot.third_party.agenix.src}/modules/age.nix" + # These modules touch things related to booting (filesystems, initrd network…) + ./hardware.nix + ./network.nix + # These modules configure services, websites etc. + ./minecraft.nix + ./gopher.nix + ./http/sterni.lv.nix + ./http/code.sterni.lv.nix + ./http/flipdot.openlab-augsburg.de.nix + ./http/likely-music.sterni.lv.nix + ]; + + config = { + time.timeZone = "Europe/Berlin"; + + nixpkgs.config.allowUnfreeRedistributable = true; + nix.package = pkgs.nix_2_3; + tvl.cache.enable = true; + + services = { + journald.extraConfig = '' + SystemMaxUse=1024M + ''; + + openssh.enable = true; + }; + + security.acme = { + defaults.email = builtins.getAttr "email" ( + builtins.head ( + builtins.filter (attrs: attrs.username == "sterni") depot.ops.users + ) + ); + acceptTerms = true; + }; + + programs = { + fish.enable = true; + mosh.enable = true; + tmux.enable = true; + }; + + environment.systemPackages = [ + pkgs.weechat + pkgs.wget + pkgs.git + pkgs.stow + pkgs.htop + pkgs.foot.terminfo + pkgs.vim + ]; + + users = { + users = { + root.openssh.authorizedKeys.keys = depot.users.sterni.keys.all; + lukas = { + isNormalUser = true; + extraGroups = [ "wheel" "http" ]; + openssh.authorizedKeys.keys = depot.users.sterni.keys.all; + shell = "${pkgs.fish}/bin/fish"; + }; + }; + }; + + nix.settings.trusted-users = [ + "lukas" + ]; + + system.stateVersion = "20.09"; + }; +} diff --git a/users/sterni/machines/edwin/gopher.nix b/users/sterni/machines/edwin/gopher.nix new file mode 100644 index 000000000000..57275e13a55a --- /dev/null +++ b/users/sterni/machines/edwin/gopher.nix @@ -0,0 +1,19 @@ +{ depot, ... }: + +{ + config = { + services.spacecookie = { + enable = true; + openFirewall = true; + settings = { + hostname = "sterni.lv"; + root = depot.users.sterni.lv.gopher; + log = { + enable = true; + hide-ips = true; + hide-time = true; + }; + }; + }; + }; +} diff --git a/users/sterni/machines/edwin/hardware.nix b/users/sterni/machines/edwin/hardware.nix new file mode 100644 index 000000000000..258410894a80 --- /dev/null +++ b/users/sterni/machines/edwin/hardware.nix @@ -0,0 +1,64 @@ +{ config, lib, pkgs, depot, ... }: + +{ + config = { + boot = { + loader.grub = { + enable = true; + version = 2; + # TODO(sterni): use /dev/disk/by-id ? + devices = [ + "/dev/sda" + "/dev/sdb" + ]; + }; + + kernelModules = [ + "kvm-intel" + ]; + + initrd.availableKernelModules = [ + "ahci" + "sd_mod" + "btrfs" + "realtek" + "r8169" + ]; + }; + + boot.initrd.luks.devices = { + "crypt1".device = "/dev/disk/by-uuid/02ac34ee-be10-401b-90c2-1c6aa54c4d5f"; + "crypt2".device = "/dev/disk/by-uuid/7ce07191-e704-4aed-a60f-dfa3ce386b26"; + "crypt-swap1".device = "/dev/disk/by-uuid/fec7155c-6a65-4f25-b271-43763e4c31eb"; + "crypt-swap2".device = "/dev/disk/by-uuid/7b0a03fc-51de-4578-9811-94b00df09d88"; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-label/root"; + fsType = "btrfs"; + }; + + "/boot" = { + device = "/dev/disk/by-label/boot"; + fsType = "btrfs"; + }; + }; + + swapDevices = [ + { device = "/dev/disk/by-label/swap1"; } + { device = "/dev/disk/by-label/swap2"; } + ]; + + powerManagement.cpuFreqGovernor = "performance"; + hardware = { + enableRedistributableFirmware = true; + cpu.intel.updateMicrocode = true; + }; + + nix.settings = { + max-jobs = 2; + cores = 4; + }; + }; +} diff --git a/users/sterni/machines/edwin/http/code.sterni.lv.nix b/users/sterni/machines/edwin/http/code.sterni.lv.nix new file mode 100644 index 000000000000..6c7e73cbc24e --- /dev/null +++ b/users/sterni/machines/edwin/http/code.sterni.lv.nix @@ -0,0 +1,120 @@ +{ depot, pkgs, lib, config, ... }: + +# TODO(sterni): automatically sync repositories with upstream if needed +let + virtualHost = "code.sterni.lv"; + + repos = { + spacecookie = { + description = "gopher server (and library for Haskell)"; + }; + gopher-proxy = { + description = "Gopher over HTTP proxy"; + }; + emoji-generic = { + description = "generic emoji library for Haskell (wip)"; + }; + grav2ty = { + description = "“realistic” 2d space game"; + }; + likely-music = { + description = "experimental application for probabilistic music composition"; + }; + logbook = { + description = "file format for keeping a personal log"; + }; + sternenblog = { + description = "file based cgi blog software"; + }; + haskell-dot-time = { + description = "UTC-centric time library for haskell with dot time support"; + defaultBranch = "main"; + }; + buchstabensuppe = { + description = "toy font rendering for low pixelcount, high contrast displays"; + defaultBranch = "main"; + }; + }; + + cgitRepoEntry = name: repo: + let + repoName = repos.name or name; + path = repo.path or "${repoName}.git"; + in + lib.concatStringsSep "\n" ( + [ + "repo.url=${repoName}" + "repo.path=/srv/git/${path}" + ] + ++ lib.optional (repo ? description) "repo.desc=${repo.description}" + ++ lib.optional (repo ? defaultBranch) "repo.defbranch=${repo.defaultBranch}" + ); + + cgitHead = pkgs.writeText "cgit-head.html" '' + <style> + #summary { + max-width: 80em; + } + + #summary * { + max-width: 100%; + } + </style> + ''; + + cgitConfig = pkgs.writeText "cgitrc" '' + virtual-root=/ + + enable-http-clone=1 + clone-url=https://${virtualHost}/$CGIT_REPO_URL + + enable-blame=1 + enable-log-filecount=1 + enable-log-linecount=1 + enable-index-owner=0 + enable-blame=1 + enable-commit-graph=1 + + root-title=code + root-desc=sterni's git repositories + css=/cgit.css + head-include=${cgitHead} + + mimetype-file=${pkgs.mime-types}/etc/mime.types + + about-filter=${depot.tools.cheddar.about-filter}/bin/cheddar-about + source-filter=${depot.tools.cheddar}/bin/cheddar + readme=:README.md + readme=:readme.md + + ${builtins.concatStringsSep "\n\n" (lib.mapAttrsToList cgitRepoEntry repos)} + ''; +in + +{ + imports = [ + ./nginx.nix + ./fcgiwrap.nix + ]; + + config = { + services.nginx.virtualHosts."${virtualHost}" = { + enableACME = true; + forceSSL = true; + root = "${pkgs.cgit-pink}/cgit/"; + extraConfig = '' + try_files $uri @cgit; + + location @cgit { + include ${pkgs.nginx}/conf/fastcgi_params; + fastcgi_param SCRIPT_FILENAME ${pkgs.cgit-pink}/cgit/cgit.cgi; + fastcgi_param PATH_INFO $uri; + fastcgi_param QUERY_STRING $args; + fastcgi_param HTTP_HOST $server_name; + fastcgi_param CGIT_CONFIG ${cgitConfig}; + fastcgi_pass unix:${toString config.services.fcgiwrap.socketAddress}; + } + ''; + }; + }; +} diff --git a/users/sterni/machines/edwin/http/fcgiwrap.nix b/users/sterni/machines/edwin/http/fcgiwrap.nix new file mode 100644 index 000000000000..19696d85d413 --- /dev/null +++ b/users/sterni/machines/edwin/http/fcgiwrap.nix @@ -0,0 +1,15 @@ +{ ... }: + +{ + imports = [ + ./nginx.nix + ]; + + config.services.fcgiwrap = { + enable = true; + socketType = "unix"; + socketAddress = "/run/fcgiwrap.sock"; + user = "http"; + group = "http"; + }; +} diff --git a/users/sterni/machines/edwin/http/flipdot.openlab-augsburg.de.nix b/users/sterni/machines/edwin/http/flipdot.openlab-augsburg.de.nix new file mode 100644 index 000000000000..c86956a0a473 --- /dev/null +++ b/users/sterni/machines/edwin/http/flipdot.openlab-augsburg.de.nix @@ -0,0 +1,36 @@ +{ depot, lib, config, ... }: + +let + inherit (depot.users.sterni.external.flipdot-gschichtler) + bahnhofshalle + warteraum + nixosModule + ; +in + +{ + imports = [ + nixosModule + ./nginx.nix + ]; + + config = { + age.secrets = lib.genAttrs [ + "warteraum-salt" + "warteraum-tokens" + ] + (name: { + file = depot.users.sterni.secrets."${name}.age"; + }); + + services.flipdot-gschichtler = { + enable = true; + virtualHost = "flipdot.openlab-augsburg.de"; + packages = { + inherit bahnhofshalle warteraum; + }; + saltFile = config.age.secretsDir + "/warteraum-salt"; + tokensFile = config.age.secretsDir + "/warteraum-tokens"; + }; + }; +} diff --git a/users/sterni/machines/edwin/http/likely-music.sterni.lv.nix b/users/sterni/machines/edwin/http/likely-music.sterni.lv.nix new file mode 100644 index 000000000000..8da03ac5e6ec --- /dev/null +++ b/users/sterni/machines/edwin/http/likely-music.sterni.lv.nix @@ -0,0 +1,23 @@ +{ depot, ... }: + +let + inherit (depot.users.sterni.external.likely-music) + nixosModule + likely-music + ; +in + +{ + imports = [ + ./nginx.nix + nixosModule + ]; + + config = { + services.likely-music = { + enable = true; + virtualHost = "likely-music.sterni.lv"; + package = likely-music; + }; + }; +} diff --git a/users/sterni/machines/edwin/http/nginx.nix b/users/sterni/machines/edwin/http/nginx.nix new file mode 100644 index 000000000000..7c99cdd150e0 --- /dev/null +++ b/users/sterni/machines/edwin/http/nginx.nix @@ -0,0 +1,28 @@ +{ ... }: + +{ + config = { + users = { + users.http = { + isSystemUser = true; + group = "http"; + }; + + groups.http = { }; + }; + + services.nginx = { + enable = true; + recommendedTlsSettings = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + + user = "http"; + group = "http"; + + appendHttpConfig = '' + charset utf-8; + ''; + }; + }; +} diff --git a/users/sterni/machines/edwin/http/sterni.lv.nix b/users/sterni/machines/edwin/http/sterni.lv.nix new file mode 100644 index 000000000000..44306c75bf64 --- /dev/null +++ b/users/sterni/machines/edwin/http/sterni.lv.nix @@ -0,0 +1,16 @@ +{ ... }: + +{ + imports = [ + ./nginx.nix + ]; + + config = { + services.nginx.virtualHosts."sterni.lv" = { + enableACME = true; + forceSSL = true; + # TODO(sterni): take website from store, replace /tmp with a simple LRU thing + root = toString /srv/http; + }; + }; +} diff --git a/users/sterni/machines/edwin/minecraft.nix b/users/sterni/machines/edwin/minecraft.nix new file mode 100644 index 000000000000..6014a3d5795a --- /dev/null +++ b/users/sterni/machines/edwin/minecraft.nix @@ -0,0 +1,118 @@ +{ pkgs, depot, config, ... }: + +let + carpet = pkgs.fetchurl { + url = "https://github.com/gnembon/fabric-carpet/releases/download/1.4.44/fabric-carpet-1.16.5-1.4.44+v210714.jar"; + sha256 = "099nwspgxv7h2k3mwwmgcykmwfcb7yg1azb38fd4ravv97z4l3j8"; + }; + + carpet-extra = pkgs.fetchurl { + url = "https://github.com/gnembon/carpet-extra/releases/download/1.4.43/carpet-extra-1.16.5-1.4.43.jar"; + sha256 = "0w3gng1xyiqybm1qv4gbbsyqry3dr2ndvynx14qb59wxlw0dv5za"; + }; + + userGroup = "minecraft"; + + makeJvmOpts = megs: [ + "-Xms${toString megs}M" + "-Xmx${toString megs}M" + ]; + + whitelist = { + spreadwasser = "242a66eb-2df2-4585-9a28-ac763ad0d0f9"; + sternenseemann = "d8e48069-1905-4886-a5da-a4ee917ee254"; + }; + + rconPasswordFile = config.age.secretsDir + "/minecraft-rcon"; + + baseProperties = { + white-list = true; + allow-flight = true; + difficulty = "hard"; + function-permission-level = 4; + snooper-enabled = false; + view-distance = 12; + sync-chunk-writes = "false"; # the single biggest performance fix + max-tick-time = 6000000; # TODO(sterni): disable watchdog via carpet + }; +in + +{ + imports = [ + ../../modules/minecraft-fabric.nix + ]; + + config = { + environment.systemPackages = [ + pkgs.mcrcon + pkgs.jre + ]; + + users = { + users."${userGroup}" = { + isNormalUser = true; + openssh.authorizedKeys.keys = depot.users.sterni.keys.all; + shell = "${pkgs.fish}/bin/fish"; + }; + + groups."${userGroup}" = { }; + }; + + age.secrets = { + minecraft-rcon.file = depot.users.sterni.secrets."minecraft-rcon.age"; + }; + + services.minecraft-fabric-server = { + creative = { + enable = true; + version = "1.16.5"; + mods = [ + carpet + carpet-extra + ]; + world = config.users.users.${userGroup}.home + "/worlds/creative"; + + jvmOpts = makeJvmOpts 2048; + user = userGroup; + group = userGroup; + + inherit whitelist rconPasswordFile; + ops = whitelist; + + serverProperties = baseProperties // { + server-port = 25566; + "rcon.port" = 25576; + gamemode = "creative"; + enable-command-block = true; + motd = "storage design server"; + spawn-protection = 2; + }; + }; + + carpet = { + enable = true; + version = "1.16.5"; + mods = [ + carpet + carpet-extra + ]; + world = config.users.users.${userGroup}.home + "/worlds/carpet"; + + jvmOpts = makeJvmOpts 4096; + user = userGroup; + group = userGroup; + + inherit whitelist rconPasswordFile; + ops = whitelist; + + serverProperties = baseProperties // { + server-port = 25565; + "rcon.port" = 25575; + motd = "ich tu fleissig hustlen nenn mich bob der baumeister"; + + level-seed = 7240251176989694927; # for posterity + }; + }; + }; + }; +} diff --git a/users/sterni/machines/edwin/network.nix b/users/sterni/machines/edwin/network.nix new file mode 100644 index 000000000000..1e3d4e76f078 --- /dev/null +++ b/users/sterni/machines/edwin/network.nix @@ -0,0 +1,62 @@ +{ config, pkgs, lib, depot, ... }: + +let + ipv6 = "2a01:4f8:151:54d0::/64"; + + ipv4 = "176.9.107.207"; + gatewayv4 = "176.9.107.193"; + netmaskv4 = "255.255.255.224"; +in + +{ + config = { + boot = { + kernelParams = [ + "ip=${ipv4}::${gatewayv4}:${netmaskv4}::eth0:none" + ]; + + initrd.network = { + enable = true; + ssh = { + enable = true; + authorizedKeys = depot.users.sterni.keys.all; + hostKeys = [ + "/etc/nixos/unlock_rsa_key_openssh" + "/etc/nixos/unlock_ed25519_key_openssh" + ]; + }; + postCommands = '' + echo 'cryptsetup-askpass' >> /root/.profile + ''; + }; + }; + + networking = { + usePredictableInterfaceNames = false; + useDHCP = false; + interfaces."eth0".useDHCP = false; + + hostName = "edwin"; + + firewall = { + enable = true; + allowPing = true; + allowedTCPPorts = [ 22 80 443 ]; + }; + }; + + systemd.network = { + enable = true; + networks."eth0".extraConfig = '' + [Match] + Name = eth0 + + [Network] + Address = ${ipv6} + Gateway = fe80::1 + Address = ${ipv4}/27 + Gateway = ${gatewayv4} + ''; + }; + }; +} diff --git a/users/sterni/secrets/default.nix b/users/sterni/secrets/default.nix new file mode 100644 index 000000000000..5550103c5a66 --- /dev/null +++ b/users/sterni/secrets/default.nix @@ -0,0 +1,3 @@ +{ depot, ... }: + +depot.ops.secrets.mkSecrets ./. (import ./secrets.nix) diff --git a/users/sterni/secrets/minecraft-rcon.age b/users/sterni/secrets/minecraft-rcon.age new file mode 100644 index 000000000000..7c896861b9d8 --- /dev/null +++ b/users/sterni/secrets/minecraft-rcon.age @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 aXKGcg VELHhE9AlsAUspZj8M9zzOcjaml3/KSuNAae73TOOEk +0vpPVz2TFMK2MLxHzMVO3a9QvnU9MfYcNO+JpMRRhN8 +-> ssh-ed25519 34g70A 28ldud+S2mz83kcIkEGv5XWWOdXUN/vetsqho7kiCh4 +/P+hJqj9r3KEi0VD15yg0MHyy0XgYUU5/zpMRrLaysM +-> .-grease }}M +ennsvHEhRup8I8R23GPWlILkCIMZmAuMT2F22SQPdjU +--- e6u1rsLXltysnQqp3x73HfHLhqzTfkIV3mXaCtW1cxE +!NiAO4P&Ԏ FFRrz \ No newline at end of file diff --git a/users/sterni/secrets/secrets.nix b/users/sterni/secrets/secrets.nix new file mode 100644 index 000000000000..d2f4860ff241 --- /dev/null +++ b/users/sterni/secrets/secrets.nix @@ -0,0 +1,15 @@ +let + nonremote = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJk+KvgvI2oJTppMASNUfMcMkA2G5ZNt+HnWDzaXKLlo" + ]; + + edwin = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+OZ8f++cnvd4E2kFyn9jEoVpxi7LfjRvyQwzE8a5Ll" + ]; +in + +{ + "warteraum-salt.age".publicKeys = nonremote ++ edwin; + "warteraum-tokens.age".publicKeys = nonremote ++ edwin; + "minecraft-rcon.age".publicKeys = nonremote ++ edwin; +} diff --git a/users/sterni/secrets/warteraum-salt.age b/users/sterni/secrets/warteraum-salt.age new file mode 100644 index 000000000000..f932a881cd43 --- /dev/null +++ b/users/sterni/secrets/warteraum-salt.age Binary files differdiff --git a/users/sterni/secrets/warteraum-tokens.age b/users/sterni/secrets/warteraum-tokens.age new file mode 100644 index 000000000000..37ab46981ecb --- /dev/null +++ b/users/sterni/secrets/warteraum-tokens.age @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> ssh-ed25519 aXKGcg yHE1bla5BN1Kgows1tdeswamJQHfzGpv8fL3qZs04k0 +rR1O25EIQXctnyVsQCZO47bM44KFhmOZ7ePiecKrZ40 +-> ssh-ed25519 34g70A voVJDU9DIrT0z6X/mAi0tQqXthRZAyrzsPXOTIIzKUw +yEiIaD9jblO44/RaoiPA0mjvRToNc4Ur9GcwfG9TSVo +-> =UOH^-Z4-grease Do<;So +l0F72v4UD8r5kbpNIT2i1IUT6ttXZhuPE91H2tucMc5TKRvGDvpdJNpQ+P+XmX2M +661iYooyust5TGZsXJFHVYg +--- To85A7ohH2Sjfy8js2+JzV0c86dmDO2JCH8TK7OtVtM +Vq%n!M#`3;1wFCH'Y]-Q1m \ No newline at end of file |