# SPDX-FileCopyrightText: 2020 Luke Granger-Brown # # SPDX-License-Identifier: Apache-2.0 { depot, lib, pkgs, config, ... }: { imports = [ ../lib/zfs.nix ../lib/bgp.nix ../lib/minotarproxy.nix ../lib/whitby-distributed.nix ../lib/macmini-distributed.nix ../lib/oracle-lon01-distributed.nix ../lib/quotes.bfob.gg.nix ../lib/coredns/default.nix ]; boot.initrd = { availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sr_mod" "igb" ]; network = { enable = true; ssh = { enable = true; hostKeys = ["/persist/etc/ssh/ssh_host_ed25519_key"]; authorizedKeys = map builtins.readFile config.users.users.lukegb.openssh.authorizedKeys.keyFiles; }; postCommands = '' echo "zfs load-key -a; killall zfs" >> /root/.profile ''; }; }; boot.kernelParams = [ "ip=185.198.188.29::185.198.188.28:255.255.255.254:clouvider-lon01:enp1s0f0:none" ]; boot.kernelModules = [ "kvm-intel" ]; powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; fileSystems = let zfs = device: { device = device; fsType = "zfs"; }; in { "/" = zfs "tank/local/root"; "/nix" = zfs "tank/local/nix"; "/persist" = zfs "tank/safe/persist"; "/home" = zfs "tank/safe/home"; "/boot1" = { device = "/dev/disk/by-partlabel/boota"; fsType = "vfat"; }; "/boot2" = { device = "/dev/disk/by-partlabel/bootb"; fsType = "vfat"; }; }; nix.settings.max-jobs = lib.mkDefault 8; # Use GRUB, so we can have mirrored bootloaders. boot.loader.efi.canTouchEfiVariables = true; boot.loader.grub = { enable = true; version = 2; zfsSupport = true; efiSupport = true; mirroredBoots = map (path: { inherit path; devices = ["nodev"]; efiSysMountPoint = path; }) ["/boot1" "/boot2"]; }; # Networking! networking = { hostName = "clouvider-lon01"; domain = "as205479.net"; hostId = "29aaa324"; nameservers = [ "2001:4860:4860::8888" "2001:4860:4860::8844" "8.8.8.8" "8.8.4.4" ]; defaultGateway = { address = "185.198.188.28"; interface = "br-ext"; }; defaultGateway6 = { address = "2a0a:54c0:0:17::1"; interface = "br-ext"; }; bridges.br-ext.interfaces = ["enp1s0f0"]; interfaces.br-ext = { ipv4.addresses = [{ address = "185.198.188.29"; prefixLength = 31; }]; ipv6.addresses = [{ address = "2a0a:54c0:0:17::2"; prefixLength = 126; }]; }; interfaces.lo = { ipv4.addresses = [{ address = "127.0.0.1"; prefixLength = 8; }]; ipv6.addresses = [{ address = "::1"; prefixLength = 128; }]; }; firewall = { allowPing = true; allowedTCPPorts = [ 80 443 # HTTP/nginx 1935 # RTMP/nginx 6697 # znc 34197 # factorio ]; allowedUDPPorts = [ 34197 # factorio ]; extraCommands = '' # Allow SSH on public interfaces. iptables -A INPUT -p tcp --dport 22 --dst 185.198.188.29 -j ACCEPT iptables -A INPUT -p tcp --dport 22 --dst ${config.my.ip.tailscale} -j ACCEPT ip6tables -A INPUT -p tcp --dport 22 --dst 2a0a:54c0:0:17::2 -j ACCEPT ip6tables -A INPUT -p tcp --dport 22 --dst ${config.my.ip.tailscale6} -j ACCEPT ''; }; }; my.ip.tailscale = "100.79.173.25"; my.ip.tailscale6 = "fd7a:115c:a1e0:ab12:4843:cd96:624f:ad19"; my.coredns.bind = [ "br-ext" "tailscale0" "127.0.0.1" "::1" ]; services.openssh.openFirewall = false; # allowed by networking.firewall.extraCommands services.openssh.hostKeys = [ { path = "/persist/etc/ssh/ssh_host_ed25519_key"; type = "ed25519"; } { path = "/persist/etc/ssh/ssh_host_rsa_key"; type = "rsa"; bits = 4096; } ]; users.users = { lukegb.extraGroups = [ "bird2" ]; }; users.groups = { znc-acme = { members = [ "znc" "nginx" ]; }; }; services.lukegbgp = let local = { asn = 205479; }; in { enable = true; config = { local = { routerID = "185.198.188.29"; }; export = { v4 = ["92.118.29.0/24"]; }; peering = { clouvider = { local = local // { v4 = "185.198.188.29"; v6 = "2a0a:54c0:0:17::2"; }; remote = { asn = 62240; export_community = 3000; routers = [{ v4 = "185.198.188.28"; v6 = "2a0a:54c0:0:17::1"; }]; }; }; }; }; }; services.znc = { enable = true; mutable = true; dataDir = "/persist/etc/znc"; useLegacyConfig = false; }; my.vault.acmeCertificates."znc.lukegb.com" = { hostnames = [ "znc.lukegb.com" "akiichiro.lukegb.com" ]; group = "znc-acme"; }; services.nginx = { enable = true; package = pkgs.nginxMainline; additionalModules = with pkgs.nginxModules; [ rtmp ]; appendConfig = '' rtmp_auto_push on; rtmp { server { listen 1935; chunk_size 4096; application live1 { allow publish 213.41.69.70; allow publish 37.26.186.120; allow publish 94.229.74.42; live on; record off; } } } ''; virtualHosts = { "clouvider-lon01.as205479.net" = { default = true; listen = [ {addr = "185.198.188.29"; port = 80; ssl = false;} {addr = "[2a0a:54c0:0:17::2]"; port = 80; ssl = false;} ]; locations."/.well-known/acme-challenge" = { root = "/var/lib/acme/.challenges"; }; locations."/" = { return = "301 https://$host$request_uri"; }; }; }; }; systemd.mounts = let bindMount' = dir: { unitConfig.RequiresMountsFor = dir; options = "bind"; what = "/persist${dir}"; where = dir; }; bindMountSvc = dir: svc: (bindMount' dir) // { bindsTo = [svc]; partOf = [svc]; }; bindMountSvcDynamic = dir: svc: (bindMount' "/var/lib/private/${dir}") // { requiredBy = [svc]; before = [svc]; wantedBy = ["multi-user.target"]; }; bindMount = dir: (bindMount' dir) // { wantedBy = ["multi-user.target"]; }; in [ (bindMountSvcDynamic "factorio" "factorio.service") ]; my.vault.secrets.gitlab-runner-environment = { restartUnits = ["gitlab-runner.service"]; group = "root"; template = '' {{ with secret "kv/apps/gitlab-runner" }} {{ .Data.data.environment }} {{ end }} ''; }; services.gitlab-runner = { enable = true; settings.concurrent = 1; services = { deployer = { registrationConfigFile = config.my.vault.secrets.gitlab-runner-environment.path; executor = "shell"; tagList = [ "cacher" ]; }; }; gracefulTermination = true; gracefulTimeout = "4min"; package = depot.nix.pkgs.heptapod-runner; }; users.users.gitlab-runner = { isNormalUser = true; group = "nogroup"; createHome = true; home = "/srv/gitlab-runner"; }; nix.gc.automatic = false; services.factorio = { inherit (depot.ops.secrets.factorio) username token; enable = true; package = pkgs.factorio-headless-experimental; saveName = "lukegb20220131-ws"; game-name = "Briefcase Full of Bees"; extraSettings = { admins = ["lukegb"]; auto_pause = true; only_admins_can_pause_the_game = false; game_password = depot.ops.secrets.factorioServerPassword; non_blocking_saving = true; autosave_only_on_server = true; autosave_interval = 5; autosave_slots = 60; }; }; my.quotesdb.listen = [ "185.198.188.29" "[2a0a:54c0:0:17::2]" ]; environment.systemPackages = [ depot.ops.factorio.multiworld ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; system.stateVersion = "20.09"; }