Initial commit

This commit is contained in:
minish 2024-10-13 16:16:39 -04:00
commit bf2c813abd
Signed by: min
SSH Key Fingerprint: SHA256:NFjjdbkd6u7aoMlcrDCVvz6o2UBtlAuPm8IQ2vhZ3Fg
42 changed files with 1729 additions and 0 deletions

4
.envrc Normal file
View File

@ -0,0 +1,4 @@
if ! has nix_direnv_version || ! nix_direnv_version 3.0.5; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.5/direnvrc" "sha256-RuwIS+QKFj/T9M2TFXScjBsLR6V3A17YVoEW/Q6AZ1w="
fi
use flake

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/.direnv
# files decrypted by vscode-sops
.decrypted~*
/tmp

22
.sops.yaml Normal file
View File

@ -0,0 +1,22 @@
keys:
- &min 78795D9EBD425CBB3E850BC45DF91852CB14CEFF
- &eidola age1uqxzduupzes3tgfrrlret0n6thyldmlef60nqfzk689lmg6yayvsqpwxj6
- &silver age19yhycdgqczrvttszq97ccljh684x3r7f5dj4p0wdwqsrusqlcayse0vsh3
creation_rules:
- path_regex: k8s/apps/.*/secrets/.*\.yaml$
encrypted_regex: "^(data|stringData)$"
key_groups:
- pgp:
- *min
- path_regex: secrets/eidola\.yaml$
key_groups:
- pgp:
- *min
age:
- *eidola
- path_regex: secrets/silver\.yaml$
key_groups:
- pgp:
- *min
age:
- *silver

12
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"nix.enableLanguageServer": true,
"nix.serverSettings": {
"nil": {
"formatting": {
"command": [
"alejandra"
]
}
}
},
}

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# infra
infrastructure-as-code repo for systems I manage

293
flake.lock Normal file
View File

@ -0,0 +1,293 @@
{
"nodes": {
"breeze": {
"inputs": {
"crane": "crane",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1726958203,
"narHash": "sha256-7Upw1xPlncrFVegoAD0+16/6IoWedszIWPinFO6bJ2g=",
"ref": "refs/heads/main",
"rev": "495aee464d1570f00069bc8ea44b708b2f96e438",
"revCount": 60,
"type": "git",
"url": "https://git.min.rip/min/breeze.git"
},
"original": {
"type": "git",
"url": "https://git.min.rip/min/breeze.git"
}
},
"crane": {
"locked": {
"lastModified": 1725409566,
"narHash": "sha256-PrtLmqhM6UtJP7v7IGyzjBFhbG4eOAHT6LPYOFmYfbk=",
"owner": "ipetkov",
"repo": "crane",
"rev": "7e4586bad4e3f8f97a9271def747cf58c4b68f3c",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"deploy-rs": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"nixpkgs"
],
"utils": "utils"
},
"locked": {
"lastModified": 1718194053,
"narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a",
"type": "github"
},
"original": {
"owner": "serokell",
"repo": "deploy-rs",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1726842196,
"narHash": "sha256-u9h03JQUuQJ607xmti9F9Eh6E96kKUAGP+aXWgwm70o=",
"owner": "nix-community",
"repo": "disko",
"rev": "51994df8ba24d5db5459ccf17b6494643301ad28",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1726153070,
"narHash": "sha256-HO4zgY0ekfwO5bX0QH/3kJ/h4KvUDFZg8YpkNwIbg1U=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "bcef6817a8b2aa20a5a6dbb19b43e63c5bf8619a",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1726560853,
"narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1725690722,
"narHash": "sha256-4qWg9sNh5g1qPGO6d/GV2ktY+eDikkBTbWSg5/iD2nY=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "63f4d0443e32b0dd7189001ee1894066765d18a5",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"min-rip": {
"flake": false,
"locked": {
"lastModified": 1726983284,
"narHash": "sha256-JNWGpZ0L6Eu5ZgZsW1tLVbO3ujGKcY1e6SbvUR66V9s=",
"ref": "refs/heads/main",
"rev": "d22d0e86beafd6a0de643ab0d28d40e761395132",
"revCount": 24,
"type": "git",
"url": "ssh://git@git.min.rip/min/min.rip.git"
},
"original": {
"type": "git",
"url": "ssh://git@git.min.rip/min/min.rip.git"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1726838390,
"narHash": "sha256-NmcVhGElxDbmEWzgXsyAjlRhUus/nEqPC5So7BOJLUM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "944b2aea7f0a2d7c79f72468106bc5510cbf5101",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1725233747,
"narHash": "sha256-Ss8QWLXdr2JCBPcYChJhz4xJm+h/xjl4G0c0XlP6a74=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/356624c12086a18f2ea2825fed34523d60ccc4e3.tar.gz"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1725762081,
"narHash": "sha256-vNv+aJUW5/YurRy1ocfvs4q/48yVESwlC/yHzjkZSP8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "dc454045f5b5d814e5862a6d057e7bb5c29edc05",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"breeze": "breeze",
"deploy-rs": "deploy-rs",
"disko": "disko",
"flake-parts": "flake-parts",
"impermanence": "impermanence",
"min-rip": "min-rip",
"nixpkgs": "nixpkgs",
"sops-nix": "sops-nix"
}
},
"sops-nix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1726524647,
"narHash": "sha256-qis6BtOOBBEAfUl7FMHqqTwRLB61OL5OFzIsOmRz2J4=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "e2d404a7ea599a013189aa42947f66cede0645c8",
"type": "github"
},
"original": {
"owner": "Mic92",
"repo": "sops-nix",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

68
flake.nix Normal file
View File

@ -0,0 +1,68 @@
{
description = "k8s land";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05";
flake-parts.url = "github:hercules-ci/flake-parts";
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
disko.url = "github:nix-community/disko";
disko.inputs.nixpkgs.follows = "nixpkgs";
deploy-rs.url = "github:serokell/deploy-rs";
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
impermanence.url = "github:nix-community/impermanence";
min-rip.url = "git+ssh://git@git.min.rip/min/min.rip.git";
min-rip.flake = false;
breeze.url = "git+https://git.min.rip/min/breeze.git";
breeze.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs @ {self, ...}:
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
flake = let
hosts = import ./nixos/hosts {inherit inputs;};
in {
inherit (hosts) nixosConfigurations deploy;
};
systems = ["x86_64-linux"];
perSystem = {
pkgs,
system,
...
}: {
devShells.default = pkgs.mkShell {
packages = with pkgs; [
sops
ssh-to-age
# not included: age, gpg, pcscd, etc.
deploy-rs
nixos-anywhere
argocd
kubectl
kubernetes-helm
minikube
cilium-cli
hubble
yamllint
nil
alejandra
statix
deadnix
];
};
};
};
}

31
nixos/hosts/README.md Normal file
View File

@ -0,0 +1,31 @@
# NixOS Hosts
This directory contains configs for all NixOS hosts.
## Installing a new machine
✩ = on target machine, everything else is on your own device
1. ✩ If SB is desired, set a UEFI password and set Secure Boot to "Setup Mode". (This may be done by clearing Secure Boot keys on some boards)
2. ✩ Boot the [NixOS remote deploy image](https://github.com/nix-community/nixos-images/releases/tag/nixos-24.05)
3. Copy an appropriate config as a base
4. ```
mkdir tempkeys
../scripts/make_base_keys.sh
cd ..
```
5. Create a `secrets/NAME_OF_HOST.yaml` file.
6. Add the AGE key from `make_base_keys.sh` into `.sops.yaml`. Add necessary keys to `secrets/NAME_OF_HOST.yaml`. Make sure that the host's `secrets.nix` uses the proper YAML secrets file.
7. Ensure disk partitioning is correct. Make sure to change the rootfs disk in `disk-config.nix`.
8. Generate secure passwords, find their hashes with `mkpasswd -m sha-512`, and put them into the `root-pw` and `user-pw` properties of your , again ensuring there's no EOLs
9. Customize the config however you want
10. `./scripts/install.sh -c NAME_OF_HOST -k tempkeys root@IP_OF_HOST`
11. Delete the `tempkeys` folder if you're done with it
12. That is about it
## Deploying changes remotely
1. Make your changes
2. `nix flake check`
3. Commit them to Git
4. `deploy`, or if you're making breaking network changes where it's necessary, `deploy --magic-rollback false`
5. Hopefully they work! I have not worked out a way to do a manual rollback remotely yet

49
nixos/hosts/default.nix Normal file
View File

@ -0,0 +1,49 @@
{inputs, ...}: let
systems = {
eidola = import ./eidola {inherit inputs;};
silver = import ./silver {inherit inputs;};
};
inherit (inputs.nixpkgs) lib;
makeNixosConfigurations = systems:
lib.mapAttrs
(name: system:
lib.nixosSystem {
inherit (system) system;
modules =
system.modules
++ [
{
_module.args = {
inherit inputs;
};
}
]
++ (import ../modules);
})
systems;
makeDeployRsNodes = systems:
lib.mapAttrs
(name: system: {
hostname = system.deployment.host;
profiles.system = {
sshUser = system.deployment.user;
sshOpts = ["-p" "${toString system.deployment.port}"];
remoteBuild = system.deployment.buildOnTarget;
magicRollback = true;
path =
inputs.deploy-rs.lib.${system.system}.activate.nixos
inputs.self.nixosConfigurations.${name};
};
})
systems;
in {
nixosConfigurations = makeNixosConfigurations systems;
deploy.nodes = makeDeployRsNodes systems;
}

View File

@ -0,0 +1,67 @@
{
config,
pkgs,
...
}: {
imports = [
./hardware.nix
./disk-config.nix
./mounts.nix
./secrets.nix
];
networking.hostName = "eidola"; # Define your hostname.
time.timeZone = "America/New_York"; # Set your time zone.
# Allow unfree packages (firmware)
nixpkgs.config.allowUnfree = true;
# Basic networking
networking.networkmanager.enable = true;
networking.firewall.enable = true;
# Locales
i18n.defaultLocale = "en_US.UTF-8";
console = {
keyMap = "us";
};
# Users - eidola & root
users.users = {
root.hashedPasswordFile = config.sops.secrets."root-pw".path;
eidola = {
isNormalUser = true;
extraGroups = ["networkmanager" "wheel"];
hashedPasswordFile = config.sops.secrets."user-pw".path;
openssh.authorizedKeys.keys = import ../../keys/ssh.nix;
};
};
# Packages
environment.systemPackages = with pkgs; [
rsync
git
vim
fastfetch
htop
];
environment.variables.EDITOR = "vim";
# Enable ssh server
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.KbdInteractiveAuthentication = false;
};
# My modules
gen.system.hardening.disableSack = true;
gen.system.bootloader.luksSsh = {
enable = true;
port = 48722;
hostKeys = ["/persist/etc/secrets/initrd/ssh_host_ed25519_key"];
};
system.stateVersion = "24.05";
}

View File

@ -0,0 +1,23 @@
{inputs, ...}: rec {
system = "x86_64-linux";
pkgs = import inputs.nixpkgs {
inherit system;
};
deployment = {
host = "192.168.1.159";
user = "root";
port = 22;
buildOnTarget = false;
};
modules = [
inputs.sops-nix.nixosModules.sops
inputs.disko.nixosModules.disko
inputs.impermanence.nixosModules.impermanence
inputs.breeze.nixosModules.${system}.breeze
./configuration.nix
];
}

View File

@ -0,0 +1,94 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
};
esp = {
name = "ESP";
type = "EF00";
size = "1G";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["defaults"];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "encrypted";
extraOpenArgs = [];
settings = {
allowDiscards = true;
bypassWorkqueues = true;
};
passwordFile = "/tmp/luks-pw";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
};
};
nodev = {
"/" = {
fsType = "tmpfs";
mountOptions = [
"defaults"
"size=8G"
"mode=755"
];
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
nix = {
size = "64G";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/nix";
mountOptions = [
"defaults"
"noatime"
];
};
};
persist = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/persist";
mountOptions = [
"defaults"
"noatime"
];
};
};
};
};
};
};
}

View File

@ -0,0 +1,43 @@
# 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,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot = {
loader = {
efi.canTouchEfiVariables = true;
timeout = 2;
systemd-boot = {
enable = true;
configurationLimit = 3;
};
};
initrd = {
availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "r8169"];
kernelModules = [];
};
kernelModules = ["kvm-amd"];
extraModulePackages = [];
};
hardware.enableAllFirmware = true;
# 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;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View File

@ -0,0 +1,27 @@
{...}: {
environment.persistence."/persist" = {
hideMounts = true;
directories = [
# "/etc/secureboot"
"/etc/ssh"
"/etc/secrets"
"/var/log"
"/var/lib/systemd/coredump"
"/var/lib/nixos"
"/var/db/sudo"
];
files = [
"/etc/machine-id"
];
};
fileSystems = {
"/".neededForBoot = true;
"/etc/ssh" = {
depends = ["/persist"];
neededForBoot = true;
};
"/persist".neededForBoot = true; # no further config is needed, disko handles the rest
};
}

View File

@ -0,0 +1,9 @@
{...}: {
sops = {
defaultSopsFile = ../../../secrets/eidola.yaml;
age.sshKeyPaths = ["/persist/etc/ssh/ssh_host_ed25519_key"];
secrets."root-pw" = {neededForUsers = true;};
secrets."user-pw" = {neededForUsers = true;};
};
}

View File

@ -0,0 +1,99 @@
{
config,
pkgs,
...
}: let
net = {
address = "107.152.41.67";
prefixLength = 24;
subnet = "255.255.255.0";
gateway = "107.152.41.1";
interface = "eth0";
};
in {
imports = [
./hardware.nix
./disk-config.nix
./mounts.nix
./secrets.nix
./services
];
networking.hostName = "silver"; # Define your hostname.
time.timeZone = "America/Chicago"; # Set your time zone.
# Allow unfree packages (firmware)
nixpkgs.config.allowUnfree = true;
# Basic networking
networking.networkmanager.enable = true;
networking.firewall.enable = true;
# Networking - IP configuration
networking = {
enableIPv6 = false;
defaultGateway = {
address = net.gateway;
inherit (net) interface;
};
interfaces.${net.interface} = {
useDHCP = false;
ipv4.addresses = [
{inherit (net) address prefixLength;}
];
};
};
boot.kernelParams = [
# Manual IP configuration for initrd
"ip=${net.address}::${net.gateway}:${net.subnet}::${net.interface}:off"
];
# Locales
i18n.defaultLocale = "en_US.UTF-8";
console = {
keyMap = "us";
};
# Users - silver & root
users.users = {
root.hashedPasswordFile = config.sops.secrets."root-pw".path;
silver = {
isNormalUser = true;
extraGroups = ["networkmanager" "wheel"];
hashedPasswordFile = config.sops.secrets."user-pw".path;
openssh.authorizedKeys.keys = import ../../keys/ssh.nix;
};
};
# Packages
environment.systemPackages = with pkgs; [
rsync
git
vim
fastfetch
htop
speedtest-cli
];
environment.variables.EDITOR = "vim";
# Enable ssh server
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.KbdInteractiveAuthentication = false;
ports = [12208];
};
# My modules
gen.system.hardening.disableSack = true;
gen.system.bootloader.luksSsh = {
enable = true;
port = 48722;
hostKeys = ["/persist/etc/secrets/initrd/ssh_host_ed25519_key"];
};
system.stateVersion = "24.05";
}

View File

@ -0,0 +1,23 @@
{inputs, ...}: rec {
system = "x86_64-linux";
pkgs = import inputs.nixpkgs {
inherit system;
};
deployment = {
host = "min.rip";
user = "root";
port = 12208;
buildOnTarget = false;
};
modules = [
inputs.sops-nix.nixosModules.sops
inputs.disko.nixosModules.disko
inputs.impermanence.nixosModules.impermanence
inputs.breeze.nixosModules.${system}.breeze
./configuration.nix
];
}

View File

@ -0,0 +1,94 @@
{
disko.devices = {
disk = {
main = {
type = "disk";
device = "/dev/vda";
content = {
type = "gpt";
partitions = {
bios = {
name = "bios";
size = "1M";
type = "EF02";
};
boot = {
name = "boot";
type = "8300";
size = "1G";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = ["defaults"];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "encrypted";
extraOpenArgs = [];
settings = {
allowDiscards = true;
bypassWorkqueues = true;
};
passwordFile = "/tmp/luks-pw";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
};
};
nodev = {
"/" = {
fsType = "tmpfs";
mountOptions = [
"defaults"
"size=6G"
"mode=755"
];
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
nix = {
size = "24G";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/nix";
mountOptions = [
"defaults"
"noatime"
];
};
};
persist = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/persist";
mountOptions = [
"defaults"
"noatime"
];
};
};
};
};
};
};
}

View File

@ -0,0 +1,32 @@
# 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.
{
lib,
modulesPath,
...
}: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = ["virtio-pci"];
# 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;
boot.loader = {
timeout = 2;
grub = {
enable = true;
efiSupport = false;
enableCryptodisk = true;
};
};
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View File

@ -0,0 +1,32 @@
{...}: {
environment.persistence."/persist" = {
hideMounts = true;
directories = [
# "/etc/secureboot"
"/etc/ssh"
"/etc/secrets"
"/var/log"
"/var/lib/systemd/coredump"
"/var/lib/nixos"
"/var/lib/containers"
"/var/db/sudo"
"/var/lib/acme"
"/srv"
];
files = [
"/etc/machine-id"
];
};
fileSystems = {
"/".neededForBoot = true;
"/etc/ssh" = {
depends = ["/persist"];
neededForBoot = true;
};
"/persist".neededForBoot = true; # no further config is needed, disko handles the rest
};
}

View File

@ -0,0 +1,9 @@
{...}: {
sops = {
defaultSopsFile = ../../../secrets/silver.yaml;
age.sshKeyPaths = ["/persist/etc/ssh/ssh_host_ed25519_key"];
secrets."root-pw" = {neededForUsers = true;};
secrets."user-pw" = {neededForUsers = true;};
};
}

View File

@ -0,0 +1,49 @@
{config, ...}: let
httpIntPort = 14010;
dom = "picture.wtf";
in {
sops.secrets."svc-breeze-upload_key" = {
owner = "breeze";
group = "breeze";
};
services.nginx = {
virtualHosts.${dom} = {
locations."/" = {
proxyPass = "http://127.0.0.1:${toString httpIntPort}";
};
forceSSL = true;
enableACME = true;
};
};
systemd.tmpfiles.rules = [
"d /srv/uploads 0750 breeze breeze - -"
];
services.breeze = {
enable = true;
uploadKeyFile = config.sops.secrets."svc-breeze-upload_key".path;
settings = {
engine = {
base_url = "https://${dom}";
motd = "minish's image host, currently hosting %uplcount% files";
max_upload_len = 2147483648;
max_temp_lifetime = 43200;
max_strip_len = 16777216;
disk.save_path = "/srv/uploads";
cache = {
max_length = 268435456;
upload_lifetime = 1800;
scan_freq = 60;
mem_capacity = 4294967296;
};
};
http.listen_on = "127.0.0.1:${toString httpIntPort}";
logger.level = "info";
};
};
}

View File

@ -0,0 +1,34 @@
{...}: {
imports = [
./vcnotifier.nix
# ./nodemusicbot.nix
./breeze.nix
./min-rip.nix
./gitea.nix
./synapse.nix
];
security.acme = {
acceptTerms = true;
defaults.email = "minishcontact@riseup.net";
};
services.nginx = {
enable = true;
recommendedZstdSettings = true;
recommendedGzipSettings = true;
recommendedBrotliSettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
# proxy_http_version is already set to 1.1 by recommendedProxySettings
appendHttpConfig = ''
proxy_request_buffering off;
'';
clientMaxBodySize = "0";
};
networking.firewall.allowedTCPPorts = [22 80 443]; # exposed by nginx
networking.firewall.allowedUDPPorts = [443];
}

View File

@ -0,0 +1,68 @@
{config, ...}: let
sshExposeIp = "0.0.0.0"; # TODO: change this to the public-facing IP for prod
sshIntPort = 14022;
httpIntPort = 14020;
dom = "git.min.rip";
in {
services.nginx = {
virtualHosts.${dom} = {
locations."/" = {
proxyPass = "http://127.0.0.1:${toString httpIntPort}";
};
forceSSL = true;
enableACME = true;
};
streamConfig = ''
upstream gitea {
server 127.0.0.1:${toString sshIntPort};
}
server {
listen ${sshExposeIp}:22;
proxy_timeout 20s;
proxy_pass gitea;
}
''; # May not support IPv6, i'm unsure..
};
# Auto-create directories we need
systemd.tmpfiles.rules = [
"d /srv/gitea 0750 1000 1000 - -"
"d /srv/gitea/gitea 0750 1000 1000 - -"
"d /srv/gitea/runner 0750 1000 1000 - -"
];
virtualisation.oci-containers.containers.gitea = {
image = "docker.io/gitea/gitea:1.21.4";
environment = {
USER_UID = "1000";
USER_GID = "1000";
GITEA_WORK_DIR = "/data/gitea";
GITEA_CUSTOM = "/data/gitea";
GITEA_APP_INI = "/data/gitea/conf/app.ini";
};
volumes = [
"/srv/gitea/gitea:/data"
"/etc/localtime:/etc/localtime:ro"
];
ports = [
"${toString httpIntPort}:3000/tcp"
"${toString sshIntPort}:22/tcp"
];
};
sops.secrets."svc-gitea-runner-env" = {};
virtualisation.oci-containers.containers.gitea-runner = {
image = "docker.io/gitea/act_runner:0.2.6-dind-rootless";
environment = {
GITEA_INSTANCE_URL = "https://${dom}/";
DOCKER_HOST = "unix:///var/run/user/1000/docker.sock";
};
environmentFiles = [config.sops.secrets."svc-gitea-runner-env".path];
volumes = [
"/srv/gitea/runner:/data"
];
extraOptions = ["--privileged"];
};
}

View File

@ -0,0 +1,24 @@
{inputs, ...}: let
dom = "min.rip";
in {
services.nginx.virtualHosts.${dom} = {
root = "${inputs.min-rip}";
forceSSL = true;
enableACME = true;
locations."/" = {
tryFiles = "$uri $uri/ =404";
extraConfig = ''
add_header Cache-Control "max-age=15552000, must-revalidate";
'';
};
locations."/robots.txt" = {
priority = 10000;
return = ''200 "User-Agent: ia_archiver\nDisallow: /"'';
extraConfig = ''
add_header Content-Type text/plain;
'';
};
};
}

View File

@ -0,0 +1,9 @@
{config, ...}: {
sops.secrets."svc-nodemusicbot-env" = {};
virtualisation.oci-containers.containers.nodemusicbot = {
image = "git.min.rip/min/nodemusicbot:latest";
extraOptions = ["--rm"];
environmentFiles = [config.sops.secrets."svc-nodemusicbot-env".path];
};
}

View File

@ -0,0 +1,103 @@
{config, ...}: let
httpIntPort = 14030;
dbIntPort = 14032;
domHost = "mtx.min.rip";
domDelegate = "min.rip";
dir = "/srv/synapse";
dirSynapse = "${dir}/synapse";
dirDb = "${dir}/db";
in {
services.nginx = {
virtualHosts.${domHost} = {
locations."/" = {
proxyPass = "http://127.0.0.1:${toString httpIntPort}";
};
forceSSL = true;
enableACME = true;
};
virtualHosts.${domDelegate} = {
locations."/.well-known/matrix/client" = {
return = ''200 '{"m.homeserver": {"base_url": "https://${domHost}:443"}}' '';
extraConfig = ''
default_type application/json;
add_header Access-Control-Allow-Origin *;
'';
};
locations."/.well-known/matrix/server" = {
return = ''200 '{"m.server": "${domHost}:443"}' '';
extraConfig = ''
default_type application/json;
add_header Access-Control-Allow-Origin *;
'';
};
};
};
# Auto-create directories we need
systemd.tmpfiles.rules = [
"d ${dir} 0777 root root - -"
"d ${dirSynapse} 0750 224 224 - -"
"d ${dirDb} 0750 70 70 - -"
];
virtualisation.oci-containers.containers.synapse-db = {
image = "docker.io/postgres:12-alpine";
environment = {
POSTGRES_USER = "synapse";
POSTGRES_PASSWORD = "synapse";
POSTGRES_INITDB_ARGS = "--encoding=UTF-8 --lc-collate=C --lc-ctype=C";
};
volumes = [
"${dirDb}:/var/lib/postgresql/data"
];
ports = ["${toString dbIntPort}:5432/tcp"];
# extraOptions = [
# "--health-cmd" "pg_isready -U \${POSTGRES_USER}"
# "--health-interval=5s"
# "--health-retries=5"
# ];
};
sops.secrets."svc-synapse-synapse-config" = {
owner = "matrix-synapse";
group = "matrix-synapse";
mode = "0664";
};
services.matrix-synapse = {
enable = true;
withJemalloc = true;
dataDir = dirSynapse;
extraConfigFiles = [config.sops.secrets."svc-synapse-synapse-config".path];
settings = {
server_name = domDelegate;
listeners = [
{
bind_addresses = ["127.0.0.1"];
port = httpIntPort;
tls = false;
type = "http";
x_forwarded = true;
resources = [
{
names = ["client" "federation"];
compress = false;
}
];
}
];
database = {
name = "psycopg2";
args = {
user = "synapse";
password = "synapse";
database = "synapse";
host = "127.0.0.1";
port = dbIntPort;
};
};
report_stats = false;
};
};
}

View File

@ -0,0 +1,16 @@
{config, ...}: {
sops.secrets."svc-vcnotifier-env" = {};
systemd.tmpfiles.rules = [
"d /srv/vcnotifier 0750 root root - -"
];
virtualisation.oci-containers.containers.vcnotifier = {
image = "ghcr.io/zyme-xd/vcping:latest";
extraOptions = ["--rm"];
environmentFiles = [config.sops.secrets."svc-vcnotifier-env".path];
volumes = [
"/srv/vcnotifier/data.json:/usr/src/app/dist/data.json"
];
};
}

4
nixos/keys/ssh.nix Normal file
View File

@ -0,0 +1,4 @@
[
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBCZ7P/hl8DOMyTm5vGZuMrxBeSr2bmN2tp8zeiK+y/zq/fOi4rMIbfQif8KmaZ2UDTnpWj8DNfrPhfz6li1nzU="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPci/gIUGWdoiLXS8Nq8T6Fvh2Wtpxv6pnqyvbSWvzyoAAAABHNzaDo="
]

5
nixos/modules/README.md Normal file
View File

@ -0,0 +1,5 @@
# NixOS Modules
This directory contains NixOS modules that are shared across hosts.
* `modules/system` - automatically loaded on every host

View File

@ -0,0 +1,3 @@
[
./system
]

View File

@ -0,0 +1,5 @@
{...}: {
imports = [
./luks-ssh.nix
];
}

View File

@ -0,0 +1,52 @@
{
config,
lib,
...
}: let
baseCfg = config.gen.system.bootloader;
cfg = baseCfg.luksSsh;
in {
options.gen.system.bootloader.luksSsh = {
enable = lib.mkEnableOption "use boot process with luks unlock over ssh";
port = lib.mkOption {
type = lib.types.port;
description = "port for ssh server to listen on";
};
hostKeys = lib.mkOption {
type = lib.types.listOf lib.types.path;
description = "paths of host keys for the ssh server to use";
};
};
config = lib.mkIf cfg.enable {
# ### Use systemd-boot ###
# boot.loader = {
# efi.canTouchEfiVariables = true;
# timeout = 2;
# systemd-boot = {
# enable = true;
# configurationLimit = 3;
# };
# };
### LUKS unlock through SSH ###
boot.initrd = {
network = {
enable = true;
flushBeforeStage2 = true;
ssh = {
enable = true;
authorizedKeys = import ../../../keys/ssh.nix;
inherit (cfg) hostKeys port;
};
postCommands = ''
# Automatically ask for the password on SSH login
echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile
'';
};
};
};
}

View File

@ -0,0 +1,33 @@
{pkgs, ...}: {
imports = [
./hardening.nix
./limits.nix
./networking.nix
./boot
];
# Ensure root login is available on every machine (if ssh is enabled)
users.users.root.openssh.authorizedKeys.keys = import ../../keys/ssh.nix;
# Speed up the build a little bit, these aren't really needed
documentation = {
enable = false;
info.enable = false;
man.enable = false;
doc.enable = false;
nixos.enable = false;
};
# Immutable users
users.mutableUsers = false;
### Nix settings ###
nix = {
# Make sure flakes are enabled
settings.experimental-features = ["nix-command" "flakes"];
# Use our nixpkgs on legacy Nix tools.
# This way I don't have to `nix-channel --update` to use `nix-shell`
nixPath = ["nixpath=${pkgs.path}"];
};
}

View File

@ -0,0 +1,60 @@
{
config,
lib,
...
}: let
cfg = config.gen.system.hardening;
in {
options.gen.system.hardening = {
hardenBpf = lib.mkEnableOption "place heavier restrictions on BPF";
fullRpFilter = lib.mkEnableOption "enable full reverse path filtering. breaks dynamic routing, probably";
ignoreIcmpEcho = lib.mkEnableOption "ignore icmp echos. obviously, this makes pings unresponsive";
disableSack = lib.mkEnableOption "disable tcp sack";
disableConsole = lib.mkEnableOption "disable console. not recommended for test machines";
};
config = {
### Sysctls ###
boot.kernel.sysctl =
{
"kernel.kptr_restrict" = 1;
"kernel.dmesg_restrict" = 1;
"kernel.printk" = "3 3 3 3";
"dev.tty.ldisc_autoload" = 0;
"vm.unprivileged_userfaultfd" = 0;
"kernel.kexec_load_disabled" = 1;
"kernel.sysrq" = 0; # ignore sysrq key
"kernel.perf_event_paranoid" = 3;
"net.ipv4.tcp_rfc1337" = 1; # drop RSTs during time-wait state
}
// lib.mkIf cfg.ignoreIcmpEcho {
"net.ipv4.icmp_echo_ignore_all" = 1;
}
// lib.mkIf cfg.hardenBpf {
"kernel.unprivileged_bpf_disabled" = 1;
"net.core.bpf_jit_harden" = 2;
}
// lib.mkIf cfg.fullRpFilter {
"net.ipv4.conf.all.rp_filter" = 1;
"net.ipv4.conf.default.rp_filter" = 1;
}
// lib.mkIf cfg.disableSack {
"net.ipv4.tcp_sack" = 0;
"net.ipv4.tcp_dsack" = 0;
"net.ipv4.tcp_fack" = 0;
};
### Security options ###
security.protectKernelImage = true;
### Disable emergency access ###
systemd.enableEmergencyMode = false;
boot.initrd.systemd.emergencyAccess = false;
### Disable tty login ###
console = {
earlySetup = true;
enable = !cfg.disableConsole;
};
};
}

View File

@ -0,0 +1,13 @@
{...}: {
boot.kernel.sysctl."net.core.rmem_max" = 2500000;
boot.kernel.sysctl."fs.inotify.max_user_instances" = 1024;
security.pam.loginLimits = [
{
domain = "*";
type = "soft";
item = "nofile";
value = "655360";
}
];
}

View File

@ -0,0 +1,3 @@
{...}: {
networking.nameservers = ["1.1.1.1" "1.0.0.1"];
}

71
scripts/install.sh Executable file
View File

@ -0,0 +1,71 @@
#!/usr/bin/env bash
# fail on errors
set -e
die() {
echo >&2 "$@"
exit 1
}
# parse args
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-c|--nixos-config)
NAME="$2"
shift # past argument
shift # past value
;;
-k|--key-dir)
KEYDIR="$2"
shift # past argument
shift # past value
;;
*)
POSITIONAL_ARGS+=("$1") # save positional arg
shift # past argument
;;
esac
done
# check args
[ ! -f "$KEYDIR/host.pub" ] && die "host pubkey missing!"
[ ! -f "$KEYDIR/host" ] && die "host privkey missing!"
[ ! -f "$KEYDIR/host_initrd.pub" ] && die "host pubkey (initrd) missing!"
[ ! -f "$KEYDIR/host_initrd" ] && die "host privkey (initrd) missing!"
[ ! -f "$KEYDIR/luks-pw" ] && die "luks pw missing!"
# temp work dir
temp=$(mktemp -d)
cleanup() {
rm -rf "$temp"
}
trap cleanup EXIT
# prepare host keys
echo "Preparing host keys.."
dir="$temp/persist/etc/ssh"
install -d -m755 "$dir"
cp "$KEYDIR/host" "$dir/ssh_host_ed25519_key"
cp "$KEYDIR/host.pub" "$dir/ssh_host_ed25519_key.pub"
chmod 600 "$dir/ssh_host_ed25519_key"
# prepare host keys (initrd)
echo "Preparing host keys.. (initrd)"
dir="$temp/persist/etc/secrets/initrd"
install -d -m755 "$dir"
cp "$KEYDIR/host" "$dir/ssh_host_ed25519_key"
cp "$KEYDIR/host.pub" "$dir/ssh_host_ed25519_key.pub"
chmod 600 "$dir/ssh_host_ed25519_key"
# nixos-anywhere
echo "Starting install.."
nixos-anywhere \
--disk-encryption-keys "/tmp/luks-pw" "$KEYDIR/luks-pw" \
--extra-files "$temp" \
--flake .#$NAME \
"${POSITIONAL_ARGS[@]}"
echo -e "Finished install.\n" \
"Make sure to delete the SSH host keys from here if you are done with them."

36
scripts/make_base_keys.sh Executable file
View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
# fail on errors
set -e
die() {
echo >&2 "$@"
exit 1
}
# set up target folder
P="$1"
[[ -z "$P" || -d "$P" ]] && die "specify a non-existent path as a first argument"
mkdir "$P"
pushd "$P" >/dev/null
# host keys
echo "Generating SSH host keys.."
ssh-keygen -t ed25519 -f ./host -q -N "" -C ""
# host pubkey -> age key
echo "AGE key is: $(cat ./host.pub | ssh-to-age)"
# host keys (initrd)
echo "Generating SSH host keys.. (initrd)"
ssh-keygen -t ed25519 -f ./host_initrd -q -N "" -C ""
# luks pw
echo "Generating LUKS password file.."
echo -n "$(openssl rand -base64 24)" > ./luks-pw
# we are done
popd >/dev/null
echo "Finished generating keys." \
"Delete them or put them somewhere else once you're done with them."

12
scripts/rekey.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
SCRIPT_DIR="$(dirname "$0")"
ROOT_DIR="$(realpath "$SCRIPT_DIR/..")"
pushd "$ROOT_DIR" > /dev/null
rekey_dir() {
find $1 | xargs -i sops updatekeys -y {}
}
rekey_dir "secrets/*.yaml"

42
secrets/eidola.yaml Normal file
View File

@ -0,0 +1,42 @@
root-pw: ENC[AES256_GCM,data:g/dIT5d5w+FCAbxgGRJoMISgVTySEqXoBCV/jopu9Cgm4db9zAFWzZ7kUqOr8IQpEpCXyguYClIGExt0SztbRze8YPu9NilcUmYH7QmI+8oaEanYkvwpT5jyBU/M2eG0U9pMzcGI6hl2Ew==,iv:2HmGvFkRrnwYi5gjB4Na/ZayGoCFEsM4TDoqKlzhZUg=,tag:NLuval5PJ6AnDLvPGVvm7w==,type:str]
user-pw: ENC[AES256_GCM,data:gr+Dis3c5NWLWnfJG4eJUxwt574R3n40djeK68hukMNPx0qwGRAT5a7UQ5doxtDBgafcH1uCgqrsWwEmy9H5dS6WfLMivE5Uy213EcEk3YNUwI9d5vbdcbCcXWvPsyCu6sxS3x731EVVYA==,iv:4AHzVLoJD95d2UwwEAwxWP0G2gekHahBt4hDDA9ZSx0=,tag:03L3Ql070mt3oDV5YdrETg==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1uqxzduupzes3tgfrrlret0n6thyldmlef60nqfzk689lmg6yayvsqpwxj6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPOUhRbm95NndkQmRnc0VX
RFpaYVpoaE1mcDVuVTFYZ0hFbFBDalozM0RJCnVsUTZ2alJsY2s4TTJwRmQvYzBB
VDQ5SUVUWnRhdGN0elNybElpMmhsRzAKLS0tIC9DZGNnbU80Z3FTU1ZRMlZlUVMv
dVh4dFgrcWxtMFdUVVZTTm4rczVLaE0KBhCAwRHxtedfNZapyR3lbkxaiWxZR5lW
SQMhh9sUTnc/4B6StOhZEn+S7bVSRjPgvn9F+W7nCzcq/fpRYTcWvw==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-08-23T20:15:55Z"
mac: ENC[AES256_GCM,data:l/9IHeMTgA7hzF2EEcWW+wkKa4eRWCRLAmdee371qhipLzgJMKrme+qK2RkJd2txVIgz7m7FJG4HWEo4hVpjvcloY1H0U86dJndwKwGKYTmJPdcEH3HQgKVcx8b5pdkww1g98vnLfY/jwbMBkx3CrPliJw86QVglkmWWHR6W92w=,iv:cYlpkLN4PwHghbRn6KIWgUGEymdbFBsnUZ8xUBgif5g=,tag:jqLa5Nl74DUYFqDpuQPfUA==,type:str]
pgp:
- created_at: "2024-09-02T19:43:07Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAwAAAAAAAAAAAQ/6AsaPEjdfJlZs1ktcZ/zingDBMEzmjk7ZCN7kO1luTMFs
F7OaxAuyTlJNHU90ihJO94Gbtw0wqLewltl9nfNvHVSAWFtrZL2ReWGaAd5tS827
b91tDiifCQ+AWYrBMO0Bmd0RkgOQvfc3FJbOzxhb1mdzhCXKGbOCjOD41A3/nadK
xaaBHv1dGhW+YYvtibgUWfntSEa/drgB0REjGwbuLqvlPL2I/aP51edYyGqok8V/
+2dWRggxzm4st2jWngb7jpKSweEckOXki9Fu35bVOeV0/x6/iMQ+6f2OObHKu6pi
OB3kes6m5hsSWPgL0s9WbrKNpyrYeFhxzweGfm4KG8hZqU9aytf6Efo4a/dKin8j
DQBeFk3TxDgEzy9s+4xq6zq9yJeud4knd0cM82Qkghg/96E/M/RUf1l9MkbuDXCU
i6HPcDv7yMMPDexLWBD4HN2Kr418TJ8rtqb1lESWhjl7LlFQeXqD9mvy6tF9URZE
/L2ez4RCFZL4EAD345+gA584hmmmfqfXi7WrQZiA1EAZRcfcTm3sQlyHKMHkT5jr
oiFXxvG5hwjrfe9ipqhQWvFn06x5PielOUy9bfG0uza9/o9AEtQWdyMOIGFqm00o
04Xfv7PblknudezGKEbAOexZRDwZTGPOSNU1WCSguSUrEwX+mFKCtxD1MCxgowTS
XgFdTAk8t/pctB4QBBVUNdN36fU8Iah+K6+T658aQjHOCcIziBWUikHtD4yT/emu
BSqn41/VbLfyCosyXuOjqtMYg6evKRsVtqMx1GnInOHTjw2juOV1ZklVZNk8fzs=
=AZ8U
-----END PGP MESSAGE-----
fp: 78795D9EBD425CBB3E850BC45DF91852CB14CEFF
unencrypted_suffix: _unencrypted
version: 3.8.1

47
secrets/silver.yaml Normal file
View File

@ -0,0 +1,47 @@
root-pw: ENC[AES256_GCM,data:VCaP0E5A/UV1LLHotZK2B6AcfXZtQhi13t0wguv8tfoljwSbzcuYIhOMDIbL0BLPcaJRA7S//LhCDmQszfs/NNH5bcRBIoxPjUjKJ+V3ip/mEFWj1LypMIOWlKt1jOAtdMpmbK3uygGUNg==,iv:SOsaoox+J3rPTmw1MUJDwbFxexPVUYoIMfJo7YRTBvw=,tag:6R+Z1gsX37zgLyMz//wZvw==,type:str]
user-pw: ENC[AES256_GCM,data:5qJ/TLLdHyQVTftN882UJZ/FPAbHUGQkw1eXqajCt2Aw2wca5D7lWhwccix79Ws1DCK/w7cQjn48ys20faODQbcXO0TkQl6GYPqD+z3j2HETWuFgZqh0yW3pl/L1S5w4Jk2bALEJ7FXthg==,iv:9BETCLg4b2uE4QezblY6Krofvuieaqd3Cbk3ucpR58E=,tag:BeyHB28CqxiZa+KWjnv5Fw==,type:str]
svc-nodemusicbot-env: ENC[AES256_GCM,data:XoTn7WuFbfs8P+MvoMLfwpvUJ4IGGRMhdG1HXdmXGiI9s6ZTlipnIL70MYlih5kKn/wSBR2QDd9i6AErbz3hDUAkCh0tBuiZTDuSctUU0X2PCnrBnbg=,iv:ayrHgGO0zCl7apVKjMGI1MbtkN8V3j6dT0Mv07/KoYQ=,tag:TdAussU7bBg+jxpLufR1sw==,type:str]
svc-vcnotifier-env: ENC[AES256_GCM,data:8DwT17Aosvu7/Q2ecbir/t9HOtanPlFeBgLOzxtcv2BpCIGTEHqbVk9pegKQKc7lGhj5OrVg4HvNnQNEdEu5fLqB2XpMV8ltS7PL1wEz,iv:CfnXvb2wSRwQAURSLUrV4jofGnFOE6PQan7KPPhERjI=,tag:ve1Dh+63N4B6W7ZtvbDCFA==,type:str]
svc-breeze-upload_key: ENC[AES256_GCM,data:qNNH4/Q0rk2lsMImzpVe54+DbSAOiGjo,iv:rX9zvcPt6qSbPs6sKYO0T8EVaHU/u9QDoT/ISHdQSV4=,tag:kivJyeJGtuBP0l54qJ0t9w==,type:str]
svc-synapse-synapse-config: ENC[AES256_GCM,data:r8ZYi67CfftGheassCFiLOVcFUho+sNNe0XCkyQETHT6Q/w2jqO9eAVA2EDJyK4Vk3S4MP6ppcGxwocMmTYzkAjmtwf6a7GzUyh14+Lj5VTybvIKOze0wuLlsEUUYgU=,iv:HTnPaS5/ZvdJIMKiTfPffZmemp5IGTo/mIWrpafk/Fk=,tag:2HusbhzmxqsTMz5/78WCRA==,type:str]
svc-gitea-runner-env: ENC[AES256_GCM,data:M2hV8YM03dcBcgpJqbpiW6RGlhDvkfF/ExF+J1GF+39GnOsBWwPKteM5EAUB2Wrl/zRFifgfNLLdYgSEWhJsT1cBLhI3vwE5,iv:9/nvC3sS6XcLxgeKrEg/AaFhptXCm3uvGgSUMAz4p5Y=,tag:A1MnoJP6aekXuWHhlONnkw==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age19yhycdgqczrvttszq97ccljh684x3r7f5dj4p0wdwqsrusqlcayse0vsh3
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1emJhUTZTcVU1c3hSMjJK
MFcwOUYxbUV5ZUtJck9WSEpZS2Y0UFMrNTJRCjE1U1RNeUI4VUE0aURvamd6WHFF
NGE4RWExanUxelI5MjI3dmV2WjYyNDAKLS0tIGprYlhpd0ZrN3E2ZnRBZWZibGFy
Z1dZRXNCRkQ5cktZRGNpUXJaWHhrYTQKXQ1VOLDgptLJ8JKSBF8CWzyEGHnlbB+4
6nZlCHid4AFPRdAZ7cgEvJViBTSV05NOWE0pKYO3WZyWVKysfBKtgg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-10-13T07:04:09Z"
mac: ENC[AES256_GCM,data:/Mn3G6qHRPSZ1vt1ks30EYZ7UxhjmC7hdkZCl0ifipEfrl//zcsgtB96Q0V/35JWPVcVVoirLJsUmMcJZaevjAgIBys9jIjLgw5AN5R9QhVdRJ25tp/qX/JlKHuj9IVOM7n9hzVjauJYoWy6ftSeTmzyWoqTJrKvF6etaU4AUYs=,iv:Wcfr3sbVqOo7JTMH4kooLFDSQGTTV6ZMnKcWJqF6gK0=,tag:Dp9fEDTN4ko1YZp4O4EtWg==,type:str]
pgp:
- created_at: "2024-10-13T01:11:54Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hQIMAwAAAAAAAAAAAQ//Z6FAOpeM+H/nYQ/FIlcX/E87PxSwtpPoQJMcnBMaqTQL
vpedSVDHuvdNexJfT0cOj2Va8aguhMQcgGo+vaoKtMWXQhJYf/WsTMS3F0UJLHwZ
AvuH62F8C3EPPxFrrhP/bQeADtki7CDRzQuE9wLXjCT8KwY4bfFXD8NDA/9Rp+k7
mU5hOADqS6LBhaB55fFZ/e8MaCinezADDIDrz8VkTDzaRiU5g5VDdZnocCIp2Pz6
umlswmJXPic2BkbH4ALAfA/v8lsLXqi5ZnMkvwzc1YoACLKsJ0TexMXE3UgTvNb9
PzxDI1JzC+9RpGSBgy6uH2hnYNfgZ9S72Ha3vGR82k7WdEAQ4JzbD/WZNllb4aXw
oTx/XSyyLoUK1o66nV1KJRFsw9yhc4Af43lafur5cQp5snSJyYg6BKc+K25eRBYK
yBV0NdF9sRZlNd+FiIjj00iKJYXJ1YclPxb5NJ8OMhKYLR52migfj3F2WUj9sjRE
bKdXtjeRup2HhiCSS3pLlcaTSE7VaxCyaYbMT4GhZI4uFMt0WSrFHE3A1e/bk+GI
6v43SnCnzHX2o8ZPs6Oz7o6/HvhRLg0qarczqsEZbRVB8HFn0GrTLHSG743RFN73
Jyhy7/KXv1pqb049VNL7ya5+ZEEFgHAjYkEkkBUKYFcnRCwh7liJ7vTkwWfbRR3S
XgG1ClrtfTSCzEHrYE3FbDC05Bjaep1YiYkWEzHT7rAeFw1YkLZGPUuLcm55owHs
jCGCk1j97DdK5lJyJVuSoNspg57DOW6CsQaho1pKmu3c/OWx0le64sU9Sg4aWGo=
=TIIJ
-----END PGP MESSAGE-----
fp: 78795D9EBD425CBB3E850BC45DF91852CB14CEFF
unencrypted_suffix: _unencrypted
version: 3.8.1