about summary refs log tree commit diff
path: root/users/sterni/machines/edwin
diff options
context:
space:
mode:
Diffstat (limited to 'users/sterni/machines/edwin')
-rw-r--r--users/sterni/machines/edwin/default.nix88
-rw-r--r--users/sterni/machines/edwin/gopher.nix19
-rw-r--r--users/sterni/machines/edwin/hardware.nix64
-rw-r--r--users/sterni/machines/edwin/http/code.sterni.lv.nix262
-rw-r--r--users/sterni/machines/edwin/http/fcgiwrap.nix15
-rw-r--r--users/sterni/machines/edwin/http/flipdot.openlab-augsburg.de.nix36
-rw-r--r--users/sterni/machines/edwin/http/likely-music.sterni.lv.nix23
-rw-r--r--users/sterni/machines/edwin/http/nginx.nix28
-rw-r--r--users/sterni/machines/edwin/http/sterni.lv.nix16
-rw-r--r--users/sterni/machines/edwin/minecraft.nix121
-rw-r--r--users/sterni/machines/edwin/network.nix62
11 files changed, 734 insertions, 0 deletions
diff --git a/users/sterni/machines/edwin/default.nix b/users/sterni/machines/edwin/default.nix
new file mode 100644
index 000000000000..de34aa78afe4
--- /dev/null
+++ b/users/sterni/machines/edwin/default.nix
@@ -0,0 +1,88 @@
+{ 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.
+    ../../modules/disk-checkup.nix
+    ./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;
+      settings = {
+        trusted-public-keys = lib.mkAfter [
+          "headcounter.org:/7YANMvnQnyvcVB6rgFTdb8p5LG1OTXaO+21CaOSBzg="
+        ];
+        substituters = lib.mkAfter [
+          "https://hydra.build"
+        ];
+      };
+    };
+    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" "git" ];
+          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..7fd730285914
--- /dev/null
+++ b/users/sterni/machines/edwin/http/code.sterni.lv.nix
@@ -0,0 +1,262 @@
+{ depot, pkgs, lib, config, ... }:
+
+let
+  virtualHost = "code.sterni.lv";
+
+  repoSections = [
+    {
+      section = "active";
+      repos = {
+        spacecookie = {
+          description = "gopher server (and library for Haskell)";
+          upstream = "https://github.com/sternenseemann/spacecookie.git";
+        };
+        "mirror/depot" = {
+          description = "monorepo for the virus lounge";
+          upstream = "https://code.tvl.fyi/depot.git";
+          cgit.defbranch = "canon";
+        };
+        "mirror/flipdot-gschichtler" = {
+          description = "message queue system for OpenLab's flipdot display";
+          upstream = "https://github.com/openlab-aux/flipdot-gschichtler.git";
+        };
+        "mirror/nixpkgs" = {
+          description = "Nix packages collection";
+          upstream = "https://github.com/nixos/nixpkgs.git";
+          cgit.enable-commit-graph = "0"; # too slow
+        };
+        "mirror/vuizvui" = {
+          description = "Nix(OS) expressions used by the OpenLab and its members";
+          upstream = "https://github.com/openlab-aux/vuizvui.git";
+        };
+      };
+    }
+    {
+      section = "poc";
+      repos = {
+        emoji-generic = {
+          description = "generic emoji library for Haskell";
+          upstream = "https://github.com/sternenseemann/emoji-generic.git";
+        };
+        grav2ty = {
+          description = "“realistic” 2d space game";
+          upstream = "https://github.com/sternenseemann/grav2ty.git";
+        };
+        haskell-dot-time = {
+          description = "UTC-centric time library for haskell with dot time support";
+          cgit.defbranch = "main";
+        };
+        buchstabensuppe = {
+          description = "toy font rendering for low pixelcount, high contrast displays";
+          upstream = "https://github.com/sternenseemann/buchstabensuppe.git";
+          cgit.defbranch = "main";
+        };
+        "mirror/saneterm" = {
+          description = "modern line-oriented terminal emulator without support for TUIs";
+          upstream = "https://git.8pit.net/saneterm.git";
+        };
+      };
+    }
+    {
+      # TODO(sterni): resisort, klammeraffe, cl-ca, ponify, tinyrl
+      section = "archive";
+      repos = {
+        gopher-proxy = {
+          description = "Gopher over HTTP proxy";
+          upstream = "https://github.com/sternenseemann/gopher-proxy.git";
+        };
+        likely-music = {
+          description = "experimental application for probabilistic music composition";
+          upstream = "https://github.com/sternenseemann/likely-music.git";
+        };
+        logbook = {
+          description = "file format for keeping a personal log";
+          upstream = "https://github.com/sternenseemann/logbook.git";
+        };
+        sternenblog = {
+          description = "file based cgi blog software";
+          upstream = "https://github.com/sternenseemann/sternenblog.git";
+        };
+      };
+    }
+  ];
+
+  repoPath = name: repo: repo.path or "/srv/git/${name}.git";
+
+  cgitRepoEntry = name: repo:
+    lib.concatStringsSep "\n" (
+      [
+        "repo.url=${name}"
+        "repo.path=${repoPath name repo}"
+      ]
+      ++ lib.optional (repo ? description) "repo.desc=${repo.description}"
+      ++ lib.mapAttrsToList (n: v: "repo.${n}=${v}") repo.cgit or { }
+    );
+
+  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.sterni.lv
+    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
+
+    section-sort=0
+    ${
+      lib.concatMapStringsSep "\n" (section:
+        ''
+          section=${section.section}
+
+        ''
+        + builtins.concatStringsSep "\n\n" (lib.mapAttrsToList cgitRepoEntry section.repos)
+      ) repoSections
+    }
+  '';
+
+  /* Merge a list of attrs, but fail when the same attribute occurs twice.
+
+     Type: [ attrs ] -> attrs
+  */
+  mergeManyDistinctAttrs = lib.foldAttrs
+    (
+      val: nul:
+        if nul == null then val else throw "Every attribute name may occur only once"
+    )
+    null;
+
+  flatRepos = mergeManyDistinctAttrs
+    (builtins.map (section: section.repos) repoSections);
+
+  reposToMirror = lib.filterAttrs (_: repo: repo ? upstream) flatRepos;
+
+  # User and group name used for running the mirror scripts
+  mirroredReposOwner = "git";
+
+  # Make repo name suitable for systemd unit/timer
+  unitName = name: "mirror-${lib.strings.sanitizeDerivationName name}";
+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};
+        }
+      '';
+    };
+
+    users = {
+      users.${mirroredReposOwner} = {
+        group = mirroredReposOwner;
+        isSystemUser = true;
+      };
+
+      groups.${mirroredReposOwner} = { };
+    };
+
+
+    systemd.timers = lib.mapAttrs'
+      (
+        name: repo:
+          {
+            name = unitName name;
+            value = {
+              description = "regularly update mirror git repository ${name}";
+              wantedBy = [ "timers.target" ];
+              enable = true;
+              timerConfig = {
+                # Fire every 6h and distribute the workload over next 6h randomly
+                OnCalendar = "*-*-* 00/6:00:00";
+                AccuracySec = "6h";
+                RandomizedDelaySec = "6h";
+                Persistent = true;
+              };
+            };
+          }
+      )
+      reposToMirror;
+
+    systemd.services = lib.mapAttrs'
+      (
+        name: repo:
+          {
+            name = unitName name;
+            value = {
+              description = "mirror git repository ${name}";
+              after = [ "network.target" ];
+              script =
+                let
+                  path = repoPath name repo;
+                in
+                ''
+                  set -euo pipefail
+
+                  export PATH="${lib.makeBinPath [ pkgs.coreutils pkgs.git ]}"
+
+                  if test ! -d "${path}"; then
+                    mkdir -p "$(dirname "${path}")"
+                    git clone --mirror "${repo.upstream}" "${path}"
+                    exit 0
+                  fi
+
+                  cd "${path}"
+
+                  git fetch "${repo.upstream}" '+refs/*:refs/*' --prune
+                '';
+
+              serviceConfig = {
+                Type = "oneshot";
+                User = mirroredReposOwner;
+                Group = mirroredReposOwner;
+              };
+            };
+          }
+      )
+      reposToMirror;
+  };
+}
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..1d623f00e663
--- /dev/null
+++ b/users/sterni/machines/edwin/minecraft.nix
@@ -0,0 +1,121 @@
+{ pkgs, depot, config, ... }:
+
+let
+  carpet = pkgs.fetchurl {
+    url = "https://github.com/gnembon/fabric-carpet/releases/download/1.4.101/fabric-carpet-1.19.4-1.4.101+v230319.jar";
+    sha256 = "1zppsl3x9iaj616phrllc8hirj4f5wqdjf6f9w2nm0mkxr66z10l";
+  };
+
+  carpet-extra = pkgs.fetchurl {
+    url = "https://github.com/gnembon/carpet-extra/releases/download/1.4.100/carpet-extra-1.19.4-1.4.100.jar";
+    sha256 = "1x3jh7nds5kkda445sbcgnz5fvw42f4pq0pvarz7rf9wgkz15i8r";
+  };
+
+  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
+    enforce-secure-profile = false;
+  };
+in
+
+# TODO(sterni): regular backups of carpet world
+
+{
+  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.19.4";
+        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.19.4";
+        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}
+      '';
+    };
+  };
+}