Initial commit
This commit is contained in:
commit
bf2c813abd
|
@ -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
|
|
@ -0,0 +1,6 @@
|
|||
/.direnv
|
||||
|
||||
# files decrypted by vscode-sops
|
||||
.decrypted~*
|
||||
|
||||
/tmp
|
|
@ -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
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"nix.enableLanguageServer": true,
|
||||
"nix.serverSettings": {
|
||||
"nil": {
|
||||
"formatting": {
|
||||
"command": [
|
||||
"alejandra"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
# infra
|
||||
|
||||
infrastructure-as-code repo for systems I manage
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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
|
||||
];
|
||||
}
|
|
@ -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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
|
@ -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;};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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
|
||||
];
|
||||
}
|
|
@ -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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
}
|
|
@ -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
|
||||
};
|
||||
}
|
|
@ -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;};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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];
|
||||
}
|
|
@ -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"];
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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];
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBCZ7P/hl8DOMyTm5vGZuMrxBeSr2bmN2tp8zeiK+y/zq/fOi4rMIbfQif8KmaZ2UDTnpWj8DNfrPhfz6li1nzU="
|
||||
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIPci/gIUGWdoiLXS8Nq8T6Fvh2Wtpxv6pnqyvbSWvzyoAAAABHNzaDo="
|
||||
]
|
|
@ -0,0 +1,5 @@
|
|||
# NixOS Modules
|
||||
|
||||
This directory contains NixOS modules that are shared across hosts.
|
||||
|
||||
* `modules/system` - automatically loaded on every host
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
./system
|
||||
]
|
|
@ -0,0 +1,5 @@
|
|||
{...}: {
|
||||
imports = [
|
||||
./luks-ssh.nix
|
||||
];
|
||||
}
|
|
@ -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
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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}"];
|
||||
};
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -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";
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{...}: {
|
||||
networking.nameservers = ["1.1.1.1" "1.0.0.1"];
|
||||
}
|
|
@ -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."
|
|
@ -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."
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue