about summary refs log tree commit diff
path: root/systems/cobalt
diff options
context:
space:
mode:
authorsefidel <contact@sefidel.net>2023-03-29 20:54:19 +0900
committersefidel <contact@sefidel.net>2023-04-03 18:32:29 +0900
commitce06f43476863da90dc60dcee606d2b6c5a89a8e (patch)
tree5d14946330cb09ff0ebd97bee59407fccee4d860 /systems/cobalt
downloadinfra-ce06f43476863da90dc60dcee606d2b6c5a89a8e.tar.gz
infra-ce06f43476863da90dc60dcee606d2b6c5a89a8e.zip
project: initial commit
Diffstat (limited to 'systems/cobalt')
-rw-r--r--systems/cobalt/default.nix303
-rw-r--r--systems/cobalt/hardware-configuration.nix65
-rw-r--r--systems/cobalt/secrets/secrets.yaml39
3 files changed, 407 insertions, 0 deletions
diff --git a/systems/cobalt/default.nix b/systems/cobalt/default.nix
new file mode 100644
index 0000000..0a5cfe0
--- /dev/null
+++ b/systems/cobalt/default.nix
@@ -0,0 +1,303 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+  ipv4 = {
+    address = "95.216.74.104";
+    gateway = "95.216.74.65";
+    netmask = "255.255.255.192";
+    prefixLength = 26; # https://www.pawprint.net/designresources/netmask-converter.php
+  };
+  ipv6 = {
+    address = "2a01:4f9:2b:a98::";
+    gateway = "fe80::1";
+    prefixLength = 64;
+  };
+  networkInterface = "eth0";
+  hostName = "cobalt";
+  hostId = "712ae82a";
+  hostAddr = "cobalt.exotic.sh";
+
+  poorObfuscation = y: x: "${x}@${y}";
+in
+{
+  deployment = {
+    targetHost = hostAddr;
+    targetPort = 22;
+    targetUser = "root";
+  };
+
+  imports = [ ./hardware-configuration.nix ];
+
+  boot.supportedFilesystems = [ "zfs" ];
+  networking.hostId = hostId;
+
+  boot.loader.grub.enable = true;
+  # boot.loader.grub.version = 2;
+  boot.loader.grub.efiSupport = false;
+  # boot.loader.grub.device = "nodev";
+
+  # This should be done automatically, but explicitly declare it just in case.
+  boot.loader.grub.copyKernels = true;
+  # Make sure that you've listed all of the boot partitions here.
+  boot.loader.grub.mirroredBoots = [
+    { path = "/boot"; devices = [ "/dev/disk/by-id/ata-ST4000NM0245-1Z2107_ZC17GW7G" ]; }
+    { path = "/boot-fallback"; devices = [ "/dev/disk/by-id/ata-ST4000NM0245-1Z2107_ZC17GWB2" ]; }
+  ];
+
+  # Boot normally when one of the boot partitions are missing
+  fileSystems."/boot".options = [ "nofail" ];
+  fileSystems."/boot-fallback".options = [ "nofail" ];
+
+  # Erase your darlings
+  # boot.initrd.postDeviceCommands = lib.mkAfter ''nix systemd environ
+  # zfs rollback -r rpool/local/root@blank
+  # '';
+
+  # NOTE: replace these to boot.initrd.availableKernelModules?
+  boot.kernelModules = [ "e1000e" ];
+  boot.initrd.kernelModules = [ "e1000e" ];
+
+  boot.kernelParams = [
+    # See <https:#www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt> for documentation.
+    # ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>:<ntp0-ip>
+    # The server ip refers to the NFS server -- not needed in this case.
+    "ip=${ipv4.address}::${ipv4.gateway}:${ipv4.netmask}:${hostName}-initrd:${networkInterface}:off:8.8.8.8"
+  ];
+
+  boot.initrd.network.enable = true;
+  boot.initrd.network.ssh = {
+    enable = true;
+
+    # Using the same port as the actual SSH will cause clients to throw errors
+    # related to host key mismatch.
+    port = 2222;
+
+    # This takes 'path's, not 'string's.
+    hostKeys = [
+      /boot/initrd-ssh-key
+      /boot-fallback/initrd-ssh-key
+    ];
+
+    # Public ssh key to log into the initrd ssh
+    authorizedKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILN14b5Fu+StHeMXq4ClyLG4G+/vCAfS7adxceEFria/ openpgp:0x1D5BCD11" ];
+  };
+  boot.initrd.network.postCommands = ''
+    cat <<EOF > /root/.profile
+    if pgrep -x "zfs" > /dev/null
+    then
+      zfs load-key -a
+      killall zfs
+    else
+      echo "ZFS is not running -- this could be a sign of failure."
+    fi
+    EOF
+  '';
+
+
+  networking.hostName = hostName;
+
+  networking.useDHCP = false;
+  networking.interfaces.${networkInterface} = {
+    ipv4 = { addresses = [{ address = ipv4.address; prefixLength = ipv4.prefixLength; }]; };
+    ipv6 = { addresses = [{ address = ipv6.address; prefixLength = ipv6.prefixLength; }]; };
+  };
+  networking.defaultGateway = ipv4.gateway;
+  networking.defaultGateway6 = { address = ipv6.gateway; interface = networkInterface; };
+  networking.nameservers = [ "8.8.8.8" ];
+
+  networking.firewall.enable = true;
+
+  time.timeZone = "UTC";
+
+  users.users.root.initialHashedPassword = ""; # FIXME: use proper secret
+  users.users.root.openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILN14b5Fu+StHeMXq4ClyLG4G+/vCAfS7adxceEFria/ openpgp:0x1D5BCD11" ];
+  services.openssh.enable = true;
+  services.openssh.settings.permitRootLogin = "prohibit-password";
+
+  services.openssh.hostKeys = [
+    {
+      path = "/persist/ssh/ssh_host_ed25519_key";
+      type = "ed25519";
+    }
+    {
+      path = "/persist/ssh/ssh_host_rsa_key";
+      type = "rsa";
+      bits = 4096;
+    }
+  ];
+
+  # impermanence requirement
+  fileSystems."/persist".neededForBoot = true;
+
+  environment.systemPackages = with pkgs; [
+    bsd-finger
+  ];
+
+  sops.secrets.acme-envs = {
+    owner = "acme";
+  };
+  sops.secrets.matrix-server-key = { };
+  sops.secrets.dendrite-envs = { };
+  sops.secrets.sliding-sync-secret = { };
+  sops.secrets.mjolnir-password = { owner = "mjolnir"; };
+  sops.secrets.mautrix-telegram-envs = { };
+  sops.secrets.turn-secret = { };
+  # sops.secrets.openldap-admin-key = {
+  # owner = "openldap";
+  # };
+
+  modules = {
+    sops.enable = true;
+
+    services.metrics = {
+      enable = true;
+      domain = "status.exotic.sh";
+      tls.acmeHost = "exotic.sh";
+    };
+
+    services.coredns.enable = false;
+    services.nginx.enable = true;
+    services.acme = {
+      enable = true;
+      email = poorObfuscation "exotic.sh" "postmaster";
+
+      certs = {
+        "exotic.sh" = {
+          subDomains = [
+            "git"
+            "matrix"
+            "*.labs"
+            "social"
+            "bouncer"
+            "meet"
+            "chat"
+            "turn"
+            "status"
+            "mail"
+            "todo"
+          ];
+        };
+        "nand.moe" = {
+          subDomains = [ ];
+        };
+        "sefidel.net" = {
+          subDomains = [ ];
+        };
+      };
+
+      secrets.acme-credentials = config.sops.secrets.acme-envs.path;
+    };
+
+    services.gitolite = {
+      enable = true;
+      adminPubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILN14b5Fu+StHeMXq4ClyLG4G+/vCAfS7adxceEFria/ openpgp:0x1D5BCD11";
+    };
+    services.gitDaemon.enable = true;
+    services.cgit = {
+      enable = true;
+      domain = "exotic.sh";
+      realHost = "git.exotic.sh";
+      settings.description = "Exotic place.";
+    };
+    services.fail2ban.enable = true;
+    services.postgresql.enable = true;
+    services.dendrite = {
+      enable = true;
+      domain = "exotic.sh";
+      realHost = "matrix.exotic.sh";
+      slidingSyncHost = "slidingsync.labs.exotic.sh";
+      turn = {
+        enable = true;
+        domain = "turn.exotic.sh";
+        shared_secret = "$TURN_SECRET"; # dendrite envs
+      };
+      secrets = {
+        matrix-server-key = config.sops.secrets.matrix-server-key.path;
+        dendrite-envs = config.sops.secrets.dendrite-envs.path;
+        sliding-sync-secret = config.sops.secrets.sliding-sync-secret.path;
+      };
+    };
+    services.coturn = {
+      enable = true;
+      domain = "turn.exotic.sh";
+      tls.acmeHost = "exotic.sh";
+      shared_secret = config.sops.secrets.turn-secret.path;
+    };
+    services.matrix-moderation = {
+      enable = true;
+      domain = "exotic.sh";
+      secrets.userPassword = config.sops.secrets.mjolnir-password.path;
+    };
+    services.matrix-bridge = {
+      enable = true;
+      domain = "exotic.sh";
+      secrets.mautrix-envs = config.sops.secrets.mautrix-telegram-envs.path;
+    };
+    services.element-web = {
+      enable = true;
+      hostName = "chat.exotic.sh";
+      matrix = {
+        baseUrl = "https://matrix.exotic.sh";
+        serverName = "exotic.sh";
+      };
+      tls.acmeHost = "exotic.sh";
+      jitsi.domain = "meet.exotic.sh";
+    };
+    services.akkoma = {
+      enable = true;
+      domain = "exotic.sh";
+      realHost = "social.exotic.sh";
+      instanceName = "exotic.sh social";
+    };
+    services.misskey = {
+      enable = true;
+      domain = "nand.moe";
+      realHost = "nand.moe";
+    };
+    services.soju = {
+      enable = true;
+      hostName = "bouncer.exotic.sh";
+      tls.enable = true;
+      tls.acmeHost = "exotic.sh";
+    };
+    services.vikunja = {
+      enable = true;
+      domain = "exotic.sh";
+      realHost = "todo.exotic.sh";
+    };
+
+
+    services.nixos-mailserver.enable = true; # TODO: replace with dovecot.nix?
+
+    services.jitsi = {
+      enable = true;
+      hostName = "meet.exotic.sh";
+      tls.acmeHost = "exotic.sh";
+    };
+
+    services.ldap = {
+      enable = false;
+      dc = "exotic";
+      tld = "sh";
+      tls.acmeHost = "exotic.sh";
+      secrets.rootPass = config.sops.secrets.openldap-admin-key.path;
+    };
+    services.pubnix.enable = false;
+    services.userweb = {
+      enable = false;
+      domain = "exotic.sh";
+    };
+
+    services.sefidel-web.enable = true;
+  };
+
+  # This value determines the NixOS release from which the default
+  # settings for stateful data, like file locations and database versions
+  # on your system were taken. It‘s perfectly fine and recommended to leave
+  # this value at the release version of the first install of this system.
+  # Before changing this value read the documentation for this option
+  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
+  system.stateVersion = "23.05"; # Did you read the comment?
+}
+
diff --git a/systems/cobalt/hardware-configuration.nix b/systems/cobalt/hardware-configuration.nix
new file mode 100644
index 0000000..95ecb96
--- /dev/null
+++ b/systems/cobalt/hardware-configuration.nix
@@ -0,0 +1,65 @@
+# Do not modify this file!  It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations.  Please make changes
+# to /etc/nixos/configuration.nix instead.
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+  imports =
+    [
+      (modulesPath + "/installer/scan/not-detected.nix")
+    ];
+
+  boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "sd_mod" ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ "kvm-intel" ];
+  boot.extraModulePackages = [ ];
+
+  fileSystems."/" =
+    {
+      device = "rpool/local/root";
+      fsType = "zfs";
+    };
+
+  fileSystems."/boot" =
+    {
+      device = "/dev/disk/by-uuid/445A-0C55";
+      fsType = "vfat";
+    };
+
+  fileSystems."/boot-fallback" =
+    {
+      device = "/dev/disk/by-uuid/445C-198F";
+      fsType = "vfat";
+    };
+
+  fileSystems."/nix" =
+    {
+      device = "rpool/local/nix";
+      fsType = "zfs";
+    };
+
+  fileSystems."/home" =
+    {
+      device = "rpool/safe/home";
+      fsType = "zfs";
+    };
+
+  fileSystems."/persist" =
+    {
+      device = "rpool/safe/persist";
+      fsType = "zfs";
+    };
+
+  swapDevices = [ ];
+
+  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+  # (the default) this is the recommended approach. When using systemd-networkd it's
+  # still possible to use this option, but it's recommended to use it in conjunction
+  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+  networking.useDHCP = lib.mkDefault false;
+  # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true;
+
+  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+  powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
+  hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
+}
diff --git a/systems/cobalt/secrets/secrets.yaml b/systems/cobalt/secrets/secrets.yaml
new file mode 100644
index 0000000..8e0c0e5
--- /dev/null
+++ b/systems/cobalt/secrets/secrets.yaml
@@ -0,0 +1,39 @@
+acme-envs: ENC[AES256_GCM,data:9IvoY1E2VLikZgPcNnEl2e33SMgLOJsX7aVTEbld1ggl8Z77a2iau17d/ZLWs0+u,iv:gr2iHuYmtZp2eWhX0E0OKolIn/Nm5+9hJqFTYZagV4c=,tag:9mqUFzqe8+3T+Nwbu5V0Fg==,type:str]
+matrix-server-key: ENC[AES256_GCM,data:MsPH8g0bc0cY+k5XvVIyi1hDpX2up7+noU9P4Dfm3Z9f1eXv7SaJhlRnR40qrk4sQN1uG0R/ro7S2z9EswX0iZx10PfjWF8Igrc9w9b2+EM/gb0O3dGskPAnDrm9JYh+gF6SsqmwJUEYh+Lx1EfuGMTWpnXZjLrimIWCfmz/1qxJECQds/aQwuA=,iv:B8yzXZ1IUVVvxFQ0MzzS5LSHZXQirnXiLoOru4S2H78=,tag:TNp1Y3C/iYgq5itqXGIt/g==,type:str]
+mjolnir-password: ENC[AES256_GCM,data:dyM2VVxn1PFRXy5dgfvq3EuWyGDhDZvJOd1sTnKE5q0Arv1y,iv:DD80um8QXLybj1w4ZsxPbv3+s2NrQfpPDAEpkztkMFo=,tag:3ZEJ7V+ICh2Ip5gZt06zjA==,type:str]
+mautrix-telegram-envs: ENC[AES256_GCM,data:hDfEI6tshgPHn/yPHkqO9/VZnB/vTnuyopVm2/0CKoWska66UXOHbXwvO6UXXUZldzkvKe6min3O9xjEGBC+SZdLWmfi6AxJvoKnmU2MzufNkrDG4k0turK7LwwVnm8ADZd9tEII+P3h42t78jhkgerailjP1rtVKleAZpr+ioRGhCTAE6tVWnhV4jveUwNkml+0AhMc3aY0N2PLvedw8p/jsX6Yujn2baKc7HOkvAasctqq/p8kdiTZCA+ASIVC15iR+KtGu2V7vXjDuzYU7Xv7+RbXN7rUTCBIJwyc3XxpwOmD46XR+/2iSZ3nL0PmDftbIEaA9LatjUap7mRFOwX5JruAl1XxAGdG965HZFyTHp1UggjjWvoHQmyb1xJXD5ZE+EU8obkFV0N1o7Q4XIF6/REz9+01JrOd1F5GxjoAo29JV+1lhdxGykrFcA63VLsXdsUgZflWH7Rxol2nOMI5t88+zohYJ5OpeLlRD0gVaX8dvgSzvzmZaNxASW+9tHOQBSzkZsM6jEon6ZXeAa0oh/ee+W82jHhe/ohlj0UV7TtpW/QWs3NR3mv1x41TMBawnVQ7sb9UH/sbdbajJYEAkSD/32ETSjXiQJsmhGEj5kRBNAQA16s1o0M24+UnpHo71jqQnRQpOUtFhLQqakOWvSdM4KgIXExc87Fkw+bQxLtpIup+T4WpJkCe5f5rB/jHvob33oitzjS1mam9UTtzwQjTuR/P4V8IORygDHlcq8W2PtDhWOdgtWI9cfIlqIIgu6+7Rg4+1dq5aw8j06eWrNH2NElPMji0opN+onT3VflgwGPXHlemId20Z2TXNuE6LlnUhyyxdh0rw3tVuCDcodzj4HfXk9mbjlTufyGKY41K/A6QTotiHANojizuTyulyjI3Gx1Wvzv8+Ib84SZGl9ZSsg7g6Ig5U12IJhNtZ/vMj8MHpRjxnyRmZ4jsQi9UctDKrhHjulD1WJyhBveoEv8L79c6e0xZYAwkSlxvdaOPK3OMGbbtbH8vy7WYXSwHZomwJ7BrsrQ/5lWav2xXzgM7ASnEg/rKBPr9YQYOBA==,iv:K2qdi99cjom4mzcNH26qqX3gQNSvZzuAh9QY4zmZv9I=,tag:e9/4biFz6mVsGHV/YOA1jg==,type:str]
+dendrite-envs: ENC[AES256_GCM,data:67FnrGQUZWFfHAoUM/idTZlBX7aek3fbPkswB9+3pjLNQuXpIWYoa2vpdGt7zec2n9o9z0V3LdlkookjS95aPpZmKYwPaKkH2L7Jaxw=,iv:c4lEReLizcQeTTiG7cJwd+2sBH+EKBGycKeoDgJ/394=,tag:zBBxIcXn+8Q90BkPidltfQ==,type:str]
+sliding-sync-secret: ENC[AES256_GCM,data:lNIlUtNbXw1/w44m7RwqmvOTmc4MYfag7Nvo0izTM6Al7eOZXjEXGgfr7b4PB3QNewghN4LEEj1ae8HqpivT/w==,iv:Qw2XLjYp3/78OuEakUDJ0Sp3fmjw36IJTg8UKTZ7UEU=,tag:tp3gACPEZNMzj+aDP3Ax4A==,type:str]
+turn-secret: ENC[AES256_GCM,data:JA5/BlGwH6yIjYsFZGa8Nm8XVbOBKpre+NFybniOtlmbSx89ldKBvuqF2ZoPltJS+vzQ/+wxM/VorhF7M+s4jA==,iv:rK5SFj4VOzgfaP/LIzWTVFyCBmklGMSyd9iWbet2CVc=,tag:QycYCHH72bMMX5UubDHTlg==,type:str]
+openldap-admin-key: ENC[AES256_GCM,data:WBBDPFDW6Q4sJ5+/pK8kAe6iFgJ8gGgi3eCVNvZB,iv:1rnmhu29UGsXLxD9Ptbv7P67EAYgKVk1dlkM6p0L4vA=,tag:yNRrHMI2yT8Oo7qkwxSeUg==,type:str]
+sefidel-imap-pass: ENC[AES256_GCM,data:rx9hZb+BARs9gB+XLLRMLWDSx67KqkKB1/4nOOtU9i56uagMprFEeDnh8pEaioZbNlqjJRO8kWTBBvWZ,iv:WxKLp0VmwfxVFZt9cnZUbp4wn5WEHubImp8fQy2bXyg=,tag:Vzh0Ntz8iFaSIEf2wjbOKg==,type:str]
+internal-imap-pass: ENC[AES256_GCM,data:ydjz/NthnJZFLrR1M+p0xEy5xhM8MbPtqE10r0s1DWDFZoyXwRRrIYefFZheW29EjY3VBfr3zWcRIbNm,iv:6hU/dHADbn4pNi0vlJG8BoyQW1ohByINSO6y+nJddfY=,tag:j67D2stmq2A+ulhFIYkZPA==,type:str]
+sops:
+    kms: []
+    gcp_kms: []
+    azure_kv: []
+    hc_vault: []
+    age:
+        - recipient: age1jt8xg0lvzj5q4f7fn7nw670qsszm3kv3caa654eh62azra4x44zss4fad8
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvbE1CVEFaWXQ4M0lxR1dH
+            c2dJMGFxTS85ZDhlamRyQWl2Y3VxcXhVdm5RCml3MWl4dkZQK1Z5T3JqTnBLaVU1
+            R25PdXJBVWczMGt6RkNWWllXOFJicDAKLS0tIElJYytrUHhzb2xHeTJTRy82bFJR
+            bm11bEpUaFJjcHB0c2pRendiakRpS2cKNa9ZrFkOLfOqEEN9ATktvrQgANceDj2c
+            mkUjhxPfti4jNE2c6gsq3DegJT/08QpFJYYuAx/sO2R8wld3kFVyrQ==
+            -----END AGE ENCRYPTED FILE-----
+        - recipient: age14a2amn7memzvctf2nnrt6uj458x3g4jpcvs04tlkww2z02p05syqawxrwh
+          enc: |
+            -----BEGIN AGE ENCRYPTED FILE-----
+            YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4TEpsUmRQNUxDUU00VENS
+            MTgxN2ZjM0NYOEdaem5yaW1XaHdlandsQmtNCk5YSzdHdTFqa1BOSkZnajJJenhY
+            SFdnKzI2WmhONnJ2UWJjRWNGNUhuT0kKLS0tIHNRcVo2VXJEY0tSVUEwVkF0Z2l6
+            cUpBZ01CMEFjNnNuWjlYejVKajkwcGMKehqYCZP0zZHDTfJrC/5LYiE/3doa0OiM
+            OKXhOuUX8HF8RfkyiOSMpntxuNX2jSvd9sQRYnHkUvgm793+IuQjrg==
+            -----END AGE ENCRYPTED FILE-----
+    lastmodified: "2023-03-27T15:19:33Z"
+    mac: ENC[AES256_GCM,data:CyVH0paaTqnff98h5CSCas3YYYYAxEtyYdkjyFBfN/Nwfpe3e71O6YwLZgzAZoiaN+1FuF0kls5WmvDNdx95rEC4yvxQACA75iRyP95B5Q9iN9SGGld0Ii8wPY6s0QkJX+OL7mCllH/gC0J2gOpnPxRB9k5v5FXtKHmJtj5kfaI=,iv:ytWBOy2VTWtVlPbrXiHF5BNxbCmQ194x6aeMh1pd7vc=,tag:0J77TO1y8OTXzdODqANkEw==,type:str]
+    pgp: []
+    unencrypted_suffix: _unencrypted
+    version: 3.7.3