diff --git a/docs/administrative-access.md b/docs/administrative-access.md index 5c58e79..169f087 100644 --- a/docs/administrative-access.md +++ b/docs/administrative-access.md @@ -85,6 +85,39 @@ Example NixOS snippet for WireGuard client config #endpoint = "80.244.242.5:51820"; persistentKeepalive = 15; } + { + # trinkgenossin.pub.solar + publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4="; + allowedIPs = [ + "10.7.6.5/32" + "fd00:fae:fae:fae:fae:5::/96" + ]; + #endpoint = "85.215.152.22:51820"; + endpoint = "[2a01:239:35d:f500::1]:51820"; + persistentKeepalive = 15; + } + { + # delite.pub.solar + publicKey = "ZT2qGWgMPwHRUOZmTQHWCRX4m14YwOsiszjsA5bpc2k="; + allowedIPs = [ + "10.7.6.6/32" + "fd00:fae:fae:fae:fae:6::/96" + ]; + #endpoint = "5.255.119.132:51820"; + endpoint = "[2a04:52c0:124:9d8c::2]:51820"; + persistentKeepalive = 15; + } + { + # blue-shell.pub.solar + publicKey = "bcrIpWrKc1M+Hq4ds3aN1lTaKE26f2rvXhd+93QrzR8="; + allowedIPs = [ + "10.7.6.7/32" + "fd00:fae:fae:fae:fae:7::/96" + ]; + #endpoint = "194.13.83.205:51820"; + endpoint = "[2a03:4000:43:24e::1]:51820"; + persistentKeepalive = 15; + } ]; }; }; diff --git a/docs/backups.md b/docs/backups.md new file mode 100644 index 0000000..ccce5f9 --- /dev/null +++ b/docs/backups.md @@ -0,0 +1,36 @@ +# Backups + +We use [Restic](https://restic.readthedocs.io/en/stable/) to create backups and push them to two repositories. +Check `./modules/backups.nix` and `./hosts/nachtigall/backups.nix` for working examples. + +### Hetzner Storagebox + +- Uses SFTP for transfer of backups + +Adding a new host SSH public key to the storagebox: + +First, [SSH to nachtigall](./administrative-access.md#ssh-access), then become root and add the new SSH public key + +``` +sudo -i +echo '' | ssh -p23 u377325@u377325.your-storagebox.de install-ssh-key +``` + +[Link to Hetzner storagebox docs](https://docs.hetzner.com/robot/storage-box/backup-space-ssh-keys). + +### Garage S3 buckets + +- Uses S3 for transfer of backups +- One bucket per host, e.g. `nachtigall-backups`, `metronom-backups` + +To start transfering backups from a new hosts, this is how to create a new bucket: + +First, [SSH to trinkgenossin](./administrative-access.md#ssh-access), then use the `garage` CLI to create a new key and bucket: + +``` +export GARAGE_RPC_SECRET= + +garage bucket create -backups +garage key create -backups-key +garage bucket allow -backups --read --write --key -backups-key +``` diff --git a/docs/garage.md b/docs/garage.md new file mode 100644 index 0000000..e1e82fb --- /dev/null +++ b/docs/garage.md @@ -0,0 +1,49 @@ +# Garage + +### How-To create a new bucket + keys + +Requirements: + +- [Setup WireGuard](./administrative-access.md#ssh-access) for hosts: `trinkgenossin`, optionally: `delite`, `blue-shell` + +``` +ssh barkeeper@trinkgenossin.wg.pub.solar + +export GARAGE_RPC_SECRET= + +garage bucket create +garage key create -key +garage bucket allow --read --write --key -key +``` + +Docs: https://garagehq.deuxfleurs.fr/documentation/quick-start/#creating-buckets-and-keys + +Then [setup your favourite S3 client](https://garagehq.deuxfleurs.fr/documentation/connect/cli/) +or use the bucket with any [S3 compatible software](https://garagehq.deuxfleurs.fr/documentation/connect/). + +### Notes on manual setup steps + +``` +ssh barkeeper@trinkgenossin.wg.pub.solar + +export GARAGE_RPC_SECRET= + +# Uses the default config /etc/garage.toml +garage node id + +garage node connect +garage node connect + +garage status + +#Zones +#DE-1 DE-2 NL-1 + +garage layout assign fdaa -z DE-1 -c 800G -t trinkgenossin +garage layout assign 8835 -z DE-2 -c 800G -t blue-shell +garage layout assign 73da -z NL-1 -c 800G -t delite +garage layout show +garage layout apply --version 1 +``` + +Source: https://garagehq.deuxfleurs.fr/documentation/cookbook/real-world/#creating-a-cluster-layout diff --git a/docs/nixos-anywhere.md b/docs/nixos-anywhere.md new file mode 100644 index 0000000..a8f7925 --- /dev/null +++ b/docs/nixos-anywhere.md @@ -0,0 +1,13 @@ +``` +curl -L https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-kexec-installer-noninteractive-x86_64-linux.tar.gz | tar -xzf- -C /root +/root/kexec/run +``` + +``` +mkdir -p /etc/secrets/initrd +ssh-keygen -t ed25519 -f /etc/secrets/initrd/ssh_host_ed25519_key +``` + +``` +nix run github:nix-community/nixos-anywhere -- --flake .#blue-shell root@194.13.83.205 +``` diff --git a/flake.lock b/flake.lock index 43c99af..d475726 100644 --- a/flake.lock +++ b/flake.lock @@ -106,6 +106,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724349583, + "narHash": "sha256-zgB1Cfk46irIsto8666yLdKjqKdBrjR48Dd3lhQ0CnQ=", + "owner": "nix-community", + "repo": "disko", + "rev": "435737144be0259559ca3b43f7d72252b1fdcc1b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "element-stickers": { "inputs": { "maunium-stickerpicker": [ @@ -488,6 +508,7 @@ "inputs": { "agenix": "agenix", "deploy-rs": "deploy-rs", + "disko": "disko", "element-stickers": "element-stickers", "element-themes": "element-themes", "flake-parts": "flake-parts", diff --git a/flake.nix b/flake.nix index 40f049c..593b96f 100644 --- a/flake.nix +++ b/flake.nix @@ -18,6 +18,9 @@ deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.inputs.nixpkgs.follows = "nixpkgs"; + disko.url = "github:nix-community/disko"; + disko.inputs.nixpkgs.follows = "nixpkgs"; + agenix.url = "github:ryantm/agenix"; agenix.inputs.nixpkgs.follows = "nixpkgs"; agenix.inputs.darwin.follows = "nix-darwin"; @@ -99,6 +102,7 @@ treefmt nixos-generators inputs.nixpkgs-2205.legacyPackages.${system}.terraform + terraform-ls jq # For the tests puppeteer-socket pkg @@ -148,6 +152,18 @@ hostname = "tankstelle.wg.pub.solar"; sshUser = username; }; + trinkgenossin = { + hostname = "trinkgenossin.wg.pub.solar"; + sshUser = username; + }; + delite = { + hostname = "delite.wg.pub.solar"; + sshUser = username; + }; + blue-shell = { + hostname = "blue-shell.wg.pub.solar"; + sshUser = username; + }; }; }; }; diff --git a/hosts/blue-shell/configuration.nix b/hosts/blue-shell/configuration.nix new file mode 100644 index 0000000..df9424b --- /dev/null +++ b/hosts/blue-shell/configuration.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + boot.loader.grub.enable = true; + + boot.kernelParams = [ + "boot.shell_on_fail=1" + "ip=dhcp" + ]; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "24.05"; # Did you read the comment? +} diff --git a/hosts/blue-shell/default.nix b/hosts/blue-shell/default.nix new file mode 100644 index 0000000..ff8c0cc --- /dev/null +++ b/hosts/blue-shell/default.nix @@ -0,0 +1,13 @@ +{ flake, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ./configuration.nix + ./disk-config.nix + + ./networking.nix + ./wireguard.nix + #./backups.nix + ]; +} diff --git a/hosts/blue-shell/disk-config.nix b/hosts/blue-shell/disk-config.nix new file mode 100644 index 0000000..2903130 --- /dev/null +++ b/hosts/blue-shell/disk-config.nix @@ -0,0 +1,101 @@ +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vdb"; + content = { + type = "gpt"; + partitions = { + bios = { + size = "1M"; + type = "EF02"; # for grub MBR + }; + boot = { + size = "1G"; + type = "8300"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/boot"; + mountOptions = [ "defaults" ]; + }; + }; + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + extraOpenArgs = [ ]; + # if you want to use the key for interactive login be sure there is no trailing newline + # for example use `echo -n "password" > /tmp/secret.key` + passwordFile = "/tmp/luks-password"; + content = { + type = "lvm_pv"; + vg = "vg0"; + }; + }; + }; + }; + }; + }; + data = { + type = "disk"; + device = "/dev/vdc"; + content = { + type = "gpt"; + partitions = { + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptdata"; + extraOpenArgs = [ ]; + # if you want to use the key for interactive login be sure there is no trailing newline + # for example use `echo -n "password" > /tmp/secret.key` + passwordFile = "/tmp/luks-password"; + content = { + type = "filesystem"; + format = "xfs"; + mountpoint = "/var/lib/garage/data"; + mountOptions = [ "defaults" ]; + }; + }; + }; + }; + }; + }; + }; + lvm_vg = { + vg0 = { + type = "lvm_vg"; + lvs = { + root = { + size = "100G"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + mountOptions = [ "defaults" ]; + }; + }; + swap = { + size = "16G"; + content = { + type = "swap"; + }; + }; + metadata = { + size = "50G"; + content = { + type = "filesystem"; + format = "btrfs"; + mountpoint = "/var/lib/garage/meta"; + mountOptions = [ "defaults" ]; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/blue-shell/hardware-configuration.nix b/hosts/blue-shell/hardware-configuration.nix new file mode 100644 index 0000000..86e1e30 --- /dev/null +++ b/hosts/blue-shell/hardware-configuration.nix @@ -0,0 +1,27 @@ +# 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 + "/profiles/qemu-guest.nix") ]; + + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "virtio_pci" + "sr_mod" + "virtio_blk" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/blue-shell/networking.nix b/hosts/blue-shell/networking.nix new file mode 100644 index 0000000..8aea3d9 --- /dev/null +++ b/hosts/blue-shell/networking.nix @@ -0,0 +1,26 @@ +{ + config, + pkgs, + flake, + ... +}: +{ + services.garage.settings.rpc_public_addr = "[2a03:4000:43:24e::1]:3901"; + + networking.hostName = "blue-shell"; + networking.hostId = "00000005"; + + networking.useDHCP = false; + systemd.network.enable = true; + systemd.network.networks."10-wan" = { + matchConfig.Name = "ens3"; + address = [ + "194.13.83.205/22" + "2a03:4000:43:24e::1/64" + ]; + gateway = [ + "194.13.80.1" + "fe80::1" + ]; + }; +} diff --git a/hosts/blue-shell/wireguard.nix b/hosts/blue-shell/wireguard.nix new file mode 100644 index 0000000..ad37918 --- /dev/null +++ b/hosts/blue-shell/wireguard.nix @@ -0,0 +1,49 @@ +{ + config, + pkgs, + flake, + ... +}: +let + wireguardIPv4 = "10.7.6.7"; + wireguardIPv6 = "fd00:fae:fae:fae:fae:7::"; +in +{ + networking.firewall.allowedUDPPorts = [ 51820 ]; + + age.secrets.wg-private-key.file = "${flake.self}/secrets/blue-shell-wg-private-key.age"; + + networking.wireguard.interfaces = { + wg-ssh = { + listenPort = 51820; + mtu = 1300; + ips = [ + "${wireguardIPv4}/32" + "${wireguardIPv6}/96" + ]; + privateKeyFile = config.age.secrets.wg-private-key.path; + peers = flake.self.logins.admins.wireguardDevices ++ [ + { + # flora-6.pub.solar + endpoint = "80.71.153.210:51820"; + publicKey = "jtSR5G2P/nm9s8WrVc26Xc/SQLupRxyXE+5eIeqlsTU="; + allowedIPs = [ + "10.7.6.2/32" + "fd00:fae:fae:fae:fae:2::/96" + ]; + } + ]; + }; + }; + + services.openssh.listenAddresses = [ + { + addr = wireguardIPv4; + port = 22; + } + { + addr = "[${wireguardIPv6}]"; + port = 22; + } + ]; +} diff --git a/hosts/default.nix b/hosts/default.nix index c8aaf1c..56dea17 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -91,6 +91,56 @@ self.nixosModules.promtail ]; }; + + trinkgenossin = self.nixos-flake.lib.mkLinuxSystem { + imports = [ + self.inputs.agenix.nixosModules.default + self.nixosModules.home-manager + ./trinkgenossin + self.nixosModules.overlays + self.nixosModules.unlock-luks-on-boot + self.nixosModules.core + self.nixosModules.prometheus-exporters + self.nixosModules.promtail + + self.nixosModules.garage + self.nixosModules.nginx + ]; + }; + + delite = self.nixos-flake.lib.mkLinuxSystem { + imports = [ + self.inputs.agenix.nixosModules.default + self.inputs.disko.nixosModules.disko + self.nixosModules.home-manager + ./delite + self.nixosModules.overlays + self.nixosModules.unlock-luks-on-boot + self.nixosModules.core + #self.nixosModules.prometheus-exporters + #self.nixosModules.promtail + + self.nixosModules.garage + self.nixosModules.nginx + ]; + }; + + blue-shell = self.nixos-flake.lib.mkLinuxSystem { + imports = [ + self.inputs.agenix.nixosModules.default + self.inputs.disko.nixosModules.disko + self.nixosModules.home-manager + ./blue-shell + self.nixosModules.overlays + self.nixosModules.unlock-luks-on-boot + self.nixosModules.core + #self.nixosModules.prometheus-exporters + #self.nixosModules.promtail + + self.nixosModules.garage + self.nixosModules.nginx + ]; + }; }; }; } diff --git a/hosts/delite/configuration.nix b/hosts/delite/configuration.nix new file mode 100644 index 0000000..3ba7d50 --- /dev/null +++ b/hosts/delite/configuration.nix @@ -0,0 +1,33 @@ +{ + flake, + config, + pkgs, + ... +}: +{ + boot.loader.grub.enable = true; + + boot.kernelParams = [ + "boot.shell_on_fail=1" + "ip=dhcp" + ]; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "24.05"; # Did you read the comment? +} diff --git a/hosts/delite/default.nix b/hosts/delite/default.nix new file mode 100644 index 0000000..ff8c0cc --- /dev/null +++ b/hosts/delite/default.nix @@ -0,0 +1,13 @@ +{ flake, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ./configuration.nix + ./disk-config.nix + + ./networking.nix + ./wireguard.nix + #./backups.nix + ]; +} diff --git a/hosts/delite/disk-config.nix b/hosts/delite/disk-config.nix new file mode 100644 index 0000000..dea45f4 --- /dev/null +++ b/hosts/delite/disk-config.nix @@ -0,0 +1,84 @@ +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/vda"; + content = { + type = "gpt"; + partitions = { + bios = { + size = "1M"; + type = "EF02"; # for grub MBR + }; + boot = { + size = "1G"; + type = "8300"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/boot"; + mountOptions = [ "defaults" ]; + }; + }; + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + extraOpenArgs = [ ]; + # if you want to use the key for interactive login be sure there is no trailing newline + # for example use `echo -n "password" > /tmp/secret.key` + passwordFile = "/tmp/luks-password"; + content = { + type = "lvm_pv"; + vg = "vg0"; + }; + }; + }; + }; + }; + }; + }; + lvm_vg = { + vg0 = { + type = "lvm_vg"; + lvs = { + root = { + size = "40G"; + content = { + type = "filesystem"; + format = "ext4"; + mountpoint = "/"; + mountOptions = [ "defaults" ]; + }; + }; + swap = { + size = "8G"; + content = { + type = "swap"; + }; + }; + data = { + size = "800G"; + content = { + type = "filesystem"; + format = "xfs"; + mountpoint = "/var/lib/garage/data"; + mountOptions = [ "defaults" ]; + }; + }; + metadata = { + size = "50G"; + content = { + type = "filesystem"; + format = "btrfs"; + mountpoint = "/var/lib/garage/meta"; + mountOptions = [ "defaults" ]; + }; + }; + }; + }; + }; + }; +} diff --git a/hosts/delite/hardware-configuration.nix b/hosts/delite/hardware-configuration.nix new file mode 100644 index 0000000..5fff330 --- /dev/null +++ b/hosts/delite/hardware-configuration.nix @@ -0,0 +1,26 @@ +# 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 + "/profiles/qemu-guest.nix") ]; + + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "virtio_pci" + "virtio_blk" + ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/delite/networking.nix b/hosts/delite/networking.nix new file mode 100644 index 0000000..357e3b0 --- /dev/null +++ b/hosts/delite/networking.nix @@ -0,0 +1,26 @@ +{ + config, + pkgs, + flake, + ... +}: +{ + services.garage.settings.rpc_public_addr = "[2a04:52c0:124:9d8c::2]:3901"; + + networking.hostName = "delite"; + networking.hostId = "00000004"; + + networking.useDHCP = false; + systemd.network.enable = true; + systemd.network.networks."10-wan" = { + matchConfig.Name = "ens3"; + address = [ + "5.255.119.132/24" + "2a04:52c0:124:9d8c::2/48" + ]; + gateway = [ + "5.255.119.1" + "2a04:52c0:124::1" + ]; + }; +} diff --git a/hosts/delite/wireguard.nix b/hosts/delite/wireguard.nix new file mode 100644 index 0000000..17eba5a --- /dev/null +++ b/hosts/delite/wireguard.nix @@ -0,0 +1,49 @@ +{ + config, + pkgs, + flake, + ... +}: +let + wireguardIPv4 = "10.7.6.6"; + wireguardIPv6 = "fd00:fae:fae:fae:fae:6::"; +in +{ + networking.firewall.allowedUDPPorts = [ 51820 ]; + + age.secrets.wg-private-key.file = "${flake.self}/secrets/delite-wg-private-key.age"; + + networking.wireguard.interfaces = { + wg-ssh = { + listenPort = 51820; + mtu = 1300; + ips = [ + "${wireguardIPv4}/32" + "${wireguardIPv6}/96" + ]; + privateKeyFile = config.age.secrets.wg-private-key.path; + peers = flake.self.logins.admins.wireguardDevices ++ [ + { + # flora-6.pub.solar + endpoint = "80.71.153.210:51820"; + publicKey = "jtSR5G2P/nm9s8WrVc26Xc/SQLupRxyXE+5eIeqlsTU="; + allowedIPs = [ + "10.7.6.2/32" + "fd00:fae:fae:fae:fae:2::/96" + ]; + } + ]; + }; + }; + + services.openssh.listenAddresses = [ + { + addr = wireguardIPv4; + port = 22; + } + { + addr = "[${wireguardIPv6}]"; + port = 22; + } + ]; +} diff --git a/hosts/flora-6/wireguard.nix b/hosts/flora-6/wireguard.nix index 3da4e16..d825e38 100644 --- a/hosts/flora-6/wireguard.nix +++ b/hosts/flora-6/wireguard.nix @@ -47,6 +47,33 @@ "fd00:fae:fae:fae:fae:4::/96" ]; } + { + # trinkgenossin.pub.solar + endpoint = "85.215.152.22:51820"; + publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4="; + allowedIPs = [ + "10.7.6.5/32" + "fd00:fae:fae:fae:fae:5::/96" + ]; + } + { + # delite.pub.solar + endpoint = "5.255.119.132:51820"; + publicKey = "ZT2qGWgMPwHRUOZmTQHWCRX4m14YwOsiszjsA5bpc2k="; + allowedIPs = [ + "10.7.6.6/32" + "fd00:fae:fae:fae:fae:6::/96" + ]; + } + { + # blue-shell.pub.solar + endpoint = "194.13.83.205:51820"; + publicKey = "bcrIpWrKc1M+Hq4ds3aN1lTaKE26f2rvXhd+93QrzR8="; + allowedIPs = [ + "10.7.6.7/32" + "fd00:fae:fae:fae:fae:7::/96" + ]; + } ]; }; }; diff --git a/hosts/metronom/backups.nix b/hosts/metronom/backups.nix index c5bf79b..3512b7b 100644 --- a/hosts/metronom/backups.nix +++ b/hosts/metronom/backups.nix @@ -1,13 +1,29 @@ -{ flake, ... }: +{ config, flake, ... }: { - age.secrets."restic-repo-droppie" = { - file = "${flake.self}/secrets/restic-repo-droppie.age"; + age.secrets."restic-repo-storagebox-metronom" = { + file = "${flake.self}/secrets/restic-repo-storagebox-metronom.age"; mode = "400"; owner = "root"; }; - age.secrets."restic-repo-storagebox" = { - file = "${flake.self}/secrets/restic-repo-storagebox.age"; + age.secrets.restic-repo-garage-metronom = { + file = "${flake.self}/secrets/restic-repo-garage-metronom.age"; mode = "400"; owner = "root"; }; + age.secrets.restic-repo-garage-metronom-env = { + file = "${flake.self}/secrets/restic-repo-garage-metronom-env.age"; + mode = "400"; + owner = "root"; + }; + + pub-solar-os.backups.repos.storagebox = { + passwordFile = config.age.secrets."restic-repo-storagebox-metronom".path; + repository = "sftp:u377325@u377325.your-storagebox.de:/metronom-backups"; + }; + + pub-solar-os.backups.repos.garage = { + passwordFile = config.age.secrets."restic-repo-garage-metronom".path; + environmentFile = config.age.secrets."restic-repo-garage-metronom-env".path; + repository = "s3:https://buckets.pub.solar/metronom-backups"; + }; } diff --git a/hosts/metronom/configuration.nix b/hosts/metronom/configuration.nix index a43c836..7203746 100644 --- a/hosts/metronom/configuration.nix +++ b/hosts/metronom/configuration.nix @@ -23,6 +23,14 @@ pools = [ "root_pool" ]; }; + # Declarative SSH private key + age.secrets."metronom-root-ssh-key" = { + file = "${flake.self}/secrets/metronom-root-ssh-key.age"; + path = "/root/.ssh/id_ed25519"; + mode = "400"; + owner = "root"; + }; + # Declarative SSH private key #age.secrets."metronom-root-ssh-key" = { # file = "${flake.self}/secrets/metronom-root-ssh-key.age"; diff --git a/hosts/metronom/default.nix b/hosts/metronom/default.nix index a6b523c..6286208 100644 --- a/hosts/metronom/default.nix +++ b/hosts/metronom/default.nix @@ -8,6 +8,6 @@ ./networking.nix ./wireguard.nix ./email.nix - #./backups.nix + ./backups.nix ]; } diff --git a/hosts/nachtigall/backups.nix b/hosts/nachtigall/backups.nix index c5bf79b..e910d0b 100644 --- a/hosts/nachtigall/backups.nix +++ b/hosts/nachtigall/backups.nix @@ -1,13 +1,34 @@ -{ flake, ... }: +{ config, flake, ... }: { age.secrets."restic-repo-droppie" = { file = "${flake.self}/secrets/restic-repo-droppie.age"; mode = "400"; owner = "root"; }; - age.secrets."restic-repo-storagebox" = { - file = "${flake.self}/secrets/restic-repo-storagebox.age"; + age.secrets."restic-repo-storagebox-nachtigall" = { + file = "${flake.self}/secrets/restic-repo-storagebox-nachtigall.age"; mode = "400"; owner = "root"; }; + age.secrets.restic-repo-garage-nachtigall = { + file = "${flake.self}/secrets/restic-repo-garage-nachtigall.age"; + mode = "400"; + owner = "root"; + }; + age.secrets.restic-repo-garage-nachtigall-env = { + file = "${flake.self}/secrets/restic-repo-garage-nachtigall-env.age"; + mode = "400"; + owner = "root"; + }; + + pub-solar-os.backups.repos.storagebox = { + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; + repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; + }; + + pub-solar-os.backups.repos.garage = { + passwordFile = config.age.secrets."restic-repo-garage-nachtigall".path; + environmentFile = config.age.secrets."restic-repo-garage-nachtigall-env".path; + repository = "s3:https://buckets.pub.solar/nachtigall-backups"; + }; } diff --git a/hosts/nachtigall/configuration.nix b/hosts/nachtigall/configuration.nix index cdc8243..c226ed0 100644 --- a/hosts/nachtigall/configuration.nix +++ b/hosts/nachtigall/configuration.nix @@ -59,11 +59,6 @@ database-password-file = config.age.secrets.keycloak-database-password.path; }; - pub-solar-os.backups.repos.storagebox = { - passwordFile = config.age.secrets."restic-repo-storagebox".path; - repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; - }; - systemd.services.postgresql = { after = [ "var-lib-postgresql.mount" ]; requisite = [ "var-lib-postgresql.mount" ]; diff --git a/hosts/tankstelle/backups.nix b/hosts/tankstelle/backups.nix index c5bf79b..ea42f3b 100644 --- a/hosts/tankstelle/backups.nix +++ b/hosts/tankstelle/backups.nix @@ -5,8 +5,8 @@ mode = "400"; owner = "root"; }; - age.secrets."restic-repo-storagebox" = { - file = "${flake.self}/secrets/restic-repo-storagebox.age"; + age.secrets."restic-repo-storagebox-tankstelle" = { + file = "${flake.self}/secrets/restic-repo-storagebox-tankstelle.age"; mode = "400"; owner = "root"; }; diff --git a/hosts/trinkgenossin/configuration.nix b/hosts/trinkgenossin/configuration.nix new file mode 100644 index 0000000..f6cf06f --- /dev/null +++ b/hosts/trinkgenossin/configuration.nix @@ -0,0 +1,35 @@ +{ + flake, + config, + lib, + pkgs, + ... +}: +{ + boot.loader.grub.enable = true; + boot.loader.grub.devices = [ "/dev/vda" ]; + + boot.kernelParams = [ + "boot.shell_on_fail=1" + "ip=dhcp" + ]; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "24.05"; # Did you read the comment? +} diff --git a/hosts/trinkgenossin/default.nix b/hosts/trinkgenossin/default.nix new file mode 100644 index 0000000..a1699f1 --- /dev/null +++ b/hosts/trinkgenossin/default.nix @@ -0,0 +1,12 @@ +{ flake, ... }: + +{ + imports = [ + ./hardware-configuration.nix + ./configuration.nix + + ./networking.nix + ./wireguard.nix + #./backups.nix + ]; +} diff --git a/hosts/trinkgenossin/hardware-configuration.nix b/hosts/trinkgenossin/hardware-configuration.nix new file mode 100644 index 0000000..a1432c9 --- /dev/null +++ b/hosts/trinkgenossin/hardware-configuration.nix @@ -0,0 +1,54 @@ +# 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 = [ ]; + + boot.initrd.availableKernelModules = [ + "ata_piix" + "uhci_hcd" + "virtio_pci" + "sr_mod" + "virtio_blk" + ]; + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + boot.initrd.luks.devices."cryptroot" = { + device = "/dev/disk/by-uuid/52a1fd17-63d7-4d0a-b7ff-74aceaf6085a"; + }; + + fileSystems."/" = { + device = "/dev/disk/by-label/nixos"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-label/boot"; + fsType = "ext4"; + }; + + fileSystems."/var/lib/garage/data" = { + device = "/dev/disk/by-label/data"; + fsType = "xfs"; + }; + + fileSystems."/var/lib/garage/meta" = { + device = "/dev/disk/by-label/metadata"; + fsType = "btrfs"; + }; + + swapDevices = [ { device = "/dev/disk/by-label/swap"; } ]; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + virtualisation.hypervGuest.enable = true; +} diff --git a/hosts/trinkgenossin/networking.nix b/hosts/trinkgenossin/networking.nix new file mode 100644 index 0000000..aa9a378 --- /dev/null +++ b/hosts/trinkgenossin/networking.nix @@ -0,0 +1,15 @@ +{ + config, + pkgs, + flake, + ... +}: +{ + services.garage.settings.rpc_public_addr = "[2a01:239:35d:f500::1]:3901"; + + networking.hostName = "trinkgenossin"; + networking.hostId = "00000003"; + + networking.enableIPv6 = true; + networking.useDHCP = true; +} diff --git a/hosts/trinkgenossin/wireguard.nix b/hosts/trinkgenossin/wireguard.nix new file mode 100644 index 0000000..f56b6a1 --- /dev/null +++ b/hosts/trinkgenossin/wireguard.nix @@ -0,0 +1,49 @@ +{ + config, + pkgs, + flake, + ... +}: +let + wireguardIPv4 = "10.7.6.5"; + wireguardIPv6 = "fd00:fae:fae:fae:fae:5::"; +in +{ + networking.firewall.allowedUDPPorts = [ 51820 ]; + + age.secrets.wg-private-key.file = "${flake.self}/secrets/trinkgenossin-wg-private-key.age"; + + networking.wireguard.interfaces = { + wg-ssh = { + listenPort = 51820; + mtu = 1300; + ips = [ + "${wireguardIPv4}/32" + "${wireguardIPv6}/96" + ]; + privateKeyFile = config.age.secrets.wg-private-key.path; + peers = flake.self.logins.admins.wireguardDevices ++ [ + { + # flora-6.pub.solar + endpoint = "80.71.153.210:51820"; + publicKey = "jtSR5G2P/nm9s8WrVc26Xc/SQLupRxyXE+5eIeqlsTU="; + allowedIPs = [ + "10.7.6.2/32" + "fd00:fae:fae:fae:fae:2::/96" + ]; + } + ]; + }; + }; + + services.openssh.listenAddresses = [ + { + addr = wireguardIPv4; + port = 22; + } + { + addr = "[${wireguardIPv6}]"; + port = 22; + } + ]; +} diff --git a/modules/backups/default.nix b/modules/backups/default.nix index 379309a..26549ab 100644 --- a/modules/backups/default.nix +++ b/modules/backups/default.nix @@ -39,6 +39,15 @@ in example = "/etc/nixos/restic-password"; }; + environmentFile = mkOption { + type = with types; nullOr str; + default = null; + description = '' + Read repository secrets as environment variables from a file. + ''; + example = "/etc/nixos/restic-env"; + }; + repository = mkOption { type = with types; nullOr str; default = null; @@ -57,11 +66,12 @@ in remotebackup = { repository = "sftp:backup@host:/backups/home"; passwordFile = "/etc/nixos/secrets/restic-password"; + environmentFile = "/etc/nixos/secrets/restic-env"; }; }; }; - backups = mkOption { + restic = mkOption { description = '' Periodic backups to create with Restic. ''; @@ -174,7 +184,7 @@ in runCheck = mkOption { type = types.bool; - default = (builtins.length config.pub-solar-os.backups.backups.${name}.checkOpts > 0); + default = (builtins.length config.pub-solar-os.backups.restic.${name}.checkOpts > 0); defaultText = literalExpression ''builtins.length config.services.backups.${name}.checkOpts > 0''; description = "Whether to run the `check` command with the provided `checkOpts` options."; example = true; @@ -256,19 +266,25 @@ in services.restic.backups = let repos = config.pub-solar-os.backups.repos; - backups = config.pub-solar-os.backups.backups; + restic = config.pub-solar-os.backups.restic; - storeNames = builtins.attrNames repos; - backupNames = builtins.attrNames backups; + repoNames = builtins.attrNames repos; + backupNames = builtins.attrNames restic; createBackups = backupName: - map (storeName: { - name = "${backupName}-${storeName}"; - value = repos."${storeName}" // backups."${backupName}"; - }) storeNames; + map (repoName: { + name = "${backupName}-${repoName}"; + value = repos."${repoName}" // restic."${backupName}"; + }) repoNames; in builtins.listToAttrs (lib.lists.flatten (map createBackups backupNames)); + + # Used for pub-solar-os.backups.repos.storagebox + programs.ssh.knownHosts = { + "u377325.your-storagebox.de".publicKey = "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5EB5p/5Hp3hGW1oHok+PIOH9Pbn7cnUiGmUEBrCVjnAw+HrKyN8bYVV0dIGllswYXwkG/+bgiBlE6IVIBAq+JwVWu1Sss3KarHY3OvFJUXZoZyRRg/Gc/+LRCE7lyKpwWQ70dbelGRyyJFH36eNv6ySXoUYtGkwlU5IVaHPApOxe4LHPZa/qhSRbPo2hwoh0orCtgejRebNtW5nlx00DNFgsvn8Svz2cIYLxsPVzKgUxs8Zxsxgn+Q/UvR7uq4AbAhyBMLxv7DjJ1pc7PJocuTno2Rw9uMZi1gkjbnmiOh6TTXIEWbnroyIhwc8555uto9melEUmWNQ+C+PwAK+MPw=="; + "[u377325.your-storagebox.de]:23".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIICf9svRenC/PLKIL9nk6K/pxQgoiFC41wTNvoIncOxs"; + }; }; } diff --git a/modules/forgejo/default.nix b/modules/forgejo/default.nix index dee6d12..d99abdd 100644 --- a/modules/forgejo/default.nix +++ b/modules/forgejo/default.nix @@ -182,7 +182,7 @@ OnCalendar = "*-*-* 00:00:00 Etc/UTC"; }; initialize = true; - passwordFile = config.age.secrets."restic-repo-storagebox".path; + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; backupPrepareCommand = '' ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d gitea > /tmp/forgejo-backup.sql diff --git a/modules/garage/default.nix b/modules/garage/default.nix new file mode 100644 index 0000000..f50d687 --- /dev/null +++ b/modules/garage/default.nix @@ -0,0 +1,142 @@ +{ + config, + lib, + pkgs, + flake, + ... +}: +{ + age.secrets."garage-rpc-secret" = { + file = "${flake.self}/secrets/garage-rpc-secret.age"; + mode = "400"; + }; + + age.secrets."garage-admin-token" = { + file = "${flake.self}/secrets/garage-admin-token.age"; + mode = "400"; + }; + + age.secrets."acme-namecheap-env" = { + file = "${flake.self}/secrets/acme-namecheap-env.age"; + mode = "400"; + }; + + networking.firewall.allowedTCPPorts = [ + 3900 + 3901 + 3902 + ]; + + networking.firewall.interfaces.wg-ssh.allowedTCPPorts = [ 3903 ]; + + security.acme = { + defaults = { + environmentFile = config.age.secrets.acme-namecheap-env.path; + }; + certs = { + # Wildcard certificate gets created automatically + "buckets.${config.pub-solar-os.networking.domain}" = { + # disable http challenge + webroot = null; + # enable dns challenge + dnsProvider = "namecheap"; + dnsPropagationCheck = false; + }; + # Wildcard certificate gets created automatically + "web.${config.pub-solar-os.networking.domain}" = { + # disable http challenge + webroot = null; + # enable dns challenge + dnsProvider = "namecheap"; + dnsPropagationCheck = false; + }; + }; + }; + + services.nginx = { + upstreams.s3_backend.servers = { + "[::1]:3900" = { }; + }; + upstreams.web_backend.servers = { + "[::1]:3902" = { }; + }; + virtualHosts."buckets.${config.pub-solar-os.networking.domain}" = { + serverAliases = [ "*.buckets.${config.pub-solar-os.networking.domain}" ]; + + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyPass = "http://s3_backend"; + extraConfig = '' + client_max_body_size 64m; + proxy_max_temp_file_size 0; + ''; + }; + }; + virtualHosts."web.${config.pub-solar-os.networking.domain}" = { + serverAliases = [ "*.web.${config.pub-solar-os.networking.domain}" ]; + + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyPass = "http://web_backend"; + }; + }; + }; + + services.garage = { + enable = true; + package = pkgs.garage_1_0_0; + settings = { + data_dir = "/var/lib/garage/data"; + metadata_dir = "/var/lib/garage/meta"; + db_engine = "lmdb"; + replication_factor = 3; + compression_level = 2; + rpc_bind_addr = "[::]:3901"; + s3_api = { + s3_region = "eu-central"; + api_bind_addr = "[::]:3900"; + root_domain = ".s3.${config.pub-solar-os.networking.domain}"; + }; + s3_web = { + bind_addr = "[::]:3902"; + root_domain = ".web.${config.pub-solar-os.networking.domain}"; + index = "index.html"; + }; + admin = { + api_bind_addr = "[::]:3903"; + }; + }; + }; + + users.users.garage = { + isSystemUser = true; + home = "/var/lib/garage"; + group = "garage"; + }; + + users.groups.garage = { }; + + # Adapted from https://git.clan.lol/clan/clan-core/src/commit/23a9e35c665ff531fe1193dcc47056432fbbeacf/clanModules/garage/default.nix + # Disabled DynamicUser https://github.com/NixOS/nixpkgs/blob/nixos-24.05/nixos/modules/services/web-servers/garage.nix + # for mounts + permissions to work + systemd.services.garage = { + serviceConfig = { + user = "garage"; + group = "garage"; + DynamicUser = false; + LoadCredential = [ + "rpc_secret_path:${config.age.secrets.garage-rpc-secret.path}" + "admin_token_path:${config.age.secrets.garage-admin-token.path}" + ]; + Environment = [ + "GARAGE_ALLOW_WORLD_READABLE_SECRETS=true" + "GARAGE_RPC_SECRET_FILE=%d/rpc_secret_path" + "GARAGE_ADMIN_TOKEN_FILE=%d/admin_token_path" + ]; + }; + }; +} diff --git a/modules/grafana/default.nix b/modules/grafana/default.nix index b62789e..952661b 100644 --- a/modules/grafana/default.nix +++ b/modules/grafana/default.nix @@ -33,6 +33,11 @@ group = "grafana"; user = "grafana"; }; + "grafana-dashboards/grafana-garage-dashboard-prometheus.json" = { + source = ./grafana-dashboards/grafana-garage-dashboard-prometheus.json; + group = "grafana"; + user = "grafana"; + }; }; services.caddy.virtualHosts."grafana.${config.pub-solar-os.networking.domain}" = { diff --git a/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json b/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json new file mode 100644 index 0000000..33ee163 --- /dev/null +++ b/modules/grafana/grafana-dashboards/grafana-garage-dashboard-prometheus.json @@ -0,0 +1,1048 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "DS_PROMETHEUS", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "9.2.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 24, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "Bps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum(rate(block_bytes_read{job=\"garage\"}[$__rate_interval]) )", + "hide": false, + "interval": "", + "legendFormat": "Disk bytes read", + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "-sum(rate(block_bytes_written{job=\"garage\"}[$__rate_interval]) )", + "hide": false, + "interval": "", + "legendFormat": "Disk bytes written", + "refId": "B" + } + ], + "title": "Disk I/O", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 8, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (api_endpoint) (rate(api_s3_request_counter {job=\"garage\"}[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "{{api_endpoint}}", + "range": true, + "refId": "A" + } + ], + "title": "API requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 16, + "y": 0 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum(rate(web_request_counter {job=\"garage\"}[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "Web request rate", + "refId": "A" + } + ], + "title": "Web requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 9 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum by (rpc_endpoint) (rate(rpc_request_counter {job=\"garage\"}[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "{{rpc_endpoint}}", + "refId": "A" + } + ], + "title": "RPC requests", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 9 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (api_endpoint, status_code) (rate(api_s3_error_counter {job=\"garage\"}[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "{{api_endpoint}} {{status_code}}", + "range": true, + "refId": "A" + } + ], + "title": "API errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 9 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum by(status_code) (rate(web_error_counter {job=\"garage\"}[$__rate_interval]))", + "hide": false, + "interval": "", + "legendFormat": "{{status_code}}", + "refId": "A" + } + ], + "title": "Web errors", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 17 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "block_resync_queue_length{job=\"garage\"}", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "title": "Resync queue length", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 8, + "y": 17 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum by(table_name) (table_gc_todo_queue_length{job=\"garage\"})", + "interval": "", + "legendFormat": "{{ table_name}}", + "refId": "A" + } + ], + "title": "Table GC queue length", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 16, + "y": 17 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "sum by(table_name) (table_merkle_updater_todo_queue_length{job=\"garage\"})", + "interval": "", + "legendFormat": "{{ table_name}}", + "refId": "A" + } + ], + "title": "Table Merkle updater queue length", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 0, + "y": 25 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "exemplar": true, + "expr": "block_resync_errored_blocks{job=\"garage\"}", + "interval": "", + "legendFormat": "{{instance}}", + "refId": "A" + } + ], + "title": "Resync errored blocks", + "type": "timeseries" + } + ], + "refresh": "30s", + "schemaVersion": 37, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "default", + "value": "default" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "DS_PROMETHEUS", + "label": "Datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Garage", + "uid": "ys3pnpZ4k", + "version": 26, + "weekStart": "" +} diff --git a/modules/keycloak/default.nix b/modules/keycloak/default.nix index b40234a..659c194 100644 --- a/modules/keycloak/default.nix +++ b/modules/keycloak/default.nix @@ -59,7 +59,7 @@ plugins = [ flake.inputs.keycloak-event-listener.packages.${pkgs.system}.keycloak-event-listener ]; }; - pub-solar-os.backups.backups.keycloak = { + pub-solar-os.backups.restic.keycloak = { paths = [ "/tmp/keycloak-backup.sql" ]; timerConfig = { OnCalendar = "*-*-* 03:00:00 Etc/UTC"; diff --git a/modules/mail/default.nix b/modules/mail/default.nix index cfbfe87..908a501 100644 --- a/modules/mail/default.nix +++ b/modules/mail/default.nix @@ -33,4 +33,20 @@ }; security.acme.acceptTerms = true; security.acme.defaults.email = "security@${config.pub-solar-os.networking.domain}"; + + pub-solar-os.backups.restic.mail = { + paths = [ + "/var/vmail" + "/var/dkim" + ]; + timerConfig = { + OnCalendar = "*-*-* 02:00:00 Etc/UTC"; + }; + initialize = true; + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 4" + "--keep-monthly 3" + ]; + }; } diff --git a/modules/mailman/default.nix b/modules/mailman/default.nix index 3db13b6..e5e2903 100644 --- a/modules/mailman/default.nix +++ b/modules/mailman/default.nix @@ -91,7 +91,7 @@ OnCalendar = "*-*-* 02:00:00 Etc/UTC"; }; initialize = true; - passwordFile = config.age.secrets."restic-repo-storagebox".path; + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; pruneOpts = [ "--keep-daily 7" diff --git a/modules/mastodon/default.nix b/modules/mastodon/default.nix index 85210e0..a26d7dd 100644 --- a/modules/mastodon/default.nix +++ b/modules/mastodon/default.nix @@ -106,7 +106,7 @@ OnCalendar = "*-*-* 04:00:00 Etc/UTC"; }; initialize = true; - passwordFile = config.age.secrets."restic-repo-storagebox".path; + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; backupPrepareCommand = '' ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mastodon > /tmp/mastodon-backup.sql diff --git a/modules/matrix/default.nix b/modules/matrix/default.nix index 66b071f..3165911 100644 --- a/modules/matrix/default.nix +++ b/modules/matrix/default.nix @@ -295,7 +295,7 @@ in OnCalendar = "*-*-* 05:00:00 Etc/UTC"; }; initialize = true; - passwordFile = config.age.secrets."restic-repo-storagebox".path; + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; backupPrepareCommand = '' ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d matrix > /tmp/matrix-synapse-backup.sql diff --git a/modules/mediawiki/default.nix b/modules/mediawiki/default.nix index 4512b55..63367ab 100644 --- a/modules/mediawiki/default.nix +++ b/modules/mediawiki/default.nix @@ -232,4 +232,27 @@ in }; }; }; + + pub-solar-os.backups.restic.mediawiki = { + paths = [ + "/var/lib/mediawiki/images" + "/var/lib/mediawiki/uploads" + "/tmp/mediawiki-backup.sql" + ]; + timerConfig = { + OnCalendar = "*-*-* 00:30:00 Etc/UTC"; + }; + initialize = true; + backupPrepareCommand = '' + ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d mediawiki > /tmp/mediawiki-backup.sql + ''; + backupCleanupCommand = '' + rm /tmp/mediawiki-backup.sql + ''; + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 4" + "--keep-monthly 3" + ]; + }; } diff --git a/modules/nextcloud/default.nix b/modules/nextcloud/default.nix index 0f81781..662d1ce 100644 --- a/modules/nextcloud/default.nix +++ b/modules/nextcloud/default.nix @@ -145,7 +145,7 @@ OnCalendar = "*-*-* 01:00:00 Etc/UTC"; }; initialize = true; - passwordFile = config.age.secrets."restic-repo-storagebox".path; + passwordFile = config.age.secrets."restic-repo-storagebox-nachtigall".path; repository = "sftp:u377325@u377325.your-storagebox.de:/backups"; backupPrepareCommand = '' ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump -d nextcloud > /tmp/nextcloud-backup.sql diff --git a/modules/obs-portal/default.nix b/modules/obs-portal/default.nix index e2733bf..dfd5793 100644 --- a/modules/obs-portal/default.nix +++ b/modules/obs-portal/default.nix @@ -147,4 +147,26 @@ in }; }; }; + + pub-solar-os.backups.restic.obs-portal = { + paths = [ + "/var/lib/obs-portal/data" + "/tmp/obs-portal-backup.sql" + ]; + timerConfig = { + OnCalendar = "*-*-* 00:30:00 Etc/UTC"; + }; + initialize = true; + backupPrepareCommand = '' + ${pkgs.docker}/bin/docker exec -ti --user postgres obs-portal-db pg_dump obs > /tmp/obs-portal-backup.sql + ''; + backupCleanupCommand = '' + rm /tmp/obs-portal-backup.sql + ''; + pruneOpts = [ + "--keep-daily 7" + "--keep-weekly 4" + "--keep-monthly 3" + ]; + }; } diff --git a/modules/prometheus/default.nix b/modules/prometheus/default.nix index 709f6a2..5834ee2 100644 --- a/modules/prometheus/default.nix +++ b/modules/prometheus/default.nix @@ -69,6 +69,14 @@ instance = "tankstelle"; }; } + { + targets = [ + "trinkgenossin.wg.${config.pub-solar-os.networking.domain}:${toString config.services.prometheus.exporters.node.port}" + ]; + labels = { + instance = "trinkgenossin"; + }; + } ]; } { @@ -83,6 +91,18 @@ } ]; } + { + job_name = "garage"; + static_configs = [ + { + targets = [ + "trinkgenossin.wg.${config.pub-solar-os.networking.domain}:3903" + "delite.wg.${config.pub-solar-os.networking.domain}:3903" + "blue-shell.wg.${config.pub-solar-os.networking.domain}:3903" + ]; + } + ]; + } ]; ruleFiles = [ diff --git a/modules/unlock-luks-on-boot/default.nix b/modules/unlock-luks-on-boot/default.nix new file mode 100644 index 0000000..0952188 --- /dev/null +++ b/modules/unlock-luks-on-boot/default.nix @@ -0,0 +1,20 @@ +{ flake, config, ... }: +{ + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + # To prevent ssh clients from freaking out because a different host key is used, + # a different port for ssh is useful (assuming the same host has also a regular sshd running) + port = 2222; + + # Please create this manually the first time. + hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ]; + authorizedKeys = config.pub-solar-os.authentication.sshPubKeys; + }; + postCommands = '' + # Automatically ask for the password on SSH login + echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile + ''; + }; +} diff --git a/secrets/acme-namecheap-env.age b/secrets/acme-namecheap-env.age new file mode 100644 index 0000000..a09e587 Binary files /dev/null and b/secrets/acme-namecheap-env.age differ diff --git a/secrets/blue-shell-wg-private-key.age b/secrets/blue-shell-wg-private-key.age new file mode 100644 index 0000000..3e1c3cf --- /dev/null +++ b/secrets/blue-shell-wg-private-key.age @@ -0,0 +1,43 @@ +age-encryption.org/v1 +-> ssh-ed25519 eP5MMw xAObv9OBtCMHWnbnO9b9w5fiG3tkJJTvjFNWmYmGfhQ +sXmgq1drzY3rap8aD8/iMbMgjGkajfENkBQDdK/2TKQ +-> ssh-ed25519 uYcDNw sxw3K1xYG+OZQy+4U2UfX//ZElPaCieANzFHanJxfxw +VyhqjYppfHVb2jTceXLL/yYwEJE2uD9TY4PliHu7c0E +-> ssh-rsa f5THog +hRIMIg4P7SOOS3IGr2vF/TAdvgAXjJ8CbjKQt+Bd8MUjxf769rD3bln3lF3DlfIU +RMkicdnwRdWTnqp+HyV0/UsD4ZzVb0YY+ntK6wujqgEwhpef9NOE2Hsiyvv228l5 +pu6eUTrosmb0ysnw8zRmr4RYdv1+MsD9gbnLOnnuHkA+i28jAE6o4gXIdnKfDcIk +ptJISTFwyzz+q8UvdfO4YGRBL4zSoWM5VEQS0IPjrt4+qBlOyC2IlXz1/aaGZk41 +ODgPUO68USpzFsLqsmRJJQOMxxkdnYWy4DoeHKUyZI4YO0t94zVEHIS3x6w2l+/Q +9r7TdKXxniLFYW9t5+28ez5XfLruapXroA8kp2hy3S7ybuOyB2MIfCXVvK0kiOfw +2kZnv7LvL4BLUMtgPKoAxj8Pzpi8HzFGxQudqNwSkjb4bvFg8eej0oP/WhvFalsY +MGSdlFJkKKeLWh8MzmD2WXHJ5yVcRFHydyWGMHlZJ4soi0I3gTSQaNSPUxWtFSd3 +Trk3Jz4Qrd7EA6y6wn2Jc4xCX+cWb8Q3nrXVZJL/FSxss+zstQit5O3BwWupJQLt +ubyqLxQI/PKP/gIU8sGhwKDWGjZUlwvjPBG+EdWJAxoI7S7+4UxkGgsNvx67VKgi +xxz3ANlHPbGLgAZTtEk5AqHWLWE6ZRn/7i3Qv1HWZJ4 +-> ssh-rsa kFDS0A +OqNv7KThlRd0aD1gixsI2LVb+Zj2r7OVm4lUD/UJ0WVe/ihlcBAeEj8noqNA3zgH +djO53WpAkGrbt8CejuQcPYLyw8Bdk++cBu9Po+X0dAp2cCPqakgIpEI6qG1uiEty +LOOF13TivCB802UrJmX/8HLDV3yv7IWIr2XV0V8s5UvasYlgCt1eg4suhXIngnJG +wd7WFnXwtNtR/UcnWtpE8c6p5kaAn4wSAtx6hFqnkN5ANjKXHy29NkFR1Lgu55OU +qoJPpcZpvEESYMQfPvfuCUSZgcSvJE8B1MJZzxdKBHFiaWa7BkkWOL2KNIARFji5 +nBrGzGLV9IaHWsS0UfIWixvM3OPl4wgwpdLtVJsnLX/ggFZrZmj+iR5DdqurfW7E +0a8Ie1NKK7FU+HnzEk6+8aiDb0QozEhrmaE5olc8dBOKK13e1idDTCsquaQcSOEh +DBP8r0LhqU7YwnNF6UpQiYs3Zs2HyPegfz2GwB3yeaHqc7+MnXm/j4B5qUcX5naz +llQoNfddAtoXGeK3G0yjugkSluValw6o2hQ+4iRx4n1f3dVcurXkBr9fjCKMmjC4 +qbOHhsBU4dHCvFIOXY27Xvq5qZ4/ceNb6fq/NXvkD87eePMLg9R9hmtTaCDlEN2d +a350/FxlWOZXEox+mRZhE+mE5qSIg+LbnFZ+zjWq+yc +-> piv-p256 vRzPNw AzwIBCtS5Tx/zuFHRYsYSOffxAE79O5foV+ndpw0hR1t +HDmWtvUS9wSnlNjbkD0Rc0jQ4tNhqpcqpeztW1GXC3g +-> piv-p256 zqq/iw Av5ZYxbCJrjUImhX7hoO8nxtWEtd7mPWhofwCxtW5GNI +tB/mFmw4U2NbeDKdasi/Z99VggQYhnv6+n9+VJekq/k +-> ssh-ed25519 YFSOsg nl0SHBFBylYgoy4qrZ851AQ6NLuDpXtIQ5WffqQPckU +/yk/gT3enujLcjHkYuE0XGUDrYUEEzvyPvIlKhHtf5c +-> ssh-ed25519 iHV63A 2Gq6dIvLDJQmwgQwxhqrPpubkToiseczLkobeCZiOSA +IXddfsh84BrA0v6X/SjqoFbUfJfw3v+zD3Dk5RdsfAE +-> ssh-ed25519 BVsyTA 9oRVFqCqPoQ35/u+Cg4dPkG4eXw7vSRaPwhel430TGE +C54Ofc94lPFMGLljqY4Ag0AhM/MHWeZjZ6x1fmyMmqI +-> ssh-ed25519 +3V2lQ 2g1xRrQZy30nCaDq6RtfXQfUchtD8oOnmGYX+A2venQ +oop5rNpGKvTUOLGN2HGc7B63H/8XYrhO+XsCjsKfPgA +--- cMgwwO4kfMX17njkjYczc4R6FVRwC+cpK37g2cFAapc + `сXӓ;RV]tbM"N4a/IpB7QeM npʱ2}z-R4E(N \ No newline at end of file diff --git a/secrets/delite-wg-private-key.age b/secrets/delite-wg-private-key.age new file mode 100644 index 0000000..48d0fe1 Binary files /dev/null and b/secrets/delite-wg-private-key.age differ diff --git a/secrets/garage-admin-token.age b/secrets/garage-admin-token.age new file mode 100644 index 0000000..a8ed9e9 --- /dev/null +++ b/secrets/garage-admin-token.age @@ -0,0 +1,47 @@ +age-encryption.org/v1 +-> ssh-ed25519 NID4eA MqbdKdPSNLU32j+ZFTT1bmSFk4ZQowSuYcuP/FRtKgs +m0UaJclORGOrQDLIvdIv4Aq4U3XNOet9CzU8pX/pGsI +-> ssh-ed25519 9RQHxg WyTt2Lqd2mRtwsx2PLajmk68IB1yP0DkgXR/xfIMERM +4JaJ+DB97XxOuI2G/qnk+NX8Xv1ruY28NPRl7aUPWEc +-> ssh-ed25519 eP5MMw HUf/aXRbaIEjQFdWpo8vWtNSqzYcQKaNKJ7y+ewMVz0 +6IcRiPufkMLjOV5mSaOBclPmFDVKII/8mqGN7jmfkYk +-> ssh-ed25519 uYcDNw gHg0z1q+4AGZtuMzbV1dZjWojmYNE0JO1ZhMnGqAbR0 +sFE6mIV3ZgRMlsuHFltkC4M+aAhEDzVQQ3rkgiR5GSY +-> ssh-rsa f5THog +BFJZWIMurARpA6XJMlxnDYFUTGCX5gEb6IycqUQbIdu9+91mpDR3WxlJYLLZC3vD +j7e5xFvr4bOXQg56N59k4AD5CnC7CoZld/PqGtP5JqUcoXPFHgq95GzfiuTLedkZ +esPsPvXfdeyqfzcdMhxTz8pO0RRPUk9Xc2wnvHrDyeNO0vS5N+bMsNMvFfRaMZTi +xV2Xl98VFl90+gzuPACN0zpfoEqajcJhPtMqoaOjOzD7sGaAz5UYLAIyOHdh3t9w +DwVorUheXKLqq1kxZRZ5QCC7N+TCbi7x6B5xCezz9hF2vXkzunDh/d7maQG34AXJ +x1sQ4R9dXn778j14RqBBNbsFPDg8WIS4Zs+ypdqev8w+aOhZkcDf5unKQJLdeu3N +W+IUJTN5zFObMX0TXtj0yI7xUSkZKSLuZs43MhdVkNo1YewHalMpKetctnw2Lz+z +ZcDCRLmD91U5BL7xp9KYQQ9EBjEn8dyw9hn8RmCaRKsvi71cIStv4OtuGxzIvTOJ +phqDJdjz53E6L/0NDmhgN7bxolYZJsPC2o/ca0lG1rx3SZdfI18WaTsQrOO2NaeZ +i4u9vkw/k7xT65mPxPsN7s67niE6lVGyTOLMwjvfO1sAHABbtto2GL0zRc454b9v +gObMCi/ZbOUo6wndMMPnrQh9SsSGKB6EIOEzmg+8M+Y +-> ssh-rsa kFDS0A +h9TH7j+1hquLDwCIRDvQiN7UJaO6rJ/NtWdeWTuqTqTGSS+aVvm9gDZBZiLzWyqb +GLd2guhepOCuSQkxocD7KAz1hp5pqf++XI8/yqepnHuU+CmInsOBmSZsG8QGktbk +wjY3ZqZdcfCorgAxjIaw4aNW3zeoq7ATC3rC3aDeOsZC6jImdgEeCvd8BczWSqOa +9acfRqd+QNDjqq3MIGIepVBlQ0nNniRtQoh4XtUey8jVb6kjow4TqBo9V33UhO7x +r3WMgk5q1onECAhaAlYFxQ3DzLjUxAVdulnkIoSBqdE1b6Njyc70CI9oYwZcGmbD +gC3qdQWmcoeOQ95YkdJAxaFIl3VNOTyn9rSXtn3a1PsVygaT+98qd1zwGPY+3ZDk +B1chqWp3IJ4y2oPqt1mO4j0am2NAChpcWlEhgeldD0HoUixoXvp2Gu0igD5ENfyH +BopesdhSoIxw8PbjKvnuwPFNSa9ysS6mpdmChTdBGpOCSpwMEcEE/m3pLo4FkzJf +nhQaxav7VmvZ2jxnmEgP/NUgxmZPHKOzlI3vqWfTsIwz/chHDwekhb6dB0O5nrjO +LzmKVrkVH0EEa3R1/BIfF674RSPXOmW89NNU7tCax3IOuPWC0QYv+2r/zjmAEq+Q +LJMPf1fUjLlsCmkOlxDYK4E/EyiG5dcjxdyXk8J+l6s +-> piv-p256 vRzPNw AzRQKtxg/bXdDoLXM4IBQaPXZ7Tg/6GSg0LeQQ3GNUnw +xf8jnJPg8nqUt26lvtemwdvV8h0nT8k/H4iGO8fBa1k +-> piv-p256 zqq/iw AtpFzxs9a5N87BOsagEIMnJFxyBv8PZwsF4orrWS7dlP +8w3nDD2dIXKRKtnz/xnFW3it99ZmfY9X4ZiQhjXnaPM +-> ssh-ed25519 YFSOsg E3q3wZk2o3+Gmv0xMuokFWqhckCEZxVomrj61M2U21w +CUlB8ynJwO5JmHND3+x/NN/PyV0HJXfoxI3TgPjOD/4 +-> ssh-ed25519 iHV63A 4tjRDQ0kSZZYda0V3pEs6teT7n8r0WFQ1iHj90XIP1c +OMGjdTkZo8LOojtNDhIw5OXaWpC21f8hIOcnv1suLA4 +-> ssh-ed25519 BVsyTA 5BzUJ7kmv/3ZwxRGOq6QNohlWn5nuHgCBTjbcGtA1jU +vaN4i/JBvrDtdb9IX+F4uLG8v6wiaF0zjTyBXJ7B0Ts +-> ssh-ed25519 +3V2lQ eS/DpYwsqIkwm1JENRu1kIHqe+qAcMssglt/DHIAuBk +JYdv3kTgpF+3b4a9eycCzl3FWyLSkunas4IYqfw9z48 +--- iffZKXnN9jbIrfnm0NrUmqfNhsBtd0FCBEc9Zp0YSj8 +[4aϓ ܥG( \)YQ '~@LKTw;j~,*q?o}' ? ׿ diff --git a/secrets/garage-rpc-secret.age b/secrets/garage-rpc-secret.age new file mode 100644 index 0000000..e8ad987 Binary files /dev/null and b/secrets/garage-rpc-secret.age differ diff --git a/secrets/metronom-root-ssh-key.age b/secrets/metronom-root-ssh-key.age new file mode 100644 index 0000000..c07ac8d Binary files /dev/null and b/secrets/metronom-root-ssh-key.age differ diff --git a/secrets/restic-repo-garage-metronom-env.age b/secrets/restic-repo-garage-metronom-env.age new file mode 100644 index 0000000..432b93a --- /dev/null +++ b/secrets/restic-repo-garage-metronom-env.age @@ -0,0 +1,44 @@ +age-encryption.org/v1 +-> ssh-ed25519 UE5Ceg rpN1FsYIOjsiqPAt3iwd6l3ZEDYNomnzcvgowqS1CAI +A5+KU6SOzcZzTQPkEPp1wN6bq9junwauKDPhM1eKi+8 +-> ssh-ed25519 uYcDNw V/zOsw5KmaQUm1YsnJExXJThypfsxOu/CS+EQ2np7RQ +vMGUU/OPOoWiyR70xsXarqWN/AgegeKgTz5lOPa04CI +-> ssh-rsa f5THog +Z3tZv8bK67z15PAp4RgMEi1Ph4y5IFBIVNHdhENVTt2zS2TnzTBoUSypjaioRlGj +YKYuUl7+sFys6QRHOWTrUM6CFF6KQo/hYR5bsFG01xE9xoG7e4V5x0ts6sFp0Xme +0nl8NBfjbORhKYyCEye6p/9EvPwJ7qpRrQt6TUpnShv9BLrZZpEyw9sy7dXS3Sjp +btXgkOiRmIJqkYLyZ3fZF2uDlOiCVVQn/m0Bii+t0vsp4ZoyvMyc/ho3pN8i2GUV +QvUPAWzps4LTIKUf/0IYpHV4adyEfXD09/L/ShPxXJjLrYpT+4JjJqzIg5Gutbyk +QRBP52GFqyt3V6M2yM9THvdk88hhczsIH37VGLmdPH+vHDG1LIabgf9rJk14+FmM +h7/TE7M4EG9YHG//zLVI4WaVf64G9Oxet4y80BhCF4kpILWRm108mpwwzPL48tR3 +VMkiX0NpP0iOe22vV6u5zzugHQYqMvR6dPtrc4yBNUPgHhOLf6GWDhX12y478o91 +ILUM08J0R0PCJhH+8LARfc7wx1fjoxeJq468sw6znHqcqbIh7WPxarKaiTbTA5bj +06oA4YHzFbV53AbiWNHcrKCNvLaGWOw+2vtXRg8UMmbbGr8icqbLMYl7qY9kS7he +wINMQgMKD79Q+V3AweMqLuIn1AyLpqwVmh9Qon3Wzdk +-> ssh-rsa kFDS0A +ZpHhJzIt2oAC5Z/xJabaunnhXCE5Ijx+Uq/s07uow2tpautkMhmP6SbdgR6zGLFV +QJMgHmDgOqybYLhaP6t8KCygmeT9DjOB47H7mmZ8yvWAitPXTpbJzlFUls6YH3Ei +C4lxsEoCjbH+znVTKFd4220Cb4GGvnMS7tXuAnQ9GFMAn/90LFBzYjbqSvkDyv/n +9Ej1Nya5r0RQg/BcTKvppr0sfdk1wCEE5jDrHAR4zMmofFxuFi7V85IcRdsrU8ij +JawhvCYGfDM6G1Yh6j8V4oaqo3gAqki0CYF5gXED42sfPrxXLV2qtYMRJSua9z0i +Zo3SgDa9WVQslqL0VZoDXn/KyDqUYWYsfsVY0kXrMezlN9+Jm77MFVWMdXNI31eG +EIAWMr0f6nsTuXV58lwXoijSLy9Ap45TPjbVbp7+1JkD2X543DuJD3ONiNq01gey +a7aGLS492IByZx0mw6sb9xpTt8jP6enH+ltqcE6gMsEcxwXfmagVKTxtNrK0izWm +g2GdcpGnVqioj42lchUJzNt/PtPqutaraEvo2oq2cw1zxCjY4zxdyNO1RdaFV71b +fFj2JJCm67GFHWdlqbAePTx2SvUoFt3a3N8DMNFKThGQN/1LwOaKEd25ZSTNEuwO +1exQgJfC2kxrfypEmQP/whSrk2kR13NW40bBHvrZgjo +-> piv-p256 vRzPNw Awtb8p5KgsKIBUumqHnVMgux3dRS478DdNpCENgG3frB +wcIPacn7KP7gl0Z5SvtoYK0pnIjWLwUB2UvVQdWJfso +-> piv-p256 zqq/iw AgAk66eJ/xs+PqwTBzazW4HfK8dawj/3jx5opFOaGLSj +xThgJOorp+YXS8DvaULIoszFubEfACcKSy+vwf9KMSA +-> ssh-ed25519 YFSOsg p+/PUojxwOxpfBfaDOfEHMOGS1oVCrl9dskXgo+gOGI +PPYr0WVPDwRiFGo14Mx+Wv+gkZ91S7CKyYslGjCI/lQ +-> ssh-ed25519 iHV63A iXr8vgW9lHnX+rX/E9/NrKNbF+LyRpe0M44P0IxaBHo +/odvSKNzyS8ondJ0Tcuiry09NM4ozFn2qeVMqRgR17w +-> ssh-ed25519 BVsyTA CgGBOj8nDcfP7GBIMnFV89WF1CAoiOFbA/dUOWggmVE +V4CUV5WZbVTPm3AnoW6WfIqIdcMW/Sm/FTljx1awdeo +-> ssh-ed25519 +3V2lQ Jg+gASEMV3bi9eEB86rFfguh6Be/yOO2szI19Mk2BlY +q7vBOf0CFOUfxbpvwD8rpJH3asQqqNqWBJSzwYTBErs +--- KSBDnbS1GMq4I8FXEljleKo/pKvauq9T8vomtInIEOQ +~p +ўhAV>m< 1|Ly ssh-ed25519 UE5Ceg ys38fGOhLJNLg9zx9T3v2VgF2IbOr/Y/rj2+dWkcAlU +QwkMX8WKgcJeGUomDSLjijen2K5UcRnYYwtebrITDqU +-> ssh-ed25519 uYcDNw wF0oWExIUjlP32CQzOvp6MyEvFw33Sm8pHhYn3Sb0zE +RHslJJumyXoCLHLw4sGlSLK++UHmgq97KPkqCu77G3o +-> ssh-rsa f5THog +pFSH+qCW+oM9zn2j+830+bja2rTXFuzATqfMNAq3o38ssW8Nl7+0FpkdMam4iYXu +sw4Pcaj1QPTO8PbhkEvjoOU4f0bUsVuJSIvcour4k8SUOBgEMiW/98AVSTIk6KBX +PvA+4uZn2Is+bB2m9EGCguwLJ9zzzfbur+USMQvwkQexg0YRpSfhJsRbCplLXhE+ +ZU6ut4HjCP0XWwvxgFzKc6sY4X+/PeWFJOd+WkWy5lL6gcMqUz5DXoi1CeG11AR4 +/hQ5KSJBpVsxw/ib3lSkGjA/ktQzwp4hZTI0l/dH9VHOFQflM8/9hPCYT2gsLVpF +7F2N++tMjgqbMI6Jve0gXLixpWFflr7X5UIBFW96k7/Aq2G+WUch/COQA6wTmfqw +OeP1wGd4Ka7YsgGByH5kuL60xDvtHG6+fYlnPXZAB5Fn86Ct6vRmWw9KUvLC7LKU +iBXDccJliY/y4vGFZH74EYlimurEfaBPiT5sxAk0Ke6hoJued3sZ39Qi+wuxMxFH +pleoFR/n1gBq2bu8FqTQaaNXB2Rsy7q4r5Fy1FxRJqDPgHJEmPx1k4rmYPq1VIaP +/ScOstPQgdMNBqVsBGoNYq7vewkzoPl6MkEwh6gP7IjtC1nvYxxwlGh0gESe3RFm +4MRh78EZaY9pmqIRAf/sRzajky26Aw+DkphmWNUjMTA +-> ssh-rsa kFDS0A +XsOTwrszUoHm2k4XSxiLniJZNWYfJOEn7riuDaQSGSW6ZpjMloD8K1FsZ/ZbMoUP +S/QD71rnETAhfQc8JAAHANOarxMXmSw3y1tSmlbL2h+TRnSoq74a1nK4Ble3aszu +y7tlUuUn3vEX6BVPRNOWM3bGW3oWNe5m0sMUAc4YSUXryWF4V48c/GbUp3T0OrRS +jm+5DWOPxt4VcLuCqe4Nv1jrjPnb7oui/7grMuottf3JRJJQxv9qZolRwlhkG2RN +4fuUSuOYnFUuHuaF2cfuTpOPaowLbh5H/Y6ETzOp+z9yNSuxRsdNgA63GrTsAorI +2axdnMakUsP7m3Xxu6YsVu8xP+Sso1xzPZoEQKA+2eol0fZpQvRPrZ59bqaf9p5U +VTIKSqIAIxyr/XN/s8S4ygaNKQZW8yBColG7TlggTth5v3XqAZ8RhcFXUg6z5lSr +RErV6Bio9JIZofvNEiJaqrl8uTo8dU4ymVuYZoEiT/mW3noqBrZlKUh6XZFMplmk +5giRTDThA3mirSTTELFCsc08kJMXqgkOzkPk5xm5kgP7VD6t/0SfGxetVWXOlUNd +dbprg8Oko1hdlO+LePY1n50TTFKBl9TeZWhvcLOhUizc0bTowUcXm+04Taf+MDwa +TMxplrtahOdCTz8k38c/HwBeHtfXRevh8A8Y1qnJXJY +-> piv-p256 vRzPNw AqccwzdKUA4RP2LzIfcTlAN9LsoEB/b7tGYyM8bk39Pn +f0srD9t9HaGY8OIAVImqJSrvHZRhxfMXkYwot4LJGeM +-> piv-p256 zqq/iw Aj8544WraFJMX2S6qyzi6CTal6sRnunmzbMO4KUQhJOO +BFiQSdLgrmgPnynqmSLNBqiWkyBme3KavSbi86HHSck +-> ssh-ed25519 YFSOsg Zece1bOI+mVc6079POREAnnzSG7ZytiTRDm+NzbbhVE +alK4ODfwrgRSDGWzcZmIuyZ88axaiMzSNfeGspsgk70 +-> ssh-ed25519 iHV63A LwfUkisQGB3txmxYYLlZSG6ddxVNVC9+UokxPiXEjRc +yRmtdHT9uM0YkS/s80jetMr1baDjGsaRubVKbJVPpCk +-> ssh-ed25519 BVsyTA +8LVssLl+DiF2f3H0KhAhvzEvTjciIAcRM9ZYwrGQh0 +CcQxWwMBdyXXzDv10vUmXBifYLXsHKOFd2/L95RGT5U +-> ssh-ed25519 +3V2lQ RWquIefIO5crVvrUxdatV7OvTv1Jabyq4IF209Ezkw0 +0SM43tcO7m7FQlNJe9QnhC9J9PwHoVxucRtZGpcACUE +--- xx8BodL5hv2CyeZ8m0tGXNzmH2DGaCveUNobqbAQK8U +)\9ct4ʿ~eJ}<[+*x>;m/&I:ϑ3 \ No newline at end of file diff --git a/secrets/restic-repo-garage-nachtigall-env.age b/secrets/restic-repo-garage-nachtigall-env.age new file mode 100644 index 0000000..fc0c27b Binary files /dev/null and b/secrets/restic-repo-garage-nachtigall-env.age differ diff --git a/secrets/restic-repo-garage-nachtigall.age b/secrets/restic-repo-garage-nachtigall.age new file mode 100644 index 0000000..c9cefe5 --- /dev/null +++ b/secrets/restic-repo-garage-nachtigall.age @@ -0,0 +1,43 @@ +age-encryption.org/v1 +-> ssh-ed25519 iDKjwg yk6WgkJbk16Yqc/aWojwDePfNZN3XgaiacpZqufw1hc +qx3x0zCUB6l7qPS9R9xGO41s6ESGsNd/ixglY4gYDtY +-> ssh-ed25519 uYcDNw nDZXlykiDEZIA+Srg6imZFRLAzhykR3PDVrfWb693Sg +MBJrrXbtLzBozetgfZaE52o1ixsrPK6Ojdp8sXhI3dc +-> ssh-rsa f5THog +WngnjCboeUafoR5NOg/+NFeW/ILxonIrcl7iUQLXoObcFWtmgzEebcogo3kqnkdk +cj7NnqQ/sFiHdPCBr+VyiWcP4BJHJeWF/w+Ht9SYP5+WlHUkC2IPxlcMzJFyy2ro +9PDq8FaPX5ZqarOfBW+U1pQsegxG9wkfoSzoF8NVL0jU5mwubPc+1s0ycbjMcGzP +CSCpWY0OqqRbCXj8gVBNOOoELVhgbNCO0oRWh6Iafqjrx/rO4MNAdZmUF9DiTZML +8QQjBFR7G8/+4ehGHn/9PF/0yVVsnPaJTEo3juS/By+NVcCihwP3b0SgQkjtp73+ +2QZL4XImwR0bBLDla86IjvZWH7GkLzR8iAw75FZ/FGIxZ/XgwRcUqtcI8m105KAD +iX1v7ai0LUYko4RPSqdDItEdGjK31Dl4bCdaLakO+aZdtc+60c7hx8uEoTp7JY9W +Qmyv4rt5bVUUAeH0IyR72vTDpTtXSkbp0vypk6Zq+yhYjbe0wmakAPCF4WbIV9gQ +YIoSyicQ3NYxfrQGcQvmct2dNXXZcCr8BW704/J5w7ngw44FiZDUIC2y562sHD84 +9rFO0obVGERJa55+MnZB4UYMqU3eWs+mkxHgWotx5yEtO0wMpTP9IFk92scJeV8h +bdr6fq1p6gtFlSNlA7P8A0go1SWs+qIoO/PEPyznoss +-> ssh-rsa kFDS0A +RM1VIV11yDWaG7KDnXbVt+Qo9kIC5kPO1JwpROuxbTH8tDGbu7bC2mJ6qsZo1R5x +ewtmDVwv+Gogs2drjQeQgdZH3qN0cMt34micbW2lvBW4NmvAGKEQ+dkkUgIWIhy9 +dNuFBCHAGqfw7FDqvX1Mm3e50CsbIVqpurBXe882seMjm/nSVzGgjOOQVaQKmNSg +04s0gsLzN1f98kQtKuNPlG8Fun9y1bKLzWpBT2iriQInkhcWSwYqg1M0yM7U01j3 +Kcxn4LJmgB9qNkloEKNpHCze5fgIGyOf+MsG4VN90CvwpNxy/EHrEyncXDxSxiCt +A81PVHCZfC7fQTR+hF2s1xGcW9mmtRpPPSEUrGY84cW2k8m4E5A9J7MJZ7FOKe6C +OY3LoU5KCV292ujHqYs1c7JSJRqVq4IMCupsNL6afzB/Fe+cV6GX7bXh1ZUl9HT7 +B6j1QH2xA9OGz+6VDrB+B6cdnxp02zRZpuS19uPTJqpIg4Sgc4vvw7YFQfz8AfUD +/SafkBpVKznEHl1/gO7bOMa1nTkNBicUp6d2Z/zNtJ75NJPb3qYc4aVsaEuyMPts +ieMR/iieeiDOMPhedtibfCWZ+0YrtyIrkkUsPK5yG76VbJgMjSRyEP+bXTedih/b +bTkE78BoV5DmNxGEAva2BJpMKtn3Or8dCgSudoSlI14 +-> piv-p256 vRzPNw Al8mhhyZ/0YFf7OSKeGm3LZhowpCdcITOhtjmky7Ygnq +CxFNUst8+6e6Cra/j7Pa2lZs3lHGLCOWRInb1VZTr2M +-> piv-p256 zqq/iw A+r/W9OhuPjuGXRuhp1vW45k/QzCFO6VLfp1W6l7RJVU +GxunFSBPJnzd5t5Ar42vr06tyJkJvZhljlGkHVZOFOQ +-> ssh-ed25519 YFSOsg e7udSQwtwKETHB0Re59fb1DdiBBPLDbV/JHmUUI4GSU +054wi1iKJm8lnWDjONCk+h2vea0setKqdCpXHuJaecI +-> ssh-ed25519 iHV63A S2sle86zYVPjtCozODRjqtTs6a5GksTpJHkmO/WYzHU +7h5kS8Hc3BiyhiWerEa9xPX6o+D/bxoJLK1fXFq1jWc +-> ssh-ed25519 BVsyTA 7meQJdKDB4JLKsYmBPgDBUnWhil1fKnoijm+uzHDemY +1bxklkYv5KYab9fXjMtz/w5QTUYMlZFTQG/khBftlWo +-> ssh-ed25519 +3V2lQ n1bF6+o/16zx7dEt/Um1gL30mARiuPaE6z3N+qjFZx4 +7ZjmhkuJDYXLcMoUEA0wosWcWZ1T1oR45kVhFyQwN1E +--- TbpcaLv/1jF23nynpaw1XjSKsO2t9hAxovPQHKhXAoQ +P^fE~6O[-cf]9e64El2=sWOQFCzcbT;[a \ No newline at end of file diff --git a/secrets/restic-repo-storagebox-metronom.age b/secrets/restic-repo-storagebox-metronom.age new file mode 100644 index 0000000..82e418e --- /dev/null +++ b/secrets/restic-repo-storagebox-metronom.age @@ -0,0 +1,43 @@ +age-encryption.org/v1 +-> ssh-ed25519 UE5Ceg Ut5S3qcz82qT9y6KnUG6WfgvhZ4Cq3akEnw6qkfOkHA +uwaOk4WQxkj/R8rw31ClUm7nS0nz5OFVyyqNdNjSKY0 +-> ssh-ed25519 uYcDNw kwQz6q16sYba+q2r/lH6Z0kSSXSxVrjGpK/3tPj4CT0 +nTo6jrcpQ9niGGxhuS7mZva6KnrYdjqvobW3yiZsYU4 +-> ssh-rsa f5THog +ugWQuX4fXVBJ/MWuVaM9Wj+kUFIpKV/+2C+Hxe4xg05/HmVWH95/TUE7QnhBKu1/ +Dda8oQL8xMSvThxUh0tY9pJjUMa/1ShfYpIAD6zE311bnPObDAZRBtS6fF5m5Vcj +9KL1ILwj7/Vj5/OMDM4BuEL1cmTmX2ohj/ho7hoWpU3ejohQKxpsH/atXAPevAgz +oajzoiQ2+qX18gW4tTLr9MqGuIQYDhj0f1YsPR5gMQEukwGJcQYaZZe78wRV/iGH +n4xbdRJGAxWyBZqKqeNKmh/VxdoC6wxIpAM3h/tchWA7RB2kn5rJBuk+XOF5pJLj +tOjMpoJClHwIgr8hmIMb5eI5bQdBZi8sIuwgaxe8GAjfy1fXt+XcR30pWW9xh/la +yLSEnz7OtjNPmHObWxMLmYkIX16qKXmdA1IMJib74THqboHOIFI08GVKWs6xCAr7 +9Mk4tFejwqPurFskwmX5Ubls8b5hNIO8Cz72RKwvGHwTFTtOR5Lzp/gRmCTD1qlb +aNYOZnduZ/ApxwG0OnNbC60C8+NB8EwRToiHmXLlnFP6WGlYKlSKy/WjJFjreFIJ +9hdiKCcHE87gsD2dEWHW4Hq4oZq/SwVL2FGCHC5dgohkY//i+aQVeSqAtvOR3tsb +CnKVhf+O6dMVZqNUeONGJ1oEaZwZJzBST9XXv6Yi2rY +-> ssh-rsa kFDS0A +EmZCGuxH9lUz/OuZKjKfkeone7oi+AETEpkUH909lc0LoTbk96Z9Q9IsRSxcrXh2 +CuQ9c8zZ3PgpwHRxLwwvCef4VMW2rgu98FLza3C41tww5ceudK/p/vwCPACUAV5e +T8fUGg2OTUFOvMpFtPejoD1fjrTHWahB4DW4r+ODbQM94fQiHjzq1qPDsFf4WpKF +1azagGfB6uejCewpQ+M+GnUZXDjOTi2IgA1+/dqQz5kGhVA9SnykfSxWGZKjcGPh +10EaBdrO5bqIh+Wf/b6GktFWKKTOipD6VzxiMbppMqr4pfRpFYy+okunl29ky+xk +6LTJHw5+19QB2YZMAbHCivmZpX+rfuCI/4JmUMfdAHrdkL56F/OWPx8j+2gFFkTm +qOUVKkuAKWfJFaUgfFbXtwwuE+JH/RuY1flG+PJjMr1xxnttFs3IYP4CVEH1j3Yg +APzd3PYpkW3fkCNT3PUJHDjVhzS3jvAjIgD2qDwc/AsQyMjJuyICSL8ciSb9PQMY +JeGX+4FjDpqgZeNYD1CIEEraAkoHoEBi2puNrsQY11qgnC/XXAfubz2XDtF4NhZS +Lr29oOuqwl9UglQq1yx0rmPyLvb5fstFvN1JELTuArOX9r7uyV4tEjhr1Emjcmlx +20XOvDtSRQNyG0JypayZcng4sXM8yLZngsUR+9kMZjo +-> piv-p256 vRzPNw AjEZFjCMWC+lzG6Mzn+yk1ylhtIS0rr8+uG3pONi8aUB +0dJi7kX8PFsGGo2nKxJ9DAi1Psz/Z93xusQ6hvgfo88 +-> piv-p256 zqq/iw AmPSSktHHwoEtSPexUIp4gro8kbxyiBi1F4I9PZBJXUN +SllB8/hq5mPkqidZnpSCktBs4IKyDn66Rq4Tn1CHjZ4 +-> ssh-ed25519 YFSOsg dQQ89fQbmnEc8ws1Ph1sBcnF9rLeOJHcT5aXzf3wdBQ +7Wve8saqRX4bbskIxPqbN6+danJimre2tNm5Y/nLBkI +-> ssh-ed25519 iHV63A 9Is8lLheIcDBr0A82rW+ercEGb4WOOHYu2ArrNuwWHQ +koc4Tp5KNMWlvqIY2Q5wGo1RV4PLLjbqZDH/te2+9vM +-> ssh-ed25519 BVsyTA SbXK3Qyz2KIN5+SuYQri6oQSVRFTsekvtCRissDF7nQ +EOuZGw1k2Ql6co/WFeEn2TmfGWN1ThCkksa1RD30yTE +-> ssh-ed25519 +3V2lQ HRGVqQxpU9SCs0tD2gSuqKz92HE3paG0JsHru3eliEE +U1z/FTfrf4sb4/gpEjHmpX559JSn7zsaiQUeej8ofpA +--- V+P4YcVeFP56hwKuk4ZLSzE/zCSvYyCTrKKRj48AuMA +%GY5fv]W1t]/M8U=bK[P1iϗ'yPU]6' fmey \ No newline at end of file diff --git a/secrets/restic-repo-storagebox-nachtigall.age b/secrets/restic-repo-storagebox-nachtigall.age new file mode 100644 index 0000000..6425221 Binary files /dev/null and b/secrets/restic-repo-storagebox-nachtigall.age differ diff --git a/secrets/restic-repo-storagebox.age b/secrets/restic-repo-storagebox.age deleted file mode 100644 index 47a89e5..0000000 Binary files a/secrets/restic-repo-storagebox.age and /dev/null differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix index ab52663..0da7892 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -5,6 +5,9 @@ let flora-6-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGP1InpTBN4AlF/4V8HHumAMLJzeO8DpzjUv9Co/+J09 root@flora-6"; metronom-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICLX6UvvrKALKL0xsNnytLPHryzZF5evUnxAgGokf14i root@metronom"; tankstelle-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJdF6cJKPDiloWiDja1ZtqkXDdXOCHPs10HD+JMzgeU4 root@tankstelle"; + trinkgenossin-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDZXRDpom/LtyoCxvRuoONARKxIT6wNUwEyUjzHRE7DG root@trinkgenossin"; + delite-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAKo7zlfQhcJ5/okFTOoOstZtmEL1iNlHxQ4q2baEcWT root@delite"; + blue-shell-host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9g9X0a/MaVtbh44IeLxcq+McuYec0GYAdLsseBpk5f root@blue-shell"; adminKeys = builtins.foldl' ( keys: login: keys ++ (builtins.attrValues login.secretEncryptionKeys) @@ -17,15 +20,32 @@ let flora6Keys = [ flora-6-host ]; metronomKeys = [ metronom-host ]; + + trinkgenossinKeys = [ trinkgenossin-host ]; + + deliteKeys = [ delite-host ]; + + blueshellKeys = [ blue-shell-host ]; + + garageKeys = [ + trinkgenossin-host + delite-host + blue-shell-host + ]; in { # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBB5XaH02a6+TchnyQED2VwaltPgeFCbildbE2h6nF5e root@nachtigall "nachtigall-root-ssh-key.age".publicKeys = nachtigallKeys ++ adminKeys; + # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDeKXqbhNzbXk15h2k8wGBByxMDCC6HE1/fwa4j6ECu root@metronom + "metronom-root-ssh-key.age".publicKeys = metronomKeys ++ adminKeys; "nachtigall-wg-private-key.age".publicKeys = nachtigallKeys ++ adminKeys; "tankstelle-wg-private-key.age".publicKeys = tankstelleKeys ++ adminKeys; "flora6-wg-private-key.age".publicKeys = flora6Keys ++ adminKeys; "metronom-wg-private-key.age".publicKeys = metronomKeys ++ adminKeys; + "trinkgenossin-wg-private-key.age".publicKeys = trinkgenossinKeys ++ adminKeys; + "delite-wg-private-key.age".publicKeys = deliteKeys ++ adminKeys; + "blue-shell-wg-private-key.age".publicKeys = blueshellKeys ++ adminKeys; "mastodon-secret-key-base.age".publicKeys = nachtigallKeys ++ adminKeys; "mastodon-otp-secret.age".publicKeys = nachtigallKeys ++ adminKeys; @@ -52,8 +72,13 @@ in "searx-environment.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-garage-metronom.age".publicKeys = metronomKeys ++ adminKeys; + "restic-repo-garage-metronom-env.age".publicKeys = metronomKeys ++ adminKeys; "restic-repo-droppie.age".publicKeys = nachtigallKeys ++ adminKeys; - "restic-repo-storagebox.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-storagebox-nachtigall.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-storagebox-metronom.age".publicKeys = metronomKeys ++ adminKeys; + "restic-repo-garage-nachtigall.age".publicKeys = nachtigallKeys ++ adminKeys; + "restic-repo-garage-nachtigall-env.age".publicKeys = nachtigallKeys ++ adminKeys; "drone-db-secrets.age".publicKeys = flora6Keys ++ adminKeys; "drone-secrets.age".publicKeys = flora6Keys ++ adminKeys; @@ -87,4 +112,10 @@ in "mail/crew.age".publicKeys = metronomKeys ++ adminKeys; "mail/erpnext.age".publicKeys = metronomKeys ++ adminKeys; "mail/hakkonaut.age".publicKeys = metronomKeys ++ adminKeys; + + # garage + "garage-rpc-secret.age".publicKeys = garageKeys ++ adminKeys; + "garage-admin-token.age".publicKeys = garageKeys ++ adminKeys; + + "acme-namecheap-env.age".publicKeys = garageKeys ++ adminKeys; } diff --git a/secrets/trinkgenossin-wg-private-key.age b/secrets/trinkgenossin-wg-private-key.age new file mode 100644 index 0000000..5af053e --- /dev/null +++ b/secrets/trinkgenossin-wg-private-key.age @@ -0,0 +1,43 @@ +age-encryption.org/v1 +-> ssh-ed25519 NID4eA Q3E8hBMDQRxoJx6UGzECMZmkffdgyYlhGaloKFNmxw0 +37DKT5sgmAEritSoPuW+O5dvjCH23pOAdFyJG0TnY6w +-> ssh-ed25519 uYcDNw zgfSabCBntiTnc0fdfDzpkq/AwUXSpyvsA14gkatP3w +tLbZDE6UB/xvC153mSGcGSSWKH+Ph1Ek5D+JTrWjzdk +-> ssh-rsa f5THog +0THw5q/Aa/wCzfqO/9YFBOvSfISS/O2cMHBlQ7NXzF2hlj+hzGjJeL2USmL8iZ7X +YToH0oy8lreVRYxfi/LUMyg14hQf11hTekT/sKc8m5eBm+8WiHbWJsQJKdRg6WVO +B2Ju+3QIZXBk7ajCIcVjgoJQy1JydXm5YQkZnI69icdtAEnYSEoVEpaPHkT7Et65 +UUC/eegltWFSeJl4bzgceVXO3VtszoG/KkL7ToT2WX2Hbnb4R3U8cWLOTr4I6hzM +90h6mNaorm3bd5fysOoU3G531/eAqcC7QZQQGyCOEBBHgx0w32ZKpjqu8q8c/f0M +VMOgE0JfK4/iB5E3dwGqRZ2G8iXu/cx0CQY98YAFCDOYExMsQzFXzqKq8KecVd+g +vaj598KJFxYskwrkGNXwIds2lPCte3HIa9XcGeQ4svaLYdQw5zsSIF32zOwAbxRn +1ABzp/T7V3BYyykJbeJi3UMoHUo3nsq75xClmXRnlTvQ7I0x62DrXdMNE9tJtqAF +lVUeD7gKlDPmYMK0QKbxFHYTVbdJ3d7UbJUgb2SxHpm5I8J7Wx29p6gLN7+swdIg ++y0Z8+qcABkeVHQ9OWwV0XYdMdLFovnc0pDAEvHL4rxv3E8W2Nv2mm0xW7I4HcG0 +h9uJ2lU4mn60YqBtso/cu+LzUHIPcHji5sRK8/qu+Tg +-> ssh-rsa kFDS0A +kXXvKZebwQLFofayT/0SFzdFl0e8xQbUJf+q47YHmPMlJY7nsQBs1fvmQsp7fsfW +TRdh14uVImErEQsuqNYgYDR/jBUVtRkySOXde8Q9QM/CZwwR7NMu8P2vBzZ6uXKL +amlZS8iYXWJKRgmxsgiONFZwfcB9TWhaDYsmeqFxV6ui2LGgtCBllttYzvyVNWZI +NXMg0bbkLd+I2svBSBX/p8rECxq5gUmr8PB2k+yrHuXJvnR8Hop7YjvbrC2qSy5r +6OOTButBV7cILTf03DPvd3f61uUqm/NapxN4UdEZDTmOYud2dF8Eqw+BCNIT2wZr +/KD49ElPlcWM8cCxBGaSTTT66mP3FWwIcCZVfdVrhf//TN/SAo+lcoN7m/p9Uj0i +Y5nM3JR7ZuiLHfXu+fTHBiWnWBtLkPYUDlGIGlFGinMQwi4CMqoUY7jROdjHuPkt +S0VK2ViRxBB5Z5tQSnL02+TNsDd+CDURRiBgWfdmk1kkh9o2SrSiGcxCV03UVEaE +4Q07ZjKJF9HeC6goK+QjSOvLHS2qHyJznUty7nAiAS+yPDlq6m13/dFTvFii7H2h +UJ+5MJcVHLd6VQhzjmwTQXCrbTn/FI2LkZgR4HPRFDElkmnMUV1NU/2gkwm7Z0gu +RaEAuYMoKZNBQ6eQgANst+LFA7ctwpz/d0PB8Gvjf6g +-> piv-p256 vRzPNw AmCpZNeI8ggIr211niro2CalG6ELXYubjXj2J01eSwL+ +IPXLB01UKFj7tptbB7FmNbbjDGrqbEoizjNzzJvNsXs +-> piv-p256 zqq/iw Auwb+rr9JfTX9VoTKaDobEGFPIwJZUFAMolG8SvZ5ix6 ++e5IWW7Sxy1T2F0Ykm1tKQIvGGJFODIrNdvrCKREvrI +-> ssh-ed25519 YFSOsg 5Eeo3PIUgfRgPrY/eR6aps8UB2NNNr9YJswZ5mPj5Fk +cN4Dwp+ZFN8UCptfVsAp3iGesYhry7umwGc77jom2Vo +-> ssh-ed25519 iHV63A RMH4ezLwPxlf9cLgFlWSrGMDdlySpIr22O3Nr4ESgkg +8Ll31aL8PCOFp5+TIhv7qYVzjnBMepWJSlT6PGBMtdM +-> ssh-ed25519 BVsyTA 9yQZMVRpIitqx4ggP9pswC2VBmtKHR8FqIiLAq6wdCs +g/dA5SXBUNyLFGuOEVwsPIu2sEyAS4y+5RlccymLfL0 +-> ssh-ed25519 +3V2lQ unqrENNB2tJvICc/nAi31TZ8c7ilbFreww51f/Mi4nQ +y7QWtFtEUq8elK+Q2HxpGav3nx3dxDQd5ikn9DpIJ20 +--- SJo44grQsKFl8WMnva4kMp88kMZ9D3EWnm3mN0Oe15c +~ڌx̆Il`u@'B#Ra ٣;(厳&G3<QsH~G ) \ No newline at end of file diff --git a/terraform/dns.tf b/terraform/dns.tf index e20c284..89674d8 100644 --- a/terraform/dns.tf +++ b/terraform/dns.tf @@ -24,6 +24,21 @@ resource "namecheap_domain_records" "pub-solar" { type = "A" address = "10.7.6.4" } + record { + hostname = "trinkgenossin.wg" + type = "A" + address = "10.7.6.5" + } + record { + hostname = "delite.wg" + type = "A" + address = "10.7.6.6" + } + record { + hostname = "blue-shell.wg" + type = "A" + address = "10.7.6.7" + } record { hostname = "nachtigall.wg" type = "AAAA" @@ -44,6 +59,21 @@ resource "namecheap_domain_records" "pub-solar" { type = "AAAA" address = "fd00:fae:fae:fae:fae:4::" } + record { + hostname = "trinkgenossin.wg" + type = "AAAA" + address = "fd00:fae:fae:fae:fae:5::" + } + record { + hostname = "delite.wg" + type = "AAAA" + address = "fd00:fae:fae:fae:fae:6::" + } + record { + hostname = "blue-shell.wg" + type = "AAAA" + address = "fd00:fae:fae:fae:fae:7::" + } record { hostname = "flora-6" type = "A" @@ -59,6 +89,36 @@ resource "namecheap_domain_records" "pub-solar" { type = "A" address = "49.13.236.167" } + record { + hostname = "trinkgenossin" + type = "A" + address = "85.215.152.22" + } + record { + hostname = "trinkgenossin" + type = "AAAA" + address = "2a01:239:35d:f500::1" + } + record { + hostname = "delite" + type = "A" + address = "5.255.119.132" + } + record { + hostname = "delite" + type = "AAAA" + address = "2a04:52c0:124:9d8c::2" + } + record { + hostname = "blue-shell" + type = "A" + address = "194.13.83.205" + } + record { + hostname = "blue-shell" + type = "AAAA" + address = "2a03:4000:43:24e::1" + } record { hostname = "auth" type = "CNAME" @@ -69,6 +129,51 @@ resource "namecheap_domain_records" "pub-solar" { type = "A" address = "80.71.153.210" } + record { + hostname = "buckets" + type = "A" + address = "85.215.152.22" + } + record { + hostname = "buckets" + type = "A" + address = "5.255.119.132" + } + record { + hostname = "buckets" + type = "A" + address = "194.13.83.205" + } + record { + hostname = "buckets" + type = "AAAA" + address = "2a01:239:35d:f500::1" + } + record { + hostname = "buckets" + type = "AAAA" + address = "2a04:52c0:124:9d8c::2" + } + record { + hostname = "buckets" + type = "AAAA" + address = "2a03:4000:43:24e::1" + } + record { + hostname = "*.buckets" + type = "CNAME" + address = "buckets.pub.solar." + } + record { + hostname = "web" + type = "CNAME" + address = "buckets.pub.solar." + } + record { + hostname = "*.web" + type = "CNAME" + address = "buckets.pub.solar." + } record { hostname = "tankstelle" type = "A"