From 90281c4eac4cd25045ed80c5f8f27c74898a02b3 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 11 Apr 2021 22:50:30 +0200 Subject: refactor(ops): Split //ops/nixos into different locations Splits //ops/nixos into: * //ops/nixos.nix - utility functions for building systems * //ops/machines - shared machine definitions (read by readTree) * //ops/modules - shared NixOS modules (skipped by readTree) This simplifies working with the configuration fixpoint in whitby, and is overall a bit more in line with how NixOS systems in user folders currently work. Change-Id: I1322ec5cc76c0207c099c05d44828a3df0b3ffc1 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2931 Tested-by: BuildkiteCI Reviewed-by: sterni Reviewed-by: glittershark --- README.md | 2 +- docs/CONTRIBUTING.md | 2 +- ops/machines/all-systems.nix | 16 + ops/machines/whitby/OWNERS | 6 + ops/machines/whitby/README.md | 5 + ops/machines/whitby/default.nix | 459 +++++++++++++++++++++ ops/modules/.skip-subtree | 1 + ops/modules/README.md | 7 + ops/modules/clbot.nix | 75 ++++ ops/modules/default.nix | 2 + ops/modules/irccat.nix | 49 +++ ops/modules/monorepo-gerrit.nix | 128 ++++++ ops/modules/panettone.nix | 103 +++++ ops/modules/paroxysm.nix | 27 ++ ops/modules/quassel.nix | 76 ++++ ops/modules/smtprelay.nix | 53 +++ ops/modules/sourcegraph.nix | 51 +++ ops/modules/tvl-buildkite.nix | 48 +++ ops/modules/tvl-slapd/default.nix | 89 ++++ ops/modules/tvl-sso/default.nix | 24 ++ ops/modules/v4l2loopback.nix | 12 + ops/modules/www/b.tvl.fyi.nix | 32 ++ ops/modules/www/base.nix | 36 ++ ops/modules/www/cache.tvl.su.nix | 26 ++ ops/modules/www/cl.tvl.fyi.nix | 30 ++ ops/modules/www/code.tvl.fyi.nix | 35 ++ ops/modules/www/cs.tvl.fyi.nix | 31 ++ ops/modules/www/login.tvl.fyi.nix | 24 ++ ops/modules/www/tazj.in.nix | 40 ++ ops/modules/www/todo.tvl.fyi.nix | 25 ++ ops/modules/www/tvl.fyi.nix | 30 ++ ops/modules/www/wigglydonke.rs.nix | 15 + ops/nixos.nix | 45 ++ ops/nixos/.gitignore | 3 - ops/nixos/.skip-subtree | 1 - ops/nixos/README.md | 7 - ops/nixos/all-systems.nix | 16 - ops/nixos/clbot.nix | 75 ---- ops/nixos/default.nix | 61 --- ops/nixos/irccat.nix | 49 --- ops/nixos/monorepo-gerrit.nix | 128 ------ ops/nixos/panettone.nix | 103 ----- ops/nixos/paroxysm.nix | 27 -- ops/nixos/quassel.nix | 76 ---- ops/nixos/smtprelay.nix | 53 --- ops/nixos/sourcegraph.nix | 51 --- ops/nixos/tvl-buildkite.nix | 48 --- ops/nixos/tvl-slapd/default.nix | 89 ---- ops/nixos/tvl-sso/default.nix | 24 -- ops/nixos/v4l2loopback.nix | 12 - ops/nixos/whitby/OWNERS | 6 - ops/nixos/whitby/README.md | 5 - ops/nixos/whitby/default.nix | 458 -------------------- ops/nixos/www/b.tvl.fyi.nix | 32 -- ops/nixos/www/base.nix | 36 -- ops/nixos/www/cache.tvl.su.nix | 26 -- ops/nixos/www/cl.tvl.fyi.nix | 30 -- ops/nixos/www/code.tvl.fyi.nix | 35 -- ops/nixos/www/cs.tvl.fyi.nix | 31 -- ops/nixos/www/login.tvl.fyi.nix | 24 -- ops/nixos/www/tazj.in.nix | 40 -- ops/nixos/www/todo.tvl.fyi.nix | 25 -- ops/nixos/www/tvl.fyi.nix | 30 -- ops/nixos/www/wigglydonke.rs.nix | 15 - .../system/system/machines/chupacabra.nix | 2 +- users/tazjin/nixos/README.md | 17 +- users/tazjin/nixos/camden/default.nix | 4 +- users/tazjin/nixos/frog/default.nix | 2 +- 68 files changed, 1613 insertions(+), 1632 deletions(-) create mode 100644 ops/machines/all-systems.nix create mode 100644 ops/machines/whitby/OWNERS create mode 100644 ops/machines/whitby/README.md create mode 100644 ops/machines/whitby/default.nix create mode 100644 ops/modules/.skip-subtree create mode 100644 ops/modules/README.md create mode 100644 ops/modules/clbot.nix create mode 100644 ops/modules/default.nix create mode 100644 ops/modules/irccat.nix create mode 100644 ops/modules/monorepo-gerrit.nix create mode 100644 ops/modules/panettone.nix create mode 100644 ops/modules/paroxysm.nix create mode 100644 ops/modules/quassel.nix create mode 100644 ops/modules/smtprelay.nix create mode 100644 ops/modules/sourcegraph.nix create mode 100644 ops/modules/tvl-buildkite.nix create mode 100644 ops/modules/tvl-slapd/default.nix create mode 100644 ops/modules/tvl-sso/default.nix create mode 100644 ops/modules/v4l2loopback.nix create mode 100644 ops/modules/www/b.tvl.fyi.nix create mode 100644 ops/modules/www/base.nix create mode 100644 ops/modules/www/cache.tvl.su.nix create mode 100644 ops/modules/www/cl.tvl.fyi.nix create mode 100644 ops/modules/www/code.tvl.fyi.nix create mode 100644 ops/modules/www/cs.tvl.fyi.nix create mode 100644 ops/modules/www/login.tvl.fyi.nix create mode 100644 ops/modules/www/tazj.in.nix create mode 100644 ops/modules/www/todo.tvl.fyi.nix create mode 100644 ops/modules/www/tvl.fyi.nix create mode 100644 ops/modules/www/wigglydonke.rs.nix create mode 100644 ops/nixos.nix delete mode 100644 ops/nixos/.gitignore delete mode 100644 ops/nixos/.skip-subtree delete mode 100644 ops/nixos/README.md delete mode 100644 ops/nixos/all-systems.nix delete mode 100644 ops/nixos/clbot.nix delete mode 100644 ops/nixos/default.nix delete mode 100644 ops/nixos/irccat.nix delete mode 100644 ops/nixos/monorepo-gerrit.nix delete mode 100644 ops/nixos/panettone.nix delete mode 100644 ops/nixos/paroxysm.nix delete mode 100644 ops/nixos/quassel.nix delete mode 100644 ops/nixos/smtprelay.nix delete mode 100644 ops/nixos/sourcegraph.nix delete mode 100644 ops/nixos/tvl-buildkite.nix delete mode 100644 ops/nixos/tvl-slapd/default.nix delete mode 100644 ops/nixos/tvl-sso/default.nix delete mode 100644 ops/nixos/v4l2loopback.nix delete mode 100644 ops/nixos/whitby/OWNERS delete mode 100644 ops/nixos/whitby/README.md delete mode 100644 ops/nixos/whitby/default.nix delete mode 100644 ops/nixos/www/b.tvl.fyi.nix delete mode 100644 ops/nixos/www/base.nix delete mode 100644 ops/nixos/www/cache.tvl.su.nix delete mode 100644 ops/nixos/www/cl.tvl.fyi.nix delete mode 100644 ops/nixos/www/code.tvl.fyi.nix delete mode 100644 ops/nixos/www/cs.tvl.fyi.nix delete mode 100644 ops/nixos/www/login.tvl.fyi.nix delete mode 100644 ops/nixos/www/tazj.in.nix delete mode 100644 ops/nixos/www/todo.tvl.fyi.nix delete mode 100644 ops/nixos/www/tvl.fyi.nix delete mode 100644 ops/nixos/www/wigglydonke.rs.nix diff --git a/README.md b/README.md index b7ea0f8765..0f618bf21d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Twitter][]. [`//ops/pipelines`](https://cs.tvl.fyi/depot/-/tree/ops/pipelines). All services that we host are deployed on NixOS machines that we manage. Their -configuration is tracked in `//ops/nixos`. +configuration is tracked in `//ops/{modules,machines}`. ## Nix diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 80481d88d3..7c9d034a93 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -60,7 +60,7 @@ And `scope` should refer to some kind of logical grouping inside of the project. It does not make sense to include the full path unless it aids in disambiguating. For example, when changing the configuration of the host -`camden` at `//ops/nixos/camden` it is enough to write `feat(camden): ...`. +`whitby` at `//ops/machines/whitby` it is enough to write `feat(whitby): ...`. Please take a look at the existing commit log for examples. diff --git a/ops/machines/all-systems.nix b/ops/machines/all-systems.nix new file mode 100644 index 0000000000..493d39e06b --- /dev/null +++ b/ops/machines/all-systems.nix @@ -0,0 +1,16 @@ +{ depot, ... }: + +(with depot.ops.machines; [ + whitby +]) ++ + +(with depot.users.tazjin.nixos; [ + camden + frog + tverskoy +]) ++ + +(with depot.users.glittershark.system.system; [ + chupacabra + yeren +]) diff --git a/ops/machines/whitby/OWNERS b/ops/machines/whitby/OWNERS new file mode 100644 index 0000000000..b1b749e871 --- /dev/null +++ b/ops/machines/whitby/OWNERS @@ -0,0 +1,6 @@ +inherited: false + +# Want in on this list? Try paying! +owners: + - lukegb + - tazjin diff --git a/ops/machines/whitby/README.md b/ops/machines/whitby/README.md new file mode 100644 index 0000000000..55287c5412 --- /dev/null +++ b/ops/machines/whitby/README.md @@ -0,0 +1,5 @@ +whitby +====== + +`whitby.tvl.fyi` is our dedicated server providing continuous +integration services and other random nonsense. diff --git a/ops/machines/whitby/default.nix b/ops/machines/whitby/default.nix new file mode 100644 index 0000000000..eb5ee4ed6d --- /dev/null +++ b/ops/machines/whitby/default.nix @@ -0,0 +1,459 @@ +{ depot, lib, pkgs, ... }: # readTree options +config: # passed by module system + +let + inherit (builtins) listToAttrs; + inherit (lib) range; +in lib.fix(self: { + imports = [ + "${depot.depotPath}/ops/modules/clbot.nix" + "${depot.depotPath}/ops/modules/irccat.nix" + "${depot.depotPath}/ops/modules/monorepo-gerrit.nix" + "${depot.depotPath}/ops/modules/panettone.nix" + "${depot.depotPath}/ops/modules/paroxysm.nix" + "${depot.depotPath}/ops/modules/smtprelay.nix" + "${depot.depotPath}/ops/modules/sourcegraph.nix" + "${depot.depotPath}/ops/modules/tvl-buildkite.nix" + "${depot.depotPath}/ops/modules/tvl-slapd/default.nix" + "${depot.depotPath}/ops/modules/tvl-sso/default.nix" + "${depot.depotPath}/ops/modules/www/b.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/cache.tvl.su.nix" + "${depot.depotPath}/ops/modules/www/cl.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/code.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/cs.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/login.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/tazj.in.nix" + "${depot.depotPath}/ops/modules/www/todo.tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/tvl.fyi.nix" + "${depot.depotPath}/ops/modules/www/wigglydonke.rs.nix" + "${pkgs.path}/nixos/modules/services/web-apps/gerrit.nix" + ]; + + hardware = { + enableRedistributableFirmware = true; + cpu.amd.updateMicrocode = true; + }; + + boot = { + tmpOnTmpfs = true; + kernelModules = [ "kvm-amd" ]; + supportedFilesystems = [ "zfs" ]; + + initrd = { + availableKernelModules = [ + "igb" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sr_mod" + ]; + + # Enable SSH in the initrd so that we can enter disk encryption + # passwords remotely. + network = { + enable = true; + ssh = { + enable = true; + port = 2222; + authorizedKeys = + depot.users.tazjin.keys.all + ++ depot.users.lukegb.keys.all + ++ [ depot.users.glittershark.keys.whitby ]; + + hostKeys = [ + /etc/secrets/initrd_host_ed25519_key + ]; + }; + + # this will launch the zfs password prompt on login and kill the + # other prompt + postCommands = '' + echo "zfs load-key -a && killall zfs" >> /root/.profile + ''; + }; + }; + + kernel.sysctl = { + "net.ipv4.tcp_congestion_control" = "bbr"; + }; + + loader.grub = { + enable = true; + version = 2; + efiSupport = true; + efiInstallAsRemovable = true; + device = "/dev/disk/by-id/nvme-SAMSUNG_MZQLB1T9HAJR-00007_S439NA0N201620"; + }; + + zfs.requestEncryptionCredentials = true; + }; + + fileSystems = { + "/" = { + device = "zroot/root"; + fsType = "zfs"; + }; + + "/boot" = { + device = "/dev/disk/by-uuid/073E-7FBD"; + fsType = "vfat"; + }; + + "/nix" = { + device = "zroot/nix"; + fsType = "zfs"; + }; + + "/home" = { + device = "zroot/home"; + fsType = "zfs"; + }; + }; + + networking = { + # Glass is boring, but Luke doesn't like Wapping - the Prospect of + # Whitby, however, is quite a pleasant establishment. + hostName = "whitby"; + domain = "tvl.fyi"; + hostId = "b38ca543"; + useDHCP = false; + + # Don't use Hetzner's DNS servers. + nameservers = [ + "8.8.8.8" + "8.8.4.4" + ]; + + defaultGateway6 = { + address = "fe80::1"; + interface = "enp196s0"; + }; + + firewall.allowedTCPPorts = [ 22 80 443 4238 29418 ]; + + interfaces.enp196s0.useDHCP = true; + interfaces.enp196s0.ipv6.addresses = [ + { + address = "2a01:04f8:0242:5b21::feed:edef:beef"; + prefixLength = 64; + } + ]; + }; + + # Generate an immutable /etc/resolv.conf from the nameserver settings + # above (otherwise DHCP overwrites it): + environment.etc."resolv.conf" = with lib; { + source = pkgs.writeText "resolv.conf" '' + ${concatStringsSep "\n" (map (ns: "nameserver ${ns}") self.networking.nameservers)} + options edns0 + ''; + }; + + # Disable background git gc system-wide, as it has a tendency to break CI. + environment.etc."gitconfig".source = pkgs.writeText "gitconfig" '' + [gc] + autoDetach = false + ''; + + time.timeZone = "UTC"; + + nix = { + nrBuildUsers = 256; + maxJobs = lib.mkDefault 64; + extraOptions = '' + secret-key-files = /etc/secrets/nix-cache-privkey + ''; + + trustedUsers = [ + "grfn" + "lukegb" + "tazjin" + "sterni" + ]; + + sshServe = { + enable = true; + keys = with depot.users; + tazjin.keys.all + ++ lukegb.keys.all + ++ [ glittershark.keys.whitby ] + ++ sterni.keys.all + ; + }; + }; + + programs.mtr.enable = true; + programs.mosh.enable = true; + services.openssh = { + enable = true; + passwordAuthentication = false; + challengeResponseAuthentication = false; + }; + + # Run a handful of Buildkite agents to support parallel builds. + services.depot.buildkite = { + enable = true; + agentCount = 32; + }; + + # Start a local SMTP relay to Gmail (used by gerrit) + services.depot.smtprelay = { + enable = true; + args = { + listen = ":2525"; + remote_host = "smtp.gmail.com:587"; + remote_auth = "plain"; + remote_user = "tvlbot@tazj.in"; + }; + }; + + # Start the Gerrit->IRC bot + services.depot.clbot = { + enable = true; + + # Almost all configuration values are already correct (well, duh), + # see //fun/clbot for details. + flags = { + gerrit_host = "cl.tvl.fyi:29418"; + gerrit_ssh_auth_username = "clbot"; + gerrit_ssh_auth_key = "/etc/secrets/clbot-key"; + irc_server = "znc.lukegb.com:6697"; + + notify_branches = "canon,refs/meta/config"; + notify_repo = "depot"; + + # This secret is read from an environment variable, which is + # populated from /etc/secrets/clbot + irc_pass = "$CLBOT_PASS"; + }; + + channels = [ + "##tvl" + "##tvl-dev" + ]; + }; + + services.depot = { + # Run a SourceGraph code search instance + sourcegraph.enable = true; + + # Run the Panettone issue tracker + panettone = { + enable = true; + dbUser = "panettone"; + dbName = "panettone"; + secretsFile = "/etc/secrets/panettone"; + irccatChannel = "##tvl,##tvl-dev"; + }; + + # Run the first cursed bot (quote bot) + paroxysm.enable = true; + + # Run irccat to forward messages to IRC + irccat = { + enable = true; + config = { + tcp.listen = ":4722"; # "ircc" + irc = { + server = "chat.freenode.net:6697"; + tls = true; + nick = "tvlbot"; + realname = "TVL Bot"; + channels = [ + "##tvl" + "##tvl-dev" + ]; + }; + }; + }; + }; + + services.postgresql = { + enable = true; + enableTCPIP = true; + + authentication = lib.mkForce '' + local all all trust + host all all 127.0.0.1/32 password + host all all ::1/128 password + hostnossl all all 127.0.0.1/32 password + hostnossl all all ::1/128 password + ''; + + ensureDatabases = [ + "panettone" + ]; + + ensureUsers = [{ + name = "panettone"; + ensurePermissions = { + "DATABASE panettone" = "ALL PRIVILEGES"; + }; + }]; + }; + + services.postgresqlBackup = { + enable = true; + databases = [ + "tvldb" + "panettone" + ]; + }; + + services.nix-serve = { + enable = true; + port = 6443; + secretKeyFile = "/etc/secrets/nix-cache-key.sec"; + bindAddress = "localhost"; + }; + + environment.systemPackages = with pkgs; [ + bb + curl + emacs-nox + git + htop + nano + rxvt_unicode.terminfo + vim + zfs + zfstools + ]; + + # Run cgit for the depot. The onion here is nginx(thttpd(cgit)). + systemd.services.cgit = { + wantedBy = [ "multi-user.target" ]; + script = "${depot.web.cgit-taz}/bin/cgit-launch"; + + serviceConfig = { + Restart = "on-failure"; + User = "git"; + Group = "git"; + }; + }; + + # Regularly back up whitby to Google Cloud Storage. + systemd.services.restic = { + description = "Backups to Google Cloud Storage"; + script = "${pkgs.restic}/bin/restic backup /var/lib/gerrit /var/backup/postgresql"; + + environment = { + GOOGLE_PROJECT_ID = "tazjins-infrastructure"; + GOOGLE_APPLICATION_CREDENTIALS = "/var/backup/restic/gcp-key.json"; + RESTIC_REPOSITORY = "gs:tvl-fyi-backups:/whitby"; + RESTIC_PASSWORD_FILE = "/var/backup/restic/secret"; + RESTIC_CACHE_DIR = "/var/backup/restic/cache"; + RESTIC_EXCLUDE_FILE = builtins.toFile "exclude-files" '' + /var/lib/gerrit/tmp + ''; + }; + }; + + systemd.timers.restic = { + wantedBy = [ "multi-user.target" ]; + timerConfig.OnCalendar = "hourly"; + }; + + services.journaldriver = { + enable = true; + googleCloudProject = "tvl-fyi"; + logStream = "whitby"; + applicationCredentials = "/var/lib/journaldriver/key.json"; + }; + + security.sudo.extraRules = [ + { + groups = ["wheel"]; + commands = [{ command = "ALL"; options = ["NOPASSWD"]; }]; + } + ]; + + users = { + users.tazjin = { + isNormalUser = true; + extraGroups = [ "git" "wheel" ]; + shell = pkgs.fish; + openssh.authorizedKeys.keys = depot.users.tazjin.keys.all; + }; + + users.lukegb = { + isNormalUser = true; + extraGroups = [ "git" "wheel" ]; + openssh.authorizedKeys.keys = depot.users.lukegb.keys.all; + }; + + users.grfn = { + isNormalUser = true; + extraGroups = [ "git" "wheel" ]; + openssh.authorizedKeys.keys = [ + depot.users.glittershark.keys.whitby + ]; + }; + + users.isomer = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.isomer.keys.all; + }; + + users.riking = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.riking.keys.u2f ++ depot.users.riking.keys.passworded; + }; + + users.edef = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.edef.keys.all; + }; + + users.qyliss = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.qyliss.keys.all; + }; + + users.eta = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.eta.keys.whitby; + }; + + users.cynthia = { + isNormalUser = true; # I'm normal OwO :3 + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.cynthia.keys.all; + }; + + users.firefly = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.firefly.keys.whitby; + }; + + users.sterni = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.sterni.keys.all; + }; + + users.flokli = { + isNormalUser = true; + extraGroups = [ "git" ]; + openssh.authorizedKeys.keys = depot.users.flokli.keys.all; + }; + + # Set up a user & group for git shenanigans + groups.git = {}; + users.git = { + group = "git"; + isNormalUser = false; + createHome = true; + home = "/var/lib/git"; + }; + }; + + security.acme = { + acceptTerms = true; + email = "certs@tvl.fyi"; + }; + + system.stateVersion = "20.03"; +}) diff --git a/ops/modules/.skip-subtree b/ops/modules/.skip-subtree new file mode 100644 index 0000000000..09520f8c83 --- /dev/null +++ b/ops/modules/.skip-subtree @@ -0,0 +1 @@ +NixOS modules are not readTree compatible. diff --git a/ops/modules/README.md b/ops/modules/README.md new file mode 100644 index 0000000000..595b4c3344 --- /dev/null +++ b/ops/modules/README.md @@ -0,0 +1,7 @@ +NixOS modules +============= + +This folder contains various NixOS modules shared by our NixOS +configurations. + +It is not read by `readTree`. diff --git a/ops/modules/clbot.nix b/ops/modules/clbot.nix new file mode 100644 index 0000000000..ad33e25a4d --- /dev/null +++ b/ops/modules/clbot.nix @@ -0,0 +1,75 @@ +# Module that configures CLBot, our Gerrit->IRC info bridge. +{ depot, config, lib, pkgs, ... }: + +let + inherit (builtins) attrValues concatStringsSep mapAttrs readFile; + inherit (pkgs) runCommandNoCC; + + inherit (lib) + listToAttrs + mkEnableOption + mkIf + mkOption + removeSuffix + types; + + description = "Bot to forward CL notifications"; + cfg = config.services.depot.clbot; + + mkFlags = flags: + concatStringsSep " " + (attrValues (mapAttrs (key: value: "-${key} \"${toString value}\"") flags)); + + # Escapes a unit name for use in systemd + systemdEscape = name: removeSuffix "\n" (readFile (runCommandNoCC "unit-name" {} '' + ${pkgs.systemd}/bin/systemd-escape '${name}' >> $out + '')); + + mkUnit = flags: channel: { + name = "clbot-${systemdEscape channel}"; + value = { + description = "${description} to ${channel}"; + wantedBy = [ "multi-user.target" ]; + + script = "${depot.fun.clbot}/bin/clbot ${mkFlags (cfg.flags // { + irc_channel = channel; + })} -alsologtostderr"; + + serviceConfig = { + User = "clbot"; + EnvironmentFile = "/etc/secrets/clbot"; + Restart = "always"; + }; + }; + }; +in { + options.services.depot.clbot = { + enable = mkEnableOption description; + + flags = mkOption { + type = types.attrsOf types.str; + description = "Key value pairs for command line flags"; + }; + + channels = mkOption { + type = with types; listOf str; + description = "Channels in which to post (generates one unit per channel)"; + }; + }; + + config = mkIf cfg.enable { + # This does not use DynamicUser because we need to make some files + # (notably the SSH private key) readable by this user outside of + # the module. + users = { + groups.clbot = {}; + + users.clbot = { + group = "clbot"; + isNormalUser = false; + }; + }; + + systemd.services = listToAttrs (map (mkUnit cfg.flags) cfg.channels); + }; +} diff --git a/ops/modules/default.nix b/ops/modules/default.nix new file mode 100644 index 0000000000..8bdfecdf41 --- /dev/null +++ b/ops/modules/default.nix @@ -0,0 +1,2 @@ +# Make readTree happy at this level. +_: {} diff --git a/ops/modules/irccat.nix b/ops/modules/irccat.nix new file mode 100644 index 0000000000..e4b30b7355 --- /dev/null +++ b/ops/modules/irccat.nix @@ -0,0 +1,49 @@ +{ depot, config, lib, pkgs, ... }: + +let + cfg = config.services.depot.irccat; + description = "irccat - forward messages to IRC"; + + # irccat expects to read its configuration from the *current + # directory*, and its configuration contains secrets. + # + # To make this work we construct the JSON configuration file and + # then recursively merge it with an on-disk secret using jq on + # service launch. + configJson = pkgs.writeText "irccat.json" (builtins.toJSON cfg.config); + configMerge = pkgs.writeShellScript "merge-irccat-config" '' + if [ ! -f "/etc/secrets/irccat.json" ]; then + echo "irccat secrets file is missing" + exit 1 + fi + + # jq's * is the recursive merge operator + ${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${configJson} /etc/secrets/irccat.json \ + > /var/lib/irccat/irccat.json + ''; +in { + options.services.depot.irccat = { + enable = lib.mkEnableOption description; + + config = lib.mkOption { + type = lib.types.attrs; # varying value types + description = "Configuration structure (unchecked!)"; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.irccat = { + inherit description; + preStart = "${configMerge}"; + script = "${depot.third_party.irccat}/bin/irccat"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + DynamicUser = true; + StateDirectory = "irccat"; + WorkingDirectory = "/var/lib/irccat"; + Restart = "always"; + }; + }; + }; +} diff --git a/ops/modules/monorepo-gerrit.nix b/ops/modules/monorepo-gerrit.nix new file mode 100644 index 0000000000..eaea386ecd --- /dev/null +++ b/ops/modules/monorepo-gerrit.nix @@ -0,0 +1,128 @@ +# Gerrit configuration for the TVL monorepo +{ depot, pkgs, config, lib, ... }: + +let + cfg = config.services.gerrit; + gerritHooks = pkgs.runCommandNoCC "gerrit-hooks" {} '' + mkdir -p $out + ln -s ${depot.ops.besadii}/bin/besadii $out/ref-updated + ''; +in { + services.gerrit = { + enable = true; + listenAddress = "[::]:4778"; # 4778 - grrt + serverId = "4fdfa107-4df9-4596-8e0a-1d2bbdd96e36"; + builtinPlugins = [ + "download-commands" + "hooks" + ]; + + plugins = with depot.third_party.gerrit_plugins; [ + owners + oauth + depot.ops.gerrit-tvl + ]; + + package = depot.third_party.gerrit; + + jvmHeapLimit = "4g"; + + settings = { + core.packedGitLimit = "100m"; + log.jsonLogging = true; + log.textLogging = false; + sshd.advertisedAddress = "code.tvl.fyi:29418"; + hooks.path = "${gerritHooks}"; + cache.web_sessions.maxAge = "3 months"; + plugins.allowRemoteAdmin = false; + change.enableAttentionSet = true; + change.enableAssignee = false; + + # Configures gerrit for being reverse-proxied by nginx as per + # https://gerrit-review.googlesource.com/Documentation/config-reverseproxy.html + gerrit = { + canonicalWebUrl = "https://cl.tvl.fyi"; + docUrl = "/Documentation"; + }; + + httpd.listenUrl = "proxy-https://${cfg.listenAddress}"; + + download.command = [ + "checkout" + "cherry_pick" + "format_patch" + "pull" + ]; + + # Configure for cgit. + gitweb = { + type = "custom"; + url = "https://code.tvl.fyi"; + project = "/"; + revision = "/commit/?id=\${commit}"; + branch = "/log/?h=\${branch}"; + tag = "/tag/?h=\${tag}"; + roottree = "/tree/?h=\${commit}"; + file = "/tree/\${file}?h=\${commit}"; + filehistory = "/log/\${file}?h=\${branch}"; + linkname = "cgit"; + }; + + # Auto-link panettone bug links + commentlink.panettone = { + match = "b/(\\\\d+)"; + html = "b/$1"; + }; + + # Auto-link other CLs + commentlink.gerrit = { + match = "cl/(\\\\d+)"; + html = "cl/$1"; + }; + + # Configures integration with CAS, which then integrates with a variety + # of backends. + auth.type = "OAUTH"; + plugin.gerrit-oauth-provider-cas-oauth = { + root-url = "https://login.tvl.fyi"; + client-id = "OAUTH-TVL-gerrit-Fv0d8Aizz5"; + # client-secret is set in /var/lib/gerrit/etc/secure.config. + }; + + # Use Gerrit's built-in HTTP passwords, rather than trying to use the + # password against the backing OAuth provider. + auth.gitBasicAuthPolicy = "HTTP"; + + # Email sending (emails are relayed via the tazj.in domain's + # GSuite currently). + # + # Note that sendemail.smtpPass is stored in + # $site_path/etc/secure.config and is *not* controlled by Nix. + # + # Receiving email is not currently supported. + sendemail = { + enable = true; + html = false; + connectTimeout = "10sec"; + from = "TVL Code Review "; + includeDiff = true; + smtpEncryption = "none"; + smtpServer = "localhost"; + smtpServerPort = 2525; + }; + }; + }; + + systemd.services.gerrit = { + serviceConfig = { + # There seems to be no easy way to get `DynamicUser` to play + # well with other services (e.g. by using SupplementaryGroups, + # which seem to have no effect) so we force the DynamicUser + # setting for the Gerrit service to be disabled and reuse the + # existing 'git' user. + DynamicUser = lib.mkForce false; + User = "git"; + Group = "git"; + }; + }; +} diff --git a/ops/modules/panettone.nix b/ops/modules/panettone.nix new file mode 100644 index 0000000000..51a7468578 --- /dev/null +++ b/ops/modules/panettone.nix @@ -0,0 +1,103 @@ +{ depot, config, lib, pkgs, ... }: + +let + cfg = config.services.depot.panettone; +in { + options.services.depot.panettone = with lib; { + enable = mkEnableOption "Panettone issue tracker"; + + port = mkOption { + description = "Port on which Panettone should listen"; + type = types.int; + default = 7268; + }; + + dbHost = mkOption { + description = "Postgresql host to connect to for Panettone"; + type = types.str; + default = "localhost"; + }; + + dbName = mkOption { + description = "Name of the database for Panettone"; + type = types.str; + default = "panettone"; + }; + + dbUser = mkOption { + description = "Name of the database user for Panettone"; + type = types.str; + default = "panettone"; + }; + + secretsFile = mkOption { + description = '' + Path to a file containing secrets, in the format accepted + by systemd's EnvironmentFile + ''; + type = types.str; + }; + + irccatHost = mkOption { + description = "Hostname for the irccat instance"; + type = types.str; + default = "localhost"; + }; + + irccatPort = mkOption { + description = "Port for the irccat instance"; + type = types.int; + default = 4722; + }; + + irccatChannel = mkOption { + description = "IRC channels to post to via irccat"; + type = types.str; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [{ + assertion = + cfg.dbHost != "localhost" || config.services.postgresql.enable; + message = "Panettone requires a postgresql database"; + } { + assertion = + cfg.dbHost != "localhost" || config.services.postgresql.enableTCPIP; + message = "Panettone can only connect to the postgresql database over TCP"; + } { + assertion = + cfg.dbHost != "localhost" || (lib.any + (user: user.name == cfg.dbUser) + config.services.postgresql.ensureUsers); + message = "Panettone requires a database user"; + } { + assertion = + cfg.dbHost != "localhost" || (lib.any + (db: db == cfg.dbName) + config.services.postgresql.ensureDatabases); + message = "Panettone requires a database"; + }]; + + systemd.services.panettone = { + wantedBy = [ "multi-user.target" ]; + script = "${depot.web.panettone}/bin/panettone"; + + serviceConfig = { + DynamicUser = true; + Restart = "always"; + EnvironmentFile = cfg.secretsFile; + }; + + environment = { + PANETTONE_PORT = toString cfg.port; + PGHOST = "localhost"; + PGUSER = cfg.dbUser; + PGDATABASE = cfg.dbName; + IRCCATHOST = cfg.irccatHost; + IRCCATPORT = toString cfg.irccatPort; + ISSUECHANNEL = cfg.irccatChannel; + }; + }; + }; +} diff --git a/ops/modules/paroxysm.nix b/ops/modules/paroxysm.nix new file mode 100644 index 0000000000..cd9cd3866e --- /dev/null +++ b/ops/modules/paroxysm.nix @@ -0,0 +1,27 @@ +{ depot, config, lib, pkgs, ... }: + +let + cfg = config.services.depot.paroxysm; + description = "TVL's majestic IRC bot"; +in { + options.services.depot.paroxysm.enable = lib.mkEnableOption description; + + config = lib.mkIf cfg.enable { + systemd.services.paroxysm = { + inherit description; + script = "${depot.fun.paroxysm}/bin/paroxysm"; + wantedBy = [ "multi-user.target" ]; + + environment = { + PARX_DATABASE_URL = "postgresql://tvldb:tvldb@localhost/tvldb"; + PARX_IRC_CONFIG_PATH = "/var/lib/paroxysm/irc.toml"; + }; + + serviceConfig = { + DynamicUser = true; + StateDirectory = "paroxysm"; + Restart = "always"; + }; + }; + }; +} diff --git a/ops/modules/quassel.nix b/ops/modules/quassel.nix new file mode 100644 index 0000000000..df26a39455 --- /dev/null +++ b/ops/modules/quassel.nix @@ -0,0 +1,76 @@ +# A more modern module for running Quassel. +{ config, lib, pkgs, ... }: + +let + cfg = config.services.depot.quassel; + quasselDaemon = pkgs.quassel.override { + monolithic = false; + enableDaemon = true; + withKDE = false; + }; +in { + options.services.depot.quassel = with lib; { + enable = mkEnableOption "Quassel IRC daemon"; + + acmeHost = mkOption { + description = "ACME host to use for the Quassel TLS certificate"; + type = lib.types.str; + }; + + bindAddresses = mkOption { + description = "Addresses Quassel will bind to/listen on"; + default = [ "127.0.0.1" ]; + }; + + logLevel = mkOption { + description = "Log level for Quassel Core"; + default = "Info"; + type = lib.types.enum [ + "Debug" + "Info" + "Warning" + "Error" + ]; + }; + + port = mkOption { + default = 6698; + description = '' + The port number the Quassel daemon will be listening to. + ''; + }; + }; + + config = with lib; mkIf cfg.enable { + systemd.services.quassel = { + description = "Quassel IRC daemon"; + wantedBy = [ "multi-user.target" ]; + + script = concatStringsSep " " [ + "${quasselDaemon}/bin/quasselcore" + "--listen=${concatStringsSep "," cfg.bindAddresses}" + "--port=${toString cfg.port}" + "--configdir=/var/lib/quassel" + "--require-ssl" + "--ssl-cert=/var/lib/acme/${cfg.acmeHost}/full.pem" + "--loglevel=${cfg.logLevel}" + ]; + + serviceConfig = { + Restart = "always"; + User = "quassel"; + Group = "quassel"; + StateDirectory = "quassel"; + }; + }; + + users = { + users.quassel = { + isNormalUser = false; + group = "quassel"; + }; + + groups.quassel = {}; + }; + }; +} diff --git a/ops/modules/smtprelay.nix b/ops/modules/smtprelay.nix new file mode 100644 index 0000000000..d8e03b5794 --- /dev/null +++ b/ops/modules/smtprelay.nix @@ -0,0 +1,53 @@ +# NixOS module for configuring the simple SMTP relay. +{ depot, pkgs, config, lib, ... }: + +let + inherit (builtins) attrValues mapAttrs; + inherit (lib) + concatStringsSep + mkEnableOption + mkIf + mkOption + types +; + + cfg = config.services.depot.smtprelay; + description = "Simple SMTP relay"; + + # Configuration values that are always overridden. In particular, + # `config` is specified to always load $StateDirectory/secure.config + # (so that passwords can be loaded from there) and logging is pinned + # to stdout for journald compatibility. + overrideArgs = { + logfile = ""; + config = "/var/lib/smtprelay/secure.config"; + }; + + # Creates the command line argument string for the service. + prepareArgs = args: + concatStringsSep " " + (attrValues (mapAttrs (key: value: "-${key} '${toString value}'") + (args // overrideArgs))); +in { + options.services.depot.smtprelay = { + enable = mkEnableOption description; + args = mkOption { + type = types.attrsOf types.str; + description = "Key value pairs for command line arguments"; + }; + }; + + config = mkIf cfg.enable { + systemd.services.smtprelay = { + inherit description; + script = "${depot.third_party.smtprelay}/bin/smtprelay ${prepareArgs cfg.args}"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + Restart = "always"; + StateDirectory = "smtprelay"; + DynamicUser = true; + }; + }; + }; +} diff --git a/ops/modules/sourcegraph.nix b/ops/modules/sourcegraph.nix new file mode 100644 index 0000000000..a24328f3e3 --- /dev/null +++ b/ops/modules/sourcegraph.nix @@ -0,0 +1,51 @@ +# Run sourcegraph, including its entire machinery, in a container. +# Running it outside of a container is a futile endeavour for now. +{ depot, config, pkgs, lib, ... }: + +let + cfg = config.services.depot.sourcegraph; +in { + options.services.depot.sourcegraph = with lib; { + enable = mkEnableOption "SourceGraph code search engine"; + + port = mkOption { + description = "Port on which SourceGraph should listen"; + type = types.int; + default = 3463; + }; + + cheddarPort = mkOption { + description = "Port on which cheddar should listen"; + type = types.int; + default = 4238; + }; + }; + + config = lib.mkIf cfg.enable { + # Run a cheddar syntax highlighting server + systemd.services.cheddar-server = { + wantedBy = [ "multi-user.target" ]; + script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.cheddarPort} --sourcegraph-server"; + + serviceConfig = { + DynamicUser = true; + Restart = "always"; + }; + }; + + virtualisation.oci-containers.containers.sourcegraph = { + image = "sourcegraph/server:3.26.0"; + + ports = [ + "127.0.0.1:${toString cfg.port}:7080" + ]; + + volumes = [ + "/var/lib/sourcegraph/etc:/etc/sourcegraph" + "/var/lib/sourcegraph/data:/var/opt/sourcegraph" + ]; + + environment.SRC_SYNTECT_SERVER = "http://172.17.0.1:${toString cfg.cheddarPort}"; + }; + }; +} diff --git a/ops/modules/tvl-buildkite.nix b/ops/modules/tvl-buildkite.nix new file mode 100644 index 0000000000..2aa3b81811 --- /dev/null +++ b/ops/modules/tvl-buildkite.nix @@ -0,0 +1,48 @@ +# Configuration for the TVL buildkite agents. +{ config, depot, pkgs, lib, ... }: + +let + cfg = config.services.depot.buildkite; + agents = lib.range 1 cfg.agentCount; + description = "Buildkite agents for TVL"; + + # All Buildkite hooks are actually besadii, but it's being invoked + # with different names. + buildkiteHooks = pkgs.runCommandNoCC "buildkite-hooks" {} '' + mkdir -p $out/bin + ln -s ${depot.ops.besadii}/bin/besadii $out/bin/post-command + ''; +in { + options.services.depot.buildkite = { + enable = lib.mkEnableOption description; + agentCount = lib.mkOption { + type = lib.types.int; + description = "Number of Buildkite agents to launch"; + }; + }; + + config = lib.mkIf cfg.enable { + # Run the Buildkite agents using the default upstream module. + services.buildkite-agents = builtins.listToAttrs (map (n: rec { + name = "whitby-${toString n}"; + value = { + inherit name; + enable = true; + tokenPath = "/etc/secrets/buildkite-agent-token"; + hooks.post-command = "${buildkiteHooks}/bin/post-command"; + }; + }) agents); + + # Set up a group for all Buildkite agent users + users = { + groups.buildkite-agents = {}; + users = builtins.listToAttrs (map (n: rec { + name = "buildkite-agent-whitby-${toString n}"; + value = { + group = lib.mkForce "buildkite-agents"; + extraGroups = [ name ]; + }; + }) agents); + }; + }; +} diff --git a/ops/modules/tvl-slapd/default.nix b/ops/modules/tvl-slapd/default.nix new file mode 100644 index 0000000000..ae99fced74 --- /dev/null +++ b/ops/modules/tvl-slapd/default.nix @@ -0,0 +1,89 @@ +# Configures an OpenLDAP instance for TVL +# +# TODO(tazjin): Configure ldaps:// +{ depot, lib, pkgs, ... }: + +with depot.nix.yants; + +let + user = struct { + username = string; + email = string; + password = string; + displayName = option string; + }; + + toLdif = defun [ user string ] (u: '' + dn: cn=${u.username},ou=users,dc=tvl,dc=fyi + objectClass: organizationalPerson + objectClass: inetOrgPerson + sn: ${u.username} + cn: ${u.username} + displayName: ${u.displayName or u.username} + mail: ${u.email} + userPassword: ${u.password} + ''); + + inherit (depot.ops) users; + +in { + # Use our patched OpenLDAP derivation which enables stronger password hashing. + # + # Unfortunately the module for OpenLDAP has no package option, so we + # need to override it system-wide. Be aware that this triggers a + # *large* number of rebuilds of packages such as GPG and Python. + nixpkgs.overlays = [ + (_: _: { + inherit (depot.third_party) openldap; + }) + ]; + + services.openldap = { + enable = true; + dataDir = "/var/lib/openldap"; + database = "mdb"; + suffix = "dc=tvl,dc=fyi"; + rootdn = "cn=admin,dc=tvl,dc=fyi"; + rootpw = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$OfcgkOQ96VQ3aJj7NfA9vQ$oS6HQOkYl/bUYg4SejpltQYy7kvqx/RUxvoR4zo1vXU"; + + settings.children = { + "olcDatabase={1}mdb".attrs = { + objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; + olcDatabase = "{1}mdb"; + olcSuffix = "dc=tvl,dc=fyi"; + olcAccess = "to * by * read"; + }; + + "cn=module{0}".attrs = { + objectClass = "olcModuleList"; + olcModuleLoad = "pw-argon2"; + }; + }; + + # Contents are immutable at runtime, and adding user accounts etc. + # is done statically in the LDIF-formatted contents in this folder. + declarativeContents."dc=tvl,dc=fyi" = '' + dn: dc=tvl,dc=fyi + dc: tvl + o: TVL LDAP server + description: Root entry for tvl.fyi + objectClass: top + objectClass: dcObject + objectClass: organization + + dn: ou=users,dc=tvl,dc=fyi + ou: users + description: All users in TVL + objectClass: top + objectClass: organizationalUnit + + dn: ou=groups,dc=tvl,dc=fyi + ou: groups + description: All groups in TVL + objectClass: top + objectClass: organizationalUnit + + ${lib.concatStringsSep "\n" (map toLdif users)} + ''; + }; +} diff --git a/ops/modules/tvl-sso/default.nix b/ops/modules/tvl-sso/default.nix new file mode 100644 index 0000000000..8e33c708b7 --- /dev/null +++ b/ops/modules/tvl-sso/default.nix @@ -0,0 +1,24 @@ +# Configures an Apereo CAS instance for TVL SSO +{ depot, ... }: + +let + inherit (depot.third_party) apereo-cas; +in { + config = { + environment.systemPackages = [ apereo-cas ]; + systemd.services.apereo-cas = { + description = "Apereo CAS Single Sign On server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + User = "apereo-cas"; + Group = "apereo-cas"; + ExecStart = "${apereo-cas}/bin/cas"; + EnvironmentFile = "/etc/cas/secrets"; + Restart = "always"; + }; + }; + users.users.apereo-cas = {}; + users.groups.apereo-cas = {}; + }; +} diff --git a/ops/modules/v4l2loopback.nix b/ops/modules/v4l2loopback.nix new file mode 100644 index 0000000000..636b2ff6cf --- /dev/null +++ b/ops/modules/v4l2loopback.nix @@ -0,0 +1,12 @@ +{ config, lib, pkgs, ... }: + +{ + boot = { + extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ]; + kernelModules = [ "v4l2loopback" ]; + extraModprobeConfig = '' + options v4l2loopback exclusive_caps=1 + ''; + }; +} + diff --git a/ops/modules/www/b.tvl.fyi.nix b/ops/modules/www/b.tvl.fyi.nix new file mode 100644 index 0000000000..45f6c6ed51 --- /dev/null +++ b/ops/modules/www/b.tvl.fyi.nix @@ -0,0 +1,32 @@ +{ config, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."b-shortlink" = { + serverName = "b"; + extraConfig = "return 302 https://b.tvl.fyi$request_uri;"; + }; + + services.nginx.virtualHosts."b.tvl.fyi" = { + serverName = "b.tvl.fyi"; + serverAliases = [ "b.tvl.su" ]; + enableACME = true; + forceSSL = true; + + extraConfig = '' + # Forward short links to issues to the issue itself (b/32) + location ~ ^/(\d+)$ { + return 302 https://b.tvl.fyi/issues$request_uri; + } + + location / { + proxy_pass http://localhost:${toString config.services.depot.panettone.port}; + } + ''; + }; + }; +} diff --git a/ops/modules/www/base.nix b/ops/modules/www/base.nix new file mode 100644 index 0000000000..4b956cd95e --- /dev/null +++ b/ops/modules/www/base.nix @@ -0,0 +1,36 @@ +{ config, pkgs, ... }: + +{ + config = { + services.nginx = { + enable = true; + enableReload = true; + + recommendedTlsSettings = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + }; + + # NixOS 20.03 broke nginx and I can't be bothered to debug it + # anymore, all solution attempts have failed, so here's a + # brute-force fix. + # + # TODO(tazjin): Find a link to the upstream issue and see if + # they've sorted it after ~20.09 + systemd.services.fix-nginx = { + script = "${pkgs.coreutils}/bin/chown -f -R nginx: /var/spool/nginx /var/cache/nginx"; + + serviceConfig = { + User = "root"; + Type = "oneshot"; + }; + }; + + systemd.timers.fix-nginx = { + wantedBy = [ "multi-user.target" ]; + timerConfig = { + OnCalendar = "minutely"; + }; + }; + }; +} diff --git a/ops/modules/www/cache.tvl.su.nix b/ops/modules/www/cache.tvl.su.nix new file mode 100644 index 0000000000..182306bebf --- /dev/null +++ b/ops/modules/www/cache.tvl.su.nix @@ -0,0 +1,26 @@ +{ config, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."cache.tvl.su" = { + serverName = "cache.tvl.su"; + serverAliases = [ "cache.tvl.fyi" ]; + enableACME = true; + forceSSL = true; + + extraConfig = '' + location = /cache-key.pub { + alias /etc/secrets/nix-cache-key.pub; + } + + location / { + proxy_pass http://localhost:${toString config.services.nix-serve.port}; + } + ''; + }; + }; +} diff --git a/ops/modules/www/cl.tvl.fyi.nix b/ops/modules/www/cl.tvl.fyi.nix new file mode 100644 index 0000000000..470122c395 --- /dev/null +++ b/ops/modules/www/cl.tvl.fyi.nix @@ -0,0 +1,30 @@ +{ config, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."cl-shortlink" = { + serverName = "cl"; + extraConfig = "return 302 https://cl.tvl.fyi$request_uri;"; + }; + + services.nginx.virtualHosts.gerrit = { + serverName = "cl.tvl.fyi"; + serverAliases = [ "cl.tvl.su" ]; + enableACME = true; + forceSSL = true; + + extraConfig = '' + location / { + proxy_pass http://localhost:4778; + proxy_set_header X-Forwarded-For $remote_addr; + # The :443 suffix is a workaround for https://b.tvl.fyi/issues/88. + proxy_set_header Host $host:443; + } + ''; + }; + }; +} diff --git a/ops/modules/www/code.tvl.fyi.nix b/ops/modules/www/code.tvl.fyi.nix new file mode 100644 index 0000000000..c8a4b27b1b --- /dev/null +++ b/ops/modules/www/code.tvl.fyi.nix @@ -0,0 +1,35 @@ +{ depot, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts.cgit = { + serverName = "code.tvl.fyi"; + serverAliases = [ "code.tvl.su" ]; + enableACME = true; + forceSSL = true; + + extraConfig = '' + # Serve the rendered Tvix component SVG. + # + # TODO(tazjin): Implement a way of serving this dynamically + location = /about/tvix/docs/component-flow.svg { + alias ${depot.tvix.docs.svg}/component-flow.svg; + } + + # Static assets must always hit the root. + location ~ ^/(favicon\.ico|cgit\.(css|png))$ { + proxy_pass http://localhost:2448; + } + + # Everything else hits the depot directly. + location / { + proxy_pass http://localhost:2448/cgit.cgi/depot/; + } + ''; + }; + }; +} diff --git a/ops/modules/www/cs.tvl.fyi.nix b/ops/modules/www/cs.tvl.fyi.nix new file mode 100644 index 0000000000..fac814baf0 --- /dev/null +++ b/ops/modules/www/cs.tvl.fyi.nix @@ -0,0 +1,31 @@ +{ config, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."cs.tvl.fyi" = { + serverName = "cs.tvl.fyi"; + serverAliases = [ "cs.tvl.su" ]; + enableACME = true; + forceSSL = true; + + extraConfig = '' + location = / { + return 301 https://cs.tvl.fyi/depot; + } + + location / { + proxy_set_header X-Sg-Auth "Anonymous"; + proxy_pass http://localhost:${toString config.services.depot.sourcegraph.port}; + } + + location /users/Anonymous/settings { + return 301 https://cs.tvl.fyi; + } + ''; + }; + }; +} diff --git a/ops/modules/www/login.tvl.fyi.nix b/ops/modules/www/login.tvl.fyi.nix new file mode 100644 index 0000000000..05b7cee253 --- /dev/null +++ b/ops/modules/www/login.tvl.fyi.nix @@ -0,0 +1,24 @@ +{ ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."login.tvl.fyi" = { + serverName = "login.tvl.fyi"; + enableACME = true; + forceSSL = true; + + extraConfig = '' + location / { + proxy_pass http://localhost:8443; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header Host $host; + } + ''; + }; + }; +} diff --git a/ops/modules/www/tazj.in.nix b/ops/modules/www/tazj.in.nix new file mode 100644 index 0000000000..7d658a5ec4 --- /dev/null +++ b/ops/modules/www/tazj.in.nix @@ -0,0 +1,40 @@ +# serve tazjin's website & blog +{ depot, config, lib, pkgs, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."tazj.in" = { + enableACME = true; + forceSSL = true; + root = depot.users.tazjin.homepage; + + extraConfig = '' + ${depot.users.tazjin.blog.oldRedirects} + location /blog/ { + alias ${depot.users.tazjin.blog.rendered}/; + + if ($request_uri ~ ^/(.*)\.html$) { + return 302 /$1; + } + + try_files $uri $uri.html $uri/ =404; + } + + # Temporary place for serving static files. + location /blobs/ { + alias /var/lib/tazjins-blobs/; + } + ''; + }; + + services.nginx.virtualHosts."git.tazj.in" = { + enableACME = true; + forceSSL = true; + extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; + }; + }; +} diff --git a/ops/modules/www/todo.tvl.fyi.nix b/ops/modules/www/todo.tvl.fyi.nix new file mode 100644 index 0000000000..b53f5437e7 --- /dev/null +++ b/ops/modules/www/todo.tvl.fyi.nix @@ -0,0 +1,25 @@ +{ depot, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."todo.tvl.fyi" = { + serverName = "todo.tvl.fyi"; + serverAliases = [ "todo.tvl.su" ]; + root = depot.web.todolist; + enableACME = true; + forceSSL = true; + + extraConfig = '' + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + location ~* \.(webp|woff2)$ { + add_header Cache-Control "public, max-age=31536000"; + } + ''; + }; + }; +} diff --git a/ops/modules/www/tvl.fyi.nix b/ops/modules/www/tvl.fyi.nix new file mode 100644 index 0000000000..45fd35803d --- /dev/null +++ b/ops/modules/www/tvl.fyi.nix @@ -0,0 +1,30 @@ +{ depot, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."tvl.fyi" = { + serverName = "tvl.fyi"; + root = depot.web.tvl; + enableACME = true; + forceSSL = true; + + extraConfig = '' + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + + rewrite ^/builds/?$ https://buildkite.com/tvl/depot/ last; + + rewrite ^/monorepo-doc/?$ https://docs.google.com/document/d/1nnyByXcH0F6GOmEezNOUa2RFelpeRpDToBLYD_CtjWE/edit?usp=sharing last; + + rewrite ^/irc/?$ ircs://chat.freenode.net:6697/##tvl last; + + location ~* \.(webp|woff2)$ { + add_header Cache-Control "public, max-age=31536000"; + } + ''; + }; + }; +} diff --git a/ops/modules/www/wigglydonke.rs.nix b/ops/modules/www/wigglydonke.rs.nix new file mode 100644 index 0000000000..0bc67898c6 --- /dev/null +++ b/ops/modules/www/wigglydonke.rs.nix @@ -0,0 +1,15 @@ +{ depot, lib, pkgs, ... }: + +{ + imports = [ + ./base.nix + ]; + + config = { + services.nginx.virtualHosts."wigglydonke.rs" = { + enableACME = true; + forceSSL = true; + root = "${depot.depotPath}/users/glittershark/wigglydonke.rs"; + }; + }; +} diff --git a/ops/nixos.nix b/ops/nixos.nix new file mode 100644 index 0000000000..465a2eed31 --- /dev/null +++ b/ops/nixos.nix @@ -0,0 +1,45 @@ +# Helper functions for instantiating depot-compatible NixOS machines. +{ depot, lib, pkgs, ... }@args: + +let inherit (lib) findFirst isAttrs; +in rec { + # This provides our standard set of arguments to all NixOS modules. + baseModule = { ... }: { + _module.args = { + inherit (args) depot; + }; + }; + + nixosFor = configuration: (depot.third_party.nixos { + configuration = { ... }: { + imports = [ + baseModule + configuration + ]; + }; + }); + + findSystem = hostname: + (findFirst + (system: system.config.networking.hostName == hostname) + (throw "${hostname} is not a known NixOS host") + (map nixosFor depot.ops.machines.all-systems)); + + rebuild-system = pkgs.writeShellScriptBin "rebuild-system" '' + set -ue + if [[ $EUID -ne 0 ]]; then + echo "Oh no! Only root is allowed to rebuild the system!" >&2 + exit 1 + fi + + echo "Rebuilding NixOS for $HOSTNAME" + system=$(nix-build -E "((import ${toString depot.depotPath} {}).ops.nixos.findSystem \"$HOSTNAME\").system" --no-out-link --show-trace) + + nix-env -p /nix/var/nix/profiles/system --set $system + $system/bin/switch-to-configuration switch + ''; + + # Systems that should be built in CI + whitbySystem = (nixosFor depot.ops.machines.whitby).system; + meta.targets = [ "whitbySystem" ]; +} diff --git a/ops/nixos/.gitignore b/ops/nixos/.gitignore deleted file mode 100644 index 773fa16670..0000000000 --- a/ops/nixos/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -hardware-configuration.nix -local-configuration.nix -result diff --git a/ops/nixos/.skip-subtree b/ops/nixos/.skip-subtree deleted file mode 100644 index 09520f8c83..0000000000 --- a/ops/nixos/.skip-subtree +++ /dev/null @@ -1 +0,0 @@ -NixOS modules are not readTree compatible. diff --git a/ops/nixos/README.md b/ops/nixos/README.md deleted file mode 100644 index 595b4c3344..0000000000 --- a/ops/nixos/README.md +++ /dev/null @@ -1,7 +0,0 @@ -NixOS modules -============= - -This folder contains various NixOS modules shared by our NixOS -configurations. - -It is not read by `readTree`. diff --git a/ops/nixos/all-systems.nix b/ops/nixos/all-systems.nix deleted file mode 100644 index 05a89e05ab..0000000000 --- a/ops/nixos/all-systems.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ depot, ... }: - -(with depot.ops.nixos; [ - whitby -]) ++ - -(with depot.users.tazjin.nixos; [ - camden - frog - tverskoy -]) ++ - -(with depot.users.glittershark.system.system; [ - chupacabra - yeren -]) diff --git a/ops/nixos/clbot.nix b/ops/nixos/clbot.nix deleted file mode 100644 index ad33e25a4d..0000000000 --- a/ops/nixos/clbot.nix +++ /dev/null @@ -1,75 +0,0 @@ -# Module that configures CLBot, our Gerrit->IRC info bridge. -{ depot, config, lib, pkgs, ... }: - -let - inherit (builtins) attrValues concatStringsSep mapAttrs readFile; - inherit (pkgs) runCommandNoCC; - - inherit (lib) - listToAttrs - mkEnableOption - mkIf - mkOption - removeSuffix - types; - - description = "Bot to forward CL notifications"; - cfg = config.services.depot.clbot; - - mkFlags = flags: - concatStringsSep " " - (attrValues (mapAttrs (key: value: "-${key} \"${toString value}\"") flags)); - - # Escapes a unit name for use in systemd - systemdEscape = name: removeSuffix "\n" (readFile (runCommandNoCC "unit-name" {} '' - ${pkgs.systemd}/bin/systemd-escape '${name}' >> $out - '')); - - mkUnit = flags: channel: { - name = "clbot-${systemdEscape channel}"; - value = { - description = "${description} to ${channel}"; - wantedBy = [ "multi-user.target" ]; - - script = "${depot.fun.clbot}/bin/clbot ${mkFlags (cfg.flags // { - irc_channel = channel; - })} -alsologtostderr"; - - serviceConfig = { - User = "clbot"; - EnvironmentFile = "/etc/secrets/clbot"; - Restart = "always"; - }; - }; - }; -in { - options.services.depot.clbot = { - enable = mkEnableOption description; - - flags = mkOption { - type = types.attrsOf types.str; - description = "Key value pairs for command line flags"; - }; - - channels = mkOption { - type = with types; listOf str; - description = "Channels in which to post (generates one unit per channel)"; - }; - }; - - config = mkIf cfg.enable { - # This does not use DynamicUser because we need to make some files - # (notably the SSH private key) readable by this user outside of - # the module. - users = { - groups.clbot = {}; - - users.clbot = { - group = "clbot"; - isNormalUser = false; - }; - }; - - systemd.services = listToAttrs (map (mkUnit cfg.flags) cfg.channels); - }; -} diff --git a/ops/nixos/default.nix b/ops/nixos/default.nix deleted file mode 100644 index 8be700b104..0000000000 --- a/ops/nixos/default.nix +++ /dev/null @@ -1,61 +0,0 @@ -# Most of the Nix expressions in this folder are NixOS modules, which -# are not readTree compatible. -# -# Some things (such as system configurations) are, and we import them -# here manually. -# -# TODO(tazjin): Find a more elegant solution for the whole module -# situation. -{ depot, lib, pkgs, ... }@args: - -let inherit (lib) findFirst isAttrs; -in rec { - whitby = import ./whitby/default.nix args; - - # System installation - - allSystems = import ./all-systems.nix args; - - # This provides our standard set of arguments to all NixOS modules. - baseModule = { ... }: { - _module.args = { - inherit (args) depot; - }; - }; - - nixosFor = configuration: (depot.third_party.nixos { - configuration = { ... }: { - imports = [ - baseModule - configuration - ]; - }; - }); - - findSystem = hostname: - (findFirst - (system: system.config.networking.hostName == hostname) - (throw "${hostname} is not a known NixOS host") - (map nixosFor allSystems)); - - rebuild-system = pkgs.writeShellScriptBin "rebuild-system" '' - set -ue - if [[ $EUID -ne 0 ]]; then - echo "Oh no! Only root is allowed to rebuild the system!" >&2 - exit 1 - fi - - echo "Rebuilding NixOS for $HOSTNAME" - system=$(nix-build -E "((import ${toString depot.depotPath} {}).ops.nixos.findSystem \"$HOSTNAME\").system" --no-out-link --show-trace) - - nix-env -p /nix/var/nix/profiles/system --set $system - $system/bin/switch-to-configuration switch - ''; - - # Systems that should be built in CI - # - # TODO(tazjin): Refactor the whole systems setup, it's a bit - # inconsistent at the moment. - whitbySystem = (nixosFor whitby).system; - meta.targets = [ "whitbySystem" ]; -} diff --git a/ops/nixos/irccat.nix b/ops/nixos/irccat.nix deleted file mode 100644 index e4b30b7355..0000000000 --- a/ops/nixos/irccat.nix +++ /dev/null @@ -1,49 +0,0 @@ -{ depot, config, lib, pkgs, ... }: - -let - cfg = config.services.depot.irccat; - description = "irccat - forward messages to IRC"; - - # irccat expects to read its configuration from the *current - # directory*, and its configuration contains secrets. - # - # To make this work we construct the JSON configuration file and - # then recursively merge it with an on-disk secret using jq on - # service launch. - configJson = pkgs.writeText "irccat.json" (builtins.toJSON cfg.config); - configMerge = pkgs.writeShellScript "merge-irccat-config" '' - if [ ! -f "/etc/secrets/irccat.json" ]; then - echo "irccat secrets file is missing" - exit 1 - fi - - # jq's * is the recursive merge operator - ${pkgs.jq}/bin/jq -s '.[0] * .[1]' ${configJson} /etc/secrets/irccat.json \ - > /var/lib/irccat/irccat.json - ''; -in { - options.services.depot.irccat = { - enable = lib.mkEnableOption description; - - config = lib.mkOption { - type = lib.types.attrs; # varying value types - description = "Configuration structure (unchecked!)"; - }; - }; - - config = lib.mkIf cfg.enable { - systemd.services.irccat = { - inherit description; - preStart = "${configMerge}"; - script = "${depot.third_party.irccat}/bin/irccat"; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - DynamicUser = true; - StateDirectory = "irccat"; - WorkingDirectory = "/var/lib/irccat"; - Restart = "always"; - }; - }; - }; -} diff --git a/ops/nixos/monorepo-gerrit.nix b/ops/nixos/monorepo-gerrit.nix deleted file mode 100644 index eaea386ecd..0000000000 --- a/ops/nixos/monorepo-gerrit.nix +++ /dev/null @@ -1,128 +0,0 @@ -# Gerrit configuration for the TVL monorepo -{ depot, pkgs, config, lib, ... }: - -let - cfg = config.services.gerrit; - gerritHooks = pkgs.runCommandNoCC "gerrit-hooks" {} '' - mkdir -p $out - ln -s ${depot.ops.besadii}/bin/besadii $out/ref-updated - ''; -in { - services.gerrit = { - enable = true; - listenAddress = "[::]:4778"; # 4778 - grrt - serverId = "4fdfa107-4df9-4596-8e0a-1d2bbdd96e36"; - builtinPlugins = [ - "download-commands" - "hooks" - ]; - - plugins = with depot.third_party.gerrit_plugins; [ - owners - oauth - depot.ops.gerrit-tvl - ]; - - package = depot.third_party.gerrit; - - jvmHeapLimit = "4g"; - - settings = { - core.packedGitLimit = "100m"; - log.jsonLogging = true; - log.textLogging = false; - sshd.advertisedAddress = "code.tvl.fyi:29418"; - hooks.path = "${gerritHooks}"; - cache.web_sessions.maxAge = "3 months"; - plugins.allowRemoteAdmin = false; - change.enableAttentionSet = true; - change.enableAssignee = false; - - # Configures gerrit for being reverse-proxied by nginx as per - # https://gerrit-review.googlesource.com/Documentation/config-reverseproxy.html - gerrit = { - canonicalWebUrl = "https://cl.tvl.fyi"; - docUrl = "/Documentation"; - }; - - httpd.listenUrl = "proxy-https://${cfg.listenAddress}"; - - download.command = [ - "checkout" - "cherry_pick" - "format_patch" - "pull" - ]; - - # Configure for cgit. - gitweb = { - type = "custom"; - url = "https://code.tvl.fyi"; - project = "/"; - revision = "/commit/?id=\${commit}"; - branch = "/log/?h=\${branch}"; - tag = "/tag/?h=\${tag}"; - roottree = "/tree/?h=\${commit}"; - file = "/tree/\${file}?h=\${commit}"; - filehistory = "/log/\${file}?h=\${branch}"; - linkname = "cgit"; - }; - - # Auto-link panettone bug links - commentlink.panettone = { - match = "b/(\\\\d+)"; - html = "b/$1"; - }; - - # Auto-link other CLs - commentlink.gerrit = { - match = "cl/(\\\\d+)"; - html = "cl/$1"; - }; - - # Configures integration with CAS, which then integrates with a variety - # of backends. - auth.type = "OAUTH"; - plugin.gerrit-oauth-provider-cas-oauth = { - root-url = "https://login.tvl.fyi"; - client-id = "OAUTH-TVL-gerrit-Fv0d8Aizz5"; - # client-secret is set in /var/lib/gerrit/etc/secure.config. - }; - - # Use Gerrit's built-in HTTP passwords, rather than trying to use the - # password against the backing OAuth provider. - auth.gitBasicAuthPolicy = "HTTP"; - - # Email sending (emails are relayed via the tazj.in domain's - # GSuite currently). - # - # Note that sendemail.smtpPass is stored in - # $site_path/etc/secure.config and is *not* controlled by Nix. - # - # Receiving email is not currently supported. - sendemail = { - enable = true; - html = false; - connectTimeout = "10sec"; - from = "TVL Code Review "; - includeDiff = true; - smtpEncryption = "none"; - smtpServer = "localhost"; - smtpServerPort = 2525; - }; - }; - }; - - systemd.services.gerrit = { - serviceConfig = { - # There seems to be no easy way to get `DynamicUser` to play - # well with other services (e.g. by using SupplementaryGroups, - # which seem to have no effect) so we force the DynamicUser - # setting for the Gerrit service to be disabled and reuse the - # existing 'git' user. - DynamicUser = lib.mkForce false; - User = "git"; - Group = "git"; - }; - }; -} diff --git a/ops/nixos/panettone.nix b/ops/nixos/panettone.nix deleted file mode 100644 index 51a7468578..0000000000 --- a/ops/nixos/panettone.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ depot, config, lib, pkgs, ... }: - -let - cfg = config.services.depot.panettone; -in { - options.services.depot.panettone = with lib; { - enable = mkEnableOption "Panettone issue tracker"; - - port = mkOption { - description = "Port on which Panettone should listen"; - type = types.int; - default = 7268; - }; - - dbHost = mkOption { - description = "Postgresql host to connect to for Panettone"; - type = types.str; - default = "localhost"; - }; - - dbName = mkOption { - description = "Name of the database for Panettone"; - type = types.str; - default = "panettone"; - }; - - dbUser = mkOption { - description = "Name of the database user for Panettone"; - type = types.str; - default = "panettone"; - }; - - secretsFile = mkOption { - description = '' - Path to a file containing secrets, in the format accepted - by systemd's EnvironmentFile - ''; - type = types.str; - }; - - irccatHost = mkOption { - description = "Hostname for the irccat instance"; - type = types.str; - default = "localhost"; - }; - - irccatPort = mkOption { - description = "Port for the irccat instance"; - type = types.int; - default = 4722; - }; - - irccatChannel = mkOption { - description = "IRC channels to post to via irccat"; - type = types.str; - }; - }; - - config = lib.mkIf cfg.enable { - assertions = [{ - assertion = - cfg.dbHost != "localhost" || config.services.postgresql.enable; - message = "Panettone requires a postgresql database"; - } { - assertion = - cfg.dbHost != "localhost" || config.services.postgresql.enableTCPIP; - message = "Panettone can only connect to the postgresql database over TCP"; - } { - assertion = - cfg.dbHost != "localhost" || (lib.any - (user: user.name == cfg.dbUser) - config.services.postgresql.ensureUsers); - message = "Panettone requires a database user"; - } { - assertion = - cfg.dbHost != "localhost" || (lib.any - (db: db == cfg.dbName) - config.services.postgresql.ensureDatabases); - message = "Panettone requires a database"; - }]; - - systemd.services.panettone = { - wantedBy = [ "multi-user.target" ]; - script = "${depot.web.panettone}/bin/panettone"; - - serviceConfig = { - DynamicUser = true; - Restart = "always"; - EnvironmentFile = cfg.secretsFile; - }; - - environment = { - PANETTONE_PORT = toString cfg.port; - PGHOST = "localhost"; - PGUSER = cfg.dbUser; - PGDATABASE = cfg.dbName; - IRCCATHOST = cfg.irccatHost; - IRCCATPORT = toString cfg.irccatPort; - ISSUECHANNEL = cfg.irccatChannel; - }; - }; - }; -} diff --git a/ops/nixos/paroxysm.nix b/ops/nixos/paroxysm.nix deleted file mode 100644 index cd9cd3866e..0000000000 --- a/ops/nixos/paroxysm.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ depot, config, lib, pkgs, ... }: - -let - cfg = config.services.depot.paroxysm; - description = "TVL's majestic IRC bot"; -in { - options.services.depot.paroxysm.enable = lib.mkEnableOption description; - - config = lib.mkIf cfg.enable { - systemd.services.paroxysm = { - inherit description; - script = "${depot.fun.paroxysm}/bin/paroxysm"; - wantedBy = [ "multi-user.target" ]; - - environment = { - PARX_DATABASE_URL = "postgresql://tvldb:tvldb@localhost/tvldb"; - PARX_IRC_CONFIG_PATH = "/var/lib/paroxysm/irc.toml"; - }; - - serviceConfig = { - DynamicUser = true; - StateDirectory = "paroxysm"; - Restart = "always"; - }; - }; - }; -} diff --git a/ops/nixos/quassel.nix b/ops/nixos/quassel.nix deleted file mode 100644 index df26a39455..0000000000 --- a/ops/nixos/quassel.nix +++ /dev/null @@ -1,76 +0,0 @@ -# A more modern module for running Quassel. -{ config, lib, pkgs, ... }: - -let - cfg = config.services.depot.quassel; - quasselDaemon = pkgs.quassel.override { - monolithic = false; - enableDaemon = true; - withKDE = false; - }; -in { - options.services.depot.quassel = with lib; { - enable = mkEnableOption "Quassel IRC daemon"; - - acmeHost = mkOption { - description = "ACME host to use for the Quassel TLS certificate"; - type = lib.types.str; - }; - - bindAddresses = mkOption { - description = "Addresses Quassel will bind to/listen on"; - default = [ "127.0.0.1" ]; - }; - - logLevel = mkOption { - description = "Log level for Quassel Core"; - default = "Info"; - type = lib.types.enum [ - "Debug" - "Info" - "Warning" - "Error" - ]; - }; - - port = mkOption { - default = 6698; - description = '' - The port number the Quassel daemon will be listening to. - ''; - }; - }; - - config = with lib; mkIf cfg.enable { - systemd.services.quassel = { - description = "Quassel IRC daemon"; - wantedBy = [ "multi-user.target" ]; - - script = concatStringsSep " " [ - "${quasselDaemon}/bin/quasselcore" - "--listen=${concatStringsSep "," cfg.bindAddresses}" - "--port=${toString cfg.port}" - "--configdir=/var/lib/quassel" - "--require-ssl" - "--ssl-cert=/var/lib/acme/${cfg.acmeHost}/full.pem" - "--loglevel=${cfg.logLevel}" - ]; - - serviceConfig = { - Restart = "always"; - User = "quassel"; - Group = "quassel"; - StateDirectory = "quassel"; - }; - }; - - users = { - users.quassel = { - isNormalUser = false; - group = "quassel"; - }; - - groups.quassel = {}; - }; - }; -} diff --git a/ops/nixos/smtprelay.nix b/ops/nixos/smtprelay.nix deleted file mode 100644 index d8e03b5794..0000000000 --- a/ops/nixos/smtprelay.nix +++ /dev/null @@ -1,53 +0,0 @@ -# NixOS module for configuring the simple SMTP relay. -{ depot, pkgs, config, lib, ... }: - -let - inherit (builtins) attrValues mapAttrs; - inherit (lib) - concatStringsSep - mkEnableOption - mkIf - mkOption - types -; - - cfg = config.services.depot.smtprelay; - description = "Simple SMTP relay"; - - # Configuration values that are always overridden. In particular, - # `config` is specified to always load $StateDirectory/secure.config - # (so that passwords can be loaded from there) and logging is pinned - # to stdout for journald compatibility. - overrideArgs = { - logfile = ""; - config = "/var/lib/smtprelay/secure.config"; - }; - - # Creates the command line argument string for the service. - prepareArgs = args: - concatStringsSep " " - (attrValues (mapAttrs (key: value: "-${key} '${toString value}'") - (args // overrideArgs))); -in { - options.services.depot.smtprelay = { - enable = mkEnableOption description; - args = mkOption { - type = types.attrsOf types.str; - description = "Key value pairs for command line arguments"; - }; - }; - - config = mkIf cfg.enable { - systemd.services.smtprelay = { - inherit description; - script = "${depot.third_party.smtprelay}/bin/smtprelay ${prepareArgs cfg.args}"; - wantedBy = [ "multi-user.target" ]; - - serviceConfig = { - Restart = "always"; - StateDirectory = "smtprelay"; - DynamicUser = true; - }; - }; - }; -} diff --git a/ops/nixos/sourcegraph.nix b/ops/nixos/sourcegraph.nix deleted file mode 100644 index a24328f3e3..0000000000 --- a/ops/nixos/sourcegraph.nix +++ /dev/null @@ -1,51 +0,0 @@ -# Run sourcegraph, including its entire machinery, in a container. -# Running it outside of a container is a futile endeavour for now. -{ depot, config, pkgs, lib, ... }: - -let - cfg = config.services.depot.sourcegraph; -in { - options.services.depot.sourcegraph = with lib; { - enable = mkEnableOption "SourceGraph code search engine"; - - port = mkOption { - description = "Port on which SourceGraph should listen"; - type = types.int; - default = 3463; - }; - - cheddarPort = mkOption { - description = "Port on which cheddar should listen"; - type = types.int; - default = 4238; - }; - }; - - config = lib.mkIf cfg.enable { - # Run a cheddar syntax highlighting server - systemd.services.cheddar-server = { - wantedBy = [ "multi-user.target" ]; - script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.cheddarPort} --sourcegraph-server"; - - serviceConfig = { - DynamicUser = true; - Restart = "always"; - }; - }; - - virtualisation.oci-containers.containers.sourcegraph = { - image = "sourcegraph/server:3.26.0"; - - ports = [ - "127.0.0.1:${toString cfg.port}:7080" - ]; - - volumes = [ - "/var/lib/sourcegraph/etc:/etc/sourcegraph" - "/var/lib/sourcegraph/data:/var/opt/sourcegraph" - ]; - - environment.SRC_SYNTECT_SERVER = "http://172.17.0.1:${toString cfg.cheddarPort}"; - }; - }; -} diff --git a/ops/nixos/tvl-buildkite.nix b/ops/nixos/tvl-buildkite.nix deleted file mode 100644 index 2aa3b81811..0000000000 --- a/ops/nixos/tvl-buildkite.nix +++ /dev/null @@ -1,48 +0,0 @@ -# Configuration for the TVL buildkite agents. -{ config, depot, pkgs, lib, ... }: - -let - cfg = config.services.depot.buildkite; - agents = lib.range 1 cfg.agentCount; - description = "Buildkite agents for TVL"; - - # All Buildkite hooks are actually besadii, but it's being invoked - # with different names. - buildkiteHooks = pkgs.runCommandNoCC "buildkite-hooks" {} '' - mkdir -p $out/bin - ln -s ${depot.ops.besadii}/bin/besadii $out/bin/post-command - ''; -in { - options.services.depot.buildkite = { - enable = lib.mkEnableOption description; - agentCount = lib.mkOption { - type = lib.types.int; - description = "Number of Buildkite agents to launch"; - }; - }; - - config = lib.mkIf cfg.enable { - # Run the Buildkite agents using the default upstream module. - services.buildkite-agents = builtins.listToAttrs (map (n: rec { - name = "whitby-${toString n}"; - value = { - inherit name; - enable = true; - tokenPath = "/etc/secrets/buildkite-agent-token"; - hooks.post-command = "${buildkiteHooks}/bin/post-command"; - }; - }) agents); - - # Set up a group for all Buildkite agent users - users = { - groups.buildkite-agents = {}; - users = builtins.listToAttrs (map (n: rec { - name = "buildkite-agent-whitby-${toString n}"; - value = { - group = lib.mkForce "buildkite-agents"; - extraGroups = [ name ]; - }; - }) agents); - }; - }; -} diff --git a/ops/nixos/tvl-slapd/default.nix b/ops/nixos/tvl-slapd/default.nix deleted file mode 100644 index ae99fced74..0000000000 --- a/ops/nixos/tvl-slapd/default.nix +++ /dev/null @@ -1,89 +0,0 @@ -# Configures an OpenLDAP instance for TVL -# -# TODO(tazjin): Configure ldaps:// -{ depot, lib, pkgs, ... }: - -with depot.nix.yants; - -let - user = struct { - username = string; - email = string; - password = string; - displayName = option string; - }; - - toLdif = defun [ user string ] (u: '' - dn: cn=${u.username},ou=users,dc=tvl,dc=fyi - objectClass: organizationalPerson - objectClass: inetOrgPerson - sn: ${u.username} - cn: ${u.username} - displayName: ${u.displayName or u.username} - mail: ${u.email} - userPassword: ${u.password} - ''); - - inherit (depot.ops) users; - -in { - # Use our patched OpenLDAP derivation which enables stronger password hashing. - # - # Unfortunately the module for OpenLDAP has no package option, so we - # need to override it system-wide. Be aware that this triggers a - # *large* number of rebuilds of packages such as GPG and Python. - nixpkgs.overlays = [ - (_: _: { - inherit (depot.third_party) openldap; - }) - ]; - - services.openldap = { - enable = true; - dataDir = "/var/lib/openldap"; - database = "mdb"; - suffix = "dc=tvl,dc=fyi"; - rootdn = "cn=admin,dc=tvl,dc=fyi"; - rootpw = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$OfcgkOQ96VQ3aJj7NfA9vQ$oS6HQOkYl/bUYg4SejpltQYy7kvqx/RUxvoR4zo1vXU"; - - settings.children = { - "olcDatabase={1}mdb".attrs = { - objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; - olcDatabase = "{1}mdb"; - olcSuffix = "dc=tvl,dc=fyi"; - olcAccess = "to * by * read"; - }; - - "cn=module{0}".attrs = { - objectClass = "olcModuleList"; - olcModuleLoad = "pw-argon2"; - }; - }; - - # Contents are immutable at runtime, and adding user accounts etc. - # is done statically in the LDIF-formatted contents in this folder. - declarativeContents."dc=tvl,dc=fyi" = '' - dn: dc=tvl,dc=fyi - dc: tvl - o: TVL LDAP server - description: Root entry for tvl.fyi - objectClass: top - objectClass: dcObject - objectClass: organization - - dn: ou=users,dc=tvl,dc=fyi - ou: users - description: All users in TVL - objectClass: top - objectClass: organizationalUnit - - dn: ou=groups,dc=tvl,dc=fyi - ou: groups - description: All groups in TVL - objectClass: top - objectClass: organizationalUnit - - ${lib.concatStringsSep "\n" (map toLdif users)} - ''; - }; -} diff --git a/ops/nixos/tvl-sso/default.nix b/ops/nixos/tvl-sso/default.nix deleted file mode 100644 index 8e33c708b7..0000000000 --- a/ops/nixos/tvl-sso/default.nix +++ /dev/null @@ -1,24 +0,0 @@ -# Configures an Apereo CAS instance for TVL SSO -{ depot, ... }: - -let - inherit (depot.third_party) apereo-cas; -in { - config = { - environment.systemPackages = [ apereo-cas ]; - systemd.services.apereo-cas = { - description = "Apereo CAS Single Sign On server"; - wantedBy = [ "multi-user.target" ]; - after = [ "network.target" ]; - serviceConfig = { - User = "apereo-cas"; - Group = "apereo-cas"; - ExecStart = "${apereo-cas}/bin/cas"; - EnvironmentFile = "/etc/cas/secrets"; - Restart = "always"; - }; - }; - users.users.apereo-cas = {}; - users.groups.apereo-cas = {}; - }; -} diff --git a/ops/nixos/v4l2loopback.nix b/ops/nixos/v4l2loopback.nix deleted file mode 100644 index 636b2ff6cf..0000000000 --- a/ops/nixos/v4l2loopback.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ config, lib, pkgs, ... }: - -{ - boot = { - extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ]; - kernelModules = [ "v4l2loopback" ]; - extraModprobeConfig = '' - options v4l2loopback exclusive_caps=1 - ''; - }; -} - diff --git a/ops/nixos/whitby/OWNERS b/ops/nixos/whitby/OWNERS deleted file mode 100644 index b1b749e871..0000000000 --- a/ops/nixos/whitby/OWNERS +++ /dev/null @@ -1,6 +0,0 @@ -inherited: false - -# Want in on this list? Try paying! -owners: - - lukegb - - tazjin diff --git a/ops/nixos/whitby/README.md b/ops/nixos/whitby/README.md deleted file mode 100644 index 55287c5412..0000000000 --- a/ops/nixos/whitby/README.md +++ /dev/null @@ -1,5 +0,0 @@ -whitby -====== - -`whitby.tvl.fyi` is our dedicated server providing continuous -integration services and other random nonsense. diff --git a/ops/nixos/whitby/default.nix b/ops/nixos/whitby/default.nix deleted file mode 100644 index 394b79c21b..0000000000 --- a/ops/nixos/whitby/default.nix +++ /dev/null @@ -1,458 +0,0 @@ -{ depot, lib, pkgs, ... }: - -let - inherit (builtins) listToAttrs; - inherit (lib) range; -in lib.fix(self: { - imports = [ - "${depot.depotPath}/ops/nixos/clbot.nix" - "${depot.depotPath}/ops/nixos/irccat.nix" - "${depot.depotPath}/ops/nixos/monorepo-gerrit.nix" - "${depot.depotPath}/ops/nixos/panettone.nix" - "${depot.depotPath}/ops/nixos/paroxysm.nix" - "${depot.depotPath}/ops/nixos/smtprelay.nix" - "${depot.depotPath}/ops/nixos/sourcegraph.nix" - "${depot.depotPath}/ops/nixos/tvl-buildkite.nix" - "${depot.depotPath}/ops/nixos/tvl-slapd/default.nix" - "${depot.depotPath}/ops/nixos/tvl-sso/default.nix" - "${depot.depotPath}/ops/nixos/www/b.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/cache.tvl.su.nix" - "${depot.depotPath}/ops/nixos/www/cl.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/code.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/cs.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/login.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/tazj.in.nix" - "${depot.depotPath}/ops/nixos/www/todo.tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/tvl.fyi.nix" - "${depot.depotPath}/ops/nixos/www/wigglydonke.rs.nix" - "${pkgs.path}/nixos/modules/services/web-apps/gerrit.nix" - ]; - - hardware = { - enableRedistributableFirmware = true; - cpu.amd.updateMicrocode = true; - }; - - boot = { - tmpOnTmpfs = true; - kernelModules = [ "kvm-amd" ]; - supportedFilesystems = [ "zfs" ]; - - initrd = { - availableKernelModules = [ - "igb" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sr_mod" - ]; - - # Enable SSH in the initrd so that we can enter disk encryption - # passwords remotely. - network = { - enable = true; - ssh = { - enable = true; - port = 2222; - authorizedKeys = - depot.users.tazjin.keys.all - ++ depot.users.lukegb.keys.all - ++ [ depot.users.glittershark.keys.whitby ]; - - hostKeys = [ - /etc/secrets/initrd_host_ed25519_key - ]; - }; - - # this will launch the zfs password prompt on login and kill the - # other prompt - postCommands = '' - echo "zfs load-key -a && killall zfs" >> /root/.profile - ''; - }; - }; - - kernel.sysctl = { - "net.ipv4.tcp_congestion_control" = "bbr"; - }; - - loader.grub = { - enable = true; - version = 2; - efiSupport = true; - efiInstallAsRemovable = true; - device = "/dev/disk/by-id/nvme-SAMSUNG_MZQLB1T9HAJR-00007_S439NA0N201620"; - }; - - zfs.requestEncryptionCredentials = true; - }; - - fileSystems = { - "/" = { - device = "zroot/root"; - fsType = "zfs"; - }; - - "/boot" = { - device = "/dev/disk/by-uuid/073E-7FBD"; - fsType = "vfat"; - }; - - "/nix" = { - device = "zroot/nix"; - fsType = "zfs"; - }; - - "/home" = { - device = "zroot/home"; - fsType = "zfs"; - }; - }; - - networking = { - # Glass is boring, but Luke doesn't like Wapping - the Prospect of - # Whitby, however, is quite a pleasant establishment. - hostName = "whitby"; - domain = "tvl.fyi"; - hostId = "b38ca543"; - useDHCP = false; - - # Don't use Hetzner's DNS servers. - nameservers = [ - "8.8.8.8" - "8.8.4.4" - ]; - - defaultGateway6 = { - address = "fe80::1"; - interface = "enp196s0"; - }; - - firewall.allowedTCPPorts = [ 22 80 443 4238 29418 ]; - - interfaces.enp196s0.useDHCP = true; - interfaces.enp196s0.ipv6.addresses = [ - { - address = "2a01:04f8:0242:5b21::feed:edef:beef"; - prefixLength = 64; - } - ]; - }; - - # Generate an immutable /etc/resolv.conf from the nameserver settings - # above (otherwise DHCP overwrites it): - environment.etc."resolv.conf" = with lib; { - source = pkgs.writeText "resolv.conf" '' - ${concatStringsSep "\n" (map (ns: "nameserver ${ns}") self.networking.nameservers)} - options edns0 - ''; - }; - - # Disable background git gc system-wide, as it has a tendency to break CI. - environment.etc."gitconfig".source = pkgs.writeText "gitconfig" '' - [gc] - autoDetach = false - ''; - - time.timeZone = "UTC"; - - nix = { - nrBuildUsers = 256; - maxJobs = lib.mkDefault 64; - extraOptions = '' - secret-key-files = /etc/secrets/nix-cache-privkey - ''; - - trustedUsers = [ - "grfn" - "lukegb" - "tazjin" - "sterni" - ]; - - sshServe = { - enable = true; - keys = with depot.users; - tazjin.keys.all - ++ lukegb.keys.all - ++ [ glittershark.keys.whitby ] - ++ sterni.keys.all - ; - }; - }; - - programs.mtr.enable = true; - programs.mosh.enable = true; - services.openssh = { - enable = true; - passwordAuthentication = false; - challengeResponseAuthentication = false; - }; - - # Run a handful of Buildkite agents to support parallel builds. - services.depot.buildkite = { - enable = true; - agentCount = 32; - }; - - # Start a local SMTP relay to Gmail (used by gerrit) - services.depot.smtprelay = { - enable = true; - args = { - listen = ":2525"; - remote_host = "smtp.gmail.com:587"; - remote_auth = "plain"; - remote_user = "tvlbot@tazj.in"; - }; - }; - - # Start the Gerrit->IRC bot - services.depot.clbot = { - enable = true; - - # Almost all configuration values are already correct (well, duh), - # see //fun/clbot for details. - flags = { - gerrit_host = "cl.tvl.fyi:29418"; - gerrit_ssh_auth_username = "clbot"; - gerrit_ssh_auth_key = "/etc/secrets/clbot-key"; - irc_server = "znc.lukegb.com:6697"; - - notify_branches = "canon,refs/meta/config"; - notify_repo = "depot"; - - # This secret is read from an environment variable, which is - # populated from /etc/secrets/clbot - irc_pass = "$CLBOT_PASS"; - }; - - channels = [ - "##tvl" - "##tvl-dev" - ]; - }; - - services.depot = { - # Run a SourceGraph code search instance - sourcegraph.enable = true; - - # Run the Panettone issue tracker - panettone = { - enable = true; - dbUser = "panettone"; - dbName = "panettone"; - secretsFile = "/etc/secrets/panettone"; - irccatChannel = "##tvl,##tvl-dev"; - }; - - # Run the first cursed bot (quote bot) - paroxysm.enable = true; - - # Run irccat to forward messages to IRC - irccat = { - enable = true; - config = { - tcp.listen = ":4722"; # "ircc" - irc = { - server = "chat.freenode.net:6697"; - tls = true; - nick = "tvlbot"; - realname = "TVL Bot"; - channels = [ - "##tvl" - "##tvl-dev" - ]; - }; - }; - }; - }; - - services.postgresql = { - enable = true; - enableTCPIP = true; - - authentication = lib.mkForce '' - local all all trust - host all all 127.0.0.1/32 password - host all all ::1/128 password - hostnossl all all 127.0.0.1/32 password - hostnossl all all ::1/128 password - ''; - - ensureDatabases = [ - "panettone" - ]; - - ensureUsers = [{ - name = "panettone"; - ensurePermissions = { - "DATABASE panettone" = "ALL PRIVILEGES"; - }; - }]; - }; - - services.postgresqlBackup = { - enable = true; - databases = [ - "tvldb" - "panettone" - ]; - }; - - services.nix-serve = { - enable = true; - port = 6443; - secretKeyFile = "/etc/secrets/nix-cache-key.sec"; - bindAddress = "localhost"; - }; - - environment.systemPackages = with pkgs; [ - bb - curl - emacs-nox - git - htop - nano - rxvt_unicode.terminfo - vim - zfs - zfstools - ]; - - # Run cgit for the depot. The onion here is nginx(thttpd(cgit)). - systemd.services.cgit = { - wantedBy = [ "multi-user.target" ]; - script = "${depot.web.cgit-taz}/bin/cgit-launch"; - - serviceConfig = { - Restart = "on-failure"; - User = "git"; - Group = "git"; - }; - }; - - # Regularly back up whitby to Google Cloud Storage. - systemd.services.restic = { - description = "Backups to Google Cloud Storage"; - script = "${pkgs.restic}/bin/restic backup /var/lib/gerrit /var/backup/postgresql"; - - environment = { - GOOGLE_PROJECT_ID = "tazjins-infrastructure"; - GOOGLE_APPLICATION_CREDENTIALS = "/var/backup/restic/gcp-key.json"; - RESTIC_REPOSITORY = "gs:tvl-fyi-backups:/whitby"; - RESTIC_PASSWORD_FILE = "/var/backup/restic/secret"; - RESTIC_CACHE_DIR = "/var/backup/restic/cache"; - RESTIC_EXCLUDE_FILE = builtins.toFile "exclude-files" '' - /var/lib/gerrit/tmp - ''; - }; - }; - - systemd.timers.restic = { - wantedBy = [ "multi-user.target" ]; - timerConfig.OnCalendar = "hourly"; - }; - - services.journaldriver = { - enable = true; - googleCloudProject = "tvl-fyi"; - logStream = "whitby"; - applicationCredentials = "/var/lib/journaldriver/key.json"; - }; - - security.sudo.extraRules = [ - { - groups = ["wheel"]; - commands = [{ command = "ALL"; options = ["NOPASSWD"]; }]; - } - ]; - - users = { - users.tazjin = { - isNormalUser = true; - extraGroups = [ "git" "wheel" ]; - shell = pkgs.fish; - openssh.authorizedKeys.keys = depot.users.tazjin.keys.all; - }; - - users.lukegb = { - isNormalUser = true; - extraGroups = [ "git" "wheel" ]; - openssh.authorizedKeys.keys = depot.users.lukegb.keys.all; - }; - - users.grfn = { - isNormalUser = true; - extraGroups = [ "git" "wheel" ]; - openssh.authorizedKeys.keys = [ - depot.users.glittershark.keys.whitby - ]; - }; - - users.isomer = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.isomer.keys.all; - }; - - users.riking = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.riking.keys.u2f ++ depot.users.riking.keys.passworded; - }; - - users.edef = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.edef.keys.all; - }; - - users.qyliss = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.qyliss.keys.all; - }; - - users.eta = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.eta.keys.whitby; - }; - - users.cynthia = { - isNormalUser = true; # I'm normal OwO :3 - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.cynthia.keys.all; - }; - - users.firefly = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.firefly.keys.whitby; - }; - - users.sterni = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.sterni.keys.all; - }; - - users.flokli = { - isNormalUser = true; - extraGroups = [ "git" ]; - openssh.authorizedKeys.keys = depot.users.flokli.keys.all; - }; - - # Set up a user & group for git shenanigans - groups.git = {}; - users.git = { - group = "git"; - isNormalUser = false; - createHome = true; - home = "/var/lib/git"; - }; - }; - - security.acme = { - acceptTerms = true; - email = "certs@tvl.fyi"; - }; - - system.stateVersion = "20.03"; -}) diff --git a/ops/nixos/www/b.tvl.fyi.nix b/ops/nixos/www/b.tvl.fyi.nix deleted file mode 100644 index 45f6c6ed51..0000000000 --- a/ops/nixos/www/b.tvl.fyi.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ config, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."b-shortlink" = { - serverName = "b"; - extraConfig = "return 302 https://b.tvl.fyi$request_uri;"; - }; - - services.nginx.virtualHosts."b.tvl.fyi" = { - serverName = "b.tvl.fyi"; - serverAliases = [ "b.tvl.su" ]; - enableACME = true; - forceSSL = true; - - extraConfig = '' - # Forward short links to issues to the issue itself (b/32) - location ~ ^/(\d+)$ { - return 302 https://b.tvl.fyi/issues$request_uri; - } - - location / { - proxy_pass http://localhost:${toString config.services.depot.panettone.port}; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/base.nix b/ops/nixos/www/base.nix deleted file mode 100644 index 4b956cd95e..0000000000 --- a/ops/nixos/www/base.nix +++ /dev/null @@ -1,36 +0,0 @@ -{ config, pkgs, ... }: - -{ - config = { - services.nginx = { - enable = true; - enableReload = true; - - recommendedTlsSettings = true; - recommendedGzipSettings = true; - recommendedProxySettings = true; - }; - - # NixOS 20.03 broke nginx and I can't be bothered to debug it - # anymore, all solution attempts have failed, so here's a - # brute-force fix. - # - # TODO(tazjin): Find a link to the upstream issue and see if - # they've sorted it after ~20.09 - systemd.services.fix-nginx = { - script = "${pkgs.coreutils}/bin/chown -f -R nginx: /var/spool/nginx /var/cache/nginx"; - - serviceConfig = { - User = "root"; - Type = "oneshot"; - }; - }; - - systemd.timers.fix-nginx = { - wantedBy = [ "multi-user.target" ]; - timerConfig = { - OnCalendar = "minutely"; - }; - }; - }; -} diff --git a/ops/nixos/www/cache.tvl.su.nix b/ops/nixos/www/cache.tvl.su.nix deleted file mode 100644 index 182306bebf..0000000000 --- a/ops/nixos/www/cache.tvl.su.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ config, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."cache.tvl.su" = { - serverName = "cache.tvl.su"; - serverAliases = [ "cache.tvl.fyi" ]; - enableACME = true; - forceSSL = true; - - extraConfig = '' - location = /cache-key.pub { - alias /etc/secrets/nix-cache-key.pub; - } - - location / { - proxy_pass http://localhost:${toString config.services.nix-serve.port}; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/cl.tvl.fyi.nix b/ops/nixos/www/cl.tvl.fyi.nix deleted file mode 100644 index 470122c395..0000000000 --- a/ops/nixos/www/cl.tvl.fyi.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ config, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."cl-shortlink" = { - serverName = "cl"; - extraConfig = "return 302 https://cl.tvl.fyi$request_uri;"; - }; - - services.nginx.virtualHosts.gerrit = { - serverName = "cl.tvl.fyi"; - serverAliases = [ "cl.tvl.su" ]; - enableACME = true; - forceSSL = true; - - extraConfig = '' - location / { - proxy_pass http://localhost:4778; - proxy_set_header X-Forwarded-For $remote_addr; - # The :443 suffix is a workaround for https://b.tvl.fyi/issues/88. - proxy_set_header Host $host:443; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/code.tvl.fyi.nix b/ops/nixos/www/code.tvl.fyi.nix deleted file mode 100644 index c8a4b27b1b..0000000000 --- a/ops/nixos/www/code.tvl.fyi.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ depot, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts.cgit = { - serverName = "code.tvl.fyi"; - serverAliases = [ "code.tvl.su" ]; - enableACME = true; - forceSSL = true; - - extraConfig = '' - # Serve the rendered Tvix component SVG. - # - # TODO(tazjin): Implement a way of serving this dynamically - location = /about/tvix/docs/component-flow.svg { - alias ${depot.tvix.docs.svg}/component-flow.svg; - } - - # Static assets must always hit the root. - location ~ ^/(favicon\.ico|cgit\.(css|png))$ { - proxy_pass http://localhost:2448; - } - - # Everything else hits the depot directly. - location / { - proxy_pass http://localhost:2448/cgit.cgi/depot/; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/cs.tvl.fyi.nix b/ops/nixos/www/cs.tvl.fyi.nix deleted file mode 100644 index fac814baf0..0000000000 --- a/ops/nixos/www/cs.tvl.fyi.nix +++ /dev/null @@ -1,31 +0,0 @@ -{ config, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."cs.tvl.fyi" = { - serverName = "cs.tvl.fyi"; - serverAliases = [ "cs.tvl.su" ]; - enableACME = true; - forceSSL = true; - - extraConfig = '' - location = / { - return 301 https://cs.tvl.fyi/depot; - } - - location / { - proxy_set_header X-Sg-Auth "Anonymous"; - proxy_pass http://localhost:${toString config.services.depot.sourcegraph.port}; - } - - location /users/Anonymous/settings { - return 301 https://cs.tvl.fyi; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/login.tvl.fyi.nix b/ops/nixos/www/login.tvl.fyi.nix deleted file mode 100644 index 05b7cee253..0000000000 --- a/ops/nixos/www/login.tvl.fyi.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."login.tvl.fyi" = { - serverName = "login.tvl.fyi"; - enableACME = true; - forceSSL = true; - - extraConfig = '' - location / { - proxy_pass http://localhost:8443; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto https; - proxy_set_header Host $host; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/tazj.in.nix b/ops/nixos/www/tazj.in.nix deleted file mode 100644 index 7d658a5ec4..0000000000 --- a/ops/nixos/www/tazj.in.nix +++ /dev/null @@ -1,40 +0,0 @@ -# serve tazjin's website & blog -{ depot, config, lib, pkgs, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."tazj.in" = { - enableACME = true; - forceSSL = true; - root = depot.users.tazjin.homepage; - - extraConfig = '' - ${depot.users.tazjin.blog.oldRedirects} - location /blog/ { - alias ${depot.users.tazjin.blog.rendered}/; - - if ($request_uri ~ ^/(.*)\.html$) { - return 302 /$1; - } - - try_files $uri $uri.html $uri/ =404; - } - - # Temporary place for serving static files. - location /blobs/ { - alias /var/lib/tazjins-blobs/; - } - ''; - }; - - services.nginx.virtualHosts."git.tazj.in" = { - enableACME = true; - forceSSL = true; - extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; - }; - }; -} diff --git a/ops/nixos/www/todo.tvl.fyi.nix b/ops/nixos/www/todo.tvl.fyi.nix deleted file mode 100644 index b53f5437e7..0000000000 --- a/ops/nixos/www/todo.tvl.fyi.nix +++ /dev/null @@ -1,25 +0,0 @@ -{ depot, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."todo.tvl.fyi" = { - serverName = "todo.tvl.fyi"; - serverAliases = [ "todo.tvl.su" ]; - root = depot.web.todolist; - enableACME = true; - forceSSL = true; - - extraConfig = '' - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - - location ~* \.(webp|woff2)$ { - add_header Cache-Control "public, max-age=31536000"; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/tvl.fyi.nix b/ops/nixos/www/tvl.fyi.nix deleted file mode 100644 index 45fd35803d..0000000000 --- a/ops/nixos/www/tvl.fyi.nix +++ /dev/null @@ -1,30 +0,0 @@ -{ depot, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."tvl.fyi" = { - serverName = "tvl.fyi"; - root = depot.web.tvl; - enableACME = true; - forceSSL = true; - - extraConfig = '' - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - - rewrite ^/builds/?$ https://buildkite.com/tvl/depot/ last; - - rewrite ^/monorepo-doc/?$ https://docs.google.com/document/d/1nnyByXcH0F6GOmEezNOUa2RFelpeRpDToBLYD_CtjWE/edit?usp=sharing last; - - rewrite ^/irc/?$ ircs://chat.freenode.net:6697/##tvl last; - - location ~* \.(webp|woff2)$ { - add_header Cache-Control "public, max-age=31536000"; - } - ''; - }; - }; -} diff --git a/ops/nixos/www/wigglydonke.rs.nix b/ops/nixos/www/wigglydonke.rs.nix deleted file mode 100644 index 0bc67898c6..0000000000 --- a/ops/nixos/www/wigglydonke.rs.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ depot, lib, pkgs, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."wigglydonke.rs" = { - enableACME = true; - forceSSL = true; - root = "${depot.depotPath}/users/glittershark/wigglydonke.rs"; - }; - }; -} diff --git a/users/glittershark/system/system/machines/chupacabra.nix b/users/glittershark/system/system/machines/chupacabra.nix index 4f7f39ee5a..974e3c34e3 100644 --- a/users/glittershark/system/system/machines/chupacabra.nix +++ b/users/glittershark/system/system/machines/chupacabra.nix @@ -7,7 +7,7 @@ ../modules/tvl.nix ../modules/fcitx.nix ../modules/rtlsdr.nix - ../../../../../ops/nixos/v4l2loopback.nix + ../../../../../ops/modules/v4l2loopback.nix ../modules/desktop.nix ../modules/development.nix ]; diff --git a/users/tazjin/nixos/README.md b/users/tazjin/nixos/README.md index 0093f4ac65..662f2a36ac 100644 --- a/users/tazjin/nixos/README.md +++ b/users/tazjin/nixos/README.md @@ -1,20 +1,17 @@ NixOS configuration =================== -My NixOS configuration! It configures most of the packages I require +My NixOS configurations! It configures most of the packages I require on my systems, sets up Emacs the way I need and does a bunch of other interesting things. -System configuration lives in folders for each machine and a custom -fixed point evaluation (similar to standard NixOS module -configuration) is used to combine configuration together. +System configuration lives in folders, and some of the modules stem +from `//ops/modules`. -Building `ops.nixos.rebuilder` yields a script that will automatically -build and activate the newest configuration based on the current -hostname. +Machines are deployed with the script at `ops.nixos.rebuild-system`. ## Configured hosts: -* `frog` - weapon of mass computation at home -* `camden` - NUC serving tazj.in, tvl.fyi & co -* ~~`urdhva` - T470s~~ (currently with edef) +* `tverskoy` - X13 AMD that's travelling around with me +* `frog` - weapon of mass computation (in storage in London) +* `camden` - NUC formerly serving tazj.in (in storage in London) diff --git a/users/tazjin/nixos/camden/default.nix b/users/tazjin/nixos/camden/default.nix index f334320b38..2659db5e91 100644 --- a/users/tazjin/nixos/camden/default.nix +++ b/users/tazjin/nixos/camden/default.nix @@ -25,8 +25,8 @@ in lib.fix(self: { sha256 = "157c64220lf825ll4c0cxsdwg7cxqdx4z559fdp7kpz0g6p8fhhr"; }; in [ - "${depot.depotPath}/ops/nixos/quassel.nix" - "${depot.depotPath}/ops/nixos/smtprelay.nix" + "${depot.depotPath}/ops/modules/quassel.nix" + "${depot.depotPath}/ops/modules/smtprelay.nix" "${oldChannel}/nixos/modules/security/acme.nix" ]; diff --git a/users/tazjin/nixos/frog/default.nix b/users/tazjin/nixos/frog/default.nix index 7f709da7ee..1394f9cf4e 100644 --- a/users/tazjin/nixos/frog/default.nix +++ b/users/tazjin/nixos/frog/default.nix @@ -16,7 +16,7 @@ config: let }; in lib.fix(self: { imports = [ - "${depot.depotPath}/ops/nixos/v4l2loopback.nix" + "${depot.depotPath}/ops/modules/v4l2loopback.nix" ]; boot = { -- cgit 1.4.1