mirror of
https://github.com/Swarsel/.dotfiles.git
synced 2026-04-14 21:29:12 +02:00
Compare commits
8 commits
b6eb29fad9
...
a7cca50ff7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7cca50ff7 | ||
|
|
69b45ab0e2 | ||
|
|
905a879ab3 | ||
|
|
23365c0358 | ||
|
|
4a14888007 | ||
|
|
3b1b048ec1 | ||
|
|
495a2b6d70 | ||
|
|
f1fa6f8e99 |
43 changed files with 2766 additions and 1477 deletions
|
|
@ -46,6 +46,14 @@ creation_rules:
|
||||||
age:
|
age:
|
||||||
- *pyramid
|
- *pyramid
|
||||||
|
|
||||||
|
- path_regex: secrets/nginx/acme.json
|
||||||
|
key_groups:
|
||||||
|
- pgp:
|
||||||
|
- *swarsel
|
||||||
|
age:
|
||||||
|
- *twothreetunnel
|
||||||
|
- *eagleland
|
||||||
|
|
||||||
- path_regex: hosts/nixos/x86_64-linux/pyramid/secrets/[^/]+\.(yaml|json|env|ini|enc)$
|
- path_regex: hosts/nixos/x86_64-linux/pyramid/secrets/[^/]+\.(yaml|json|env|ini|enc)$
|
||||||
key_groups:
|
key_groups:
|
||||||
- pgp:
|
- pgp:
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -245,10 +245,10 @@ $ssh_root_cmd "nixos-generate-config --force --no-filesystems --root /mnt"
|
||||||
mkdir -p "$FLAKE"/hosts/nixos/"$target_arch"/"$target_hostname"
|
mkdir -p "$FLAKE"/hosts/nixos/"$target_arch"/"$target_hostname"
|
||||||
$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/hosts/nixos/"$target_arch"/"$target_hostname"/hardware-configuration.nix
|
$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/hosts/nixos/"$target_arch"/"$target_hostname"/hardware-configuration.nix
|
||||||
# ------------------------
|
# ------------------------
|
||||||
# green "Generating hostkey for ssh initrd"
|
green "Generating hostkey for ssh initrd"
|
||||||
# $ssh_root_cmd "mkdir -p $temp/etc/secrets/initrd /etc/secrets/initrd"
|
$ssh_root_cmd "mkdir -p $temp/etc/secrets/initrd /etc/secrets/initrd"
|
||||||
# $ssh_root_cmd "ssh-keygen -t ed25519 -N '' -f $temp/etc/secrets/initrd/ssh_host_ed25519_key"
|
$ssh_root_cmd "ssh-keygen -t ed25519 -N '' -f $temp/etc/secrets/initrd/ssh_host_ed25519_key"
|
||||||
# $ssh_root_cmd "cp $temp/etc/secrets/initrd/ssh_host_ed25519_key /etc/secrets/initrd/ssh_host_ed25519_key"
|
$ssh_root_cmd "cp $temp/etc/secrets/initrd/ssh_host_ed25519_key /etc/secrets/initrd/ssh_host_ed25519_key"
|
||||||
# ------------------------
|
# ------------------------
|
||||||
|
|
||||||
green "Deploying minimal NixOS installation on $target_destination"
|
green "Deploying minimal NixOS installation on $target_destination"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
topology.self = {
|
topology.self = {
|
||||||
icon = "devices.cloud-server";
|
icon = "devices.cloud-server";
|
||||||
};
|
};
|
||||||
swarselmodules.server.nginx = false;
|
|
||||||
|
|
||||||
swarselsystems = {
|
swarselsystems = {
|
||||||
flakePath = "/root/.dotfiles";
|
flakePath = "/root/.dotfiles";
|
||||||
|
|
@ -29,10 +28,12 @@
|
||||||
isCloud = true;
|
isCloud = true;
|
||||||
proxyHost = "twothreetunnel";
|
proxyHost = "twothreetunnel";
|
||||||
server = {
|
server = {
|
||||||
wireguard = {
|
wireguard.interfaces = {
|
||||||
|
wgProxy = {
|
||||||
isClient = true;
|
isClient = true;
|
||||||
serverName = "twothreetunnel";
|
serverName = "twothreetunnel";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
garage = {
|
garage = {
|
||||||
data_dir = {
|
data_dir = {
|
||||||
capacity = "150G";
|
capacity = "150G";
|
||||||
|
|
@ -60,7 +61,7 @@
|
||||||
postgresql = true;
|
postgresql = true;
|
||||||
attic = true;
|
attic = true;
|
||||||
garage = true;
|
garage = true;
|
||||||
hydra = true;
|
hydra = false;
|
||||||
dns-hostrecord = true;
|
dns-hostrecord = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
swarselmodules.server = {
|
swarselmodules.server = {
|
||||||
nginx = false;
|
|
||||||
bastion = true;
|
bastion = true;
|
||||||
dns-hostrecord = true;
|
dns-hostrecord = true;
|
||||||
# ssh = false;
|
# ssh = false;
|
||||||
|
|
|
||||||
|
|
@ -76,10 +76,12 @@ in
|
||||||
isCloud = true;
|
isCloud = true;
|
||||||
proxyHost = "twothreetunnel";
|
proxyHost = "twothreetunnel";
|
||||||
server = {
|
server = {
|
||||||
wireguard = {
|
wireguard.interfaces = {
|
||||||
|
wgProxy = {
|
||||||
isClient = true;
|
isClient = true;
|
||||||
serverName = "twothreetunnel";
|
serverName = "twothreetunnel";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
restic = {
|
restic = {
|
||||||
bucketName = "SwarselMoonside";
|
bucketName = "SwarselMoonside";
|
||||||
paths = [
|
paths = [
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@
|
||||||
topology.self = {
|
topology.self = {
|
||||||
icon = "devices.cloud-server";
|
icon = "devices.cloud-server";
|
||||||
};
|
};
|
||||||
swarselmodules.server.nginx = false;
|
|
||||||
|
|
||||||
|
|
||||||
swarselsystems = {
|
swarselsystems = {
|
||||||
flakePath = "/root/.dotfiles";
|
flakePath = "/root/.dotfiles";
|
||||||
|
|
@ -34,7 +32,6 @@
|
||||||
|
|
||||||
swarselmodules.server = {
|
swarselmodules.server = {
|
||||||
nsd = true;
|
nsd = true;
|
||||||
nginx = false;
|
|
||||||
dns-hostrecord = true;
|
dns-hostrecord = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,9 @@
|
||||||
isLinux = true;
|
isLinux = true;
|
||||||
isCloud = true;
|
isCloud = true;
|
||||||
server = {
|
server = {
|
||||||
wireguard = {
|
wireguard.interfaces = {
|
||||||
ifName = "wg";
|
wgProxy = {
|
||||||
|
# ifName = "wg";
|
||||||
isServer = true;
|
isServer = true;
|
||||||
peers = [
|
peers = [
|
||||||
"moonside"
|
"moonside"
|
||||||
|
|
@ -37,14 +38,15 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
};
|
||||||
} // lib.optionalAttrs (!minimal) {
|
} // lib.optionalAttrs (!minimal) {
|
||||||
swarselprofiles = {
|
swarselprofiles = {
|
||||||
server = true;
|
server = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
swarselmodules.server = {
|
swarselmodules.server = {
|
||||||
nginx = true; # for now
|
nginx = true;
|
||||||
oauth2-proxy = true; # for now
|
oauth2-proxy = true;
|
||||||
dns-hostrecord = true;
|
dns-hostrecord = true;
|
||||||
wireguard = true;
|
wireguard = true;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
{
|
|
||||||
"swarsel.win": {
|
|
||||||
"fulldomain": "ENC[AES256_GCM,data:CVasUSMRn/KWzVRlcYfTO/RL+W5Cz2JpDj0JLAKITXrDZrl+Wsg46X8zv4hX6NLj/wAyvXQ=,iv:N3DL4JPX8vWTbllFWcpNulwtDJ57xpHrAwoUxWhTzxs=,tag:CYWoK9uT121rFXQ5h69CZA==,type:str]",
|
|
||||||
"subdomain": "ENC[AES256_GCM,data:uM457vEJa10IV4SovBDUzLLlW+mPwh1SiWr8thQisFoe6zAk,iv:Tdbd5a20Gv/thkPfsvNiAbI86JjcDs70MAfk4yCZLgs=,tag:MulJiRWPs215x0bc+1jBiA==,type:str]",
|
|
||||||
"username": "ENC[AES256_GCM,data:ePE2BEKL5uaXqzGngW9ArhwP3qwDzwULtfwUfb5Q56VGGURp,iv:/GZRbyXHorcq1PIYlhfOmUVwCg0I/N4ZraEzSrc8qmA=,tag:wM5B1U0BsRsBAJg3qNOXpA==,type:str]",
|
|
||||||
"password": "ENC[AES256_GCM,data:RGzdi8IMqm+rtiuU4RtWGQ4N/7FYBbp5Pir8/k2V1QEdM8z7SIn0FQ==,iv:ThFbY9eZuEZoyzcWV5DwtSi8ugNwM49JfRof560Qx/Y=,tag:sgMaLrPB8WgpXWPzaCwOBQ==,type:str]",
|
|
||||||
"server_url": "ENC[AES256_GCM,data:zJdXoO7ED7qeskYJ9Wu0Rdprbvj/uP+Z,iv:ce+QXocqCjNKCsZRyVt6koUyc2lsTwPNMcfQyqbktN0=,tag:bQSE4/6va+V0TORWANLdUA==,type:str]"
|
|
||||||
},
|
|
||||||
"sops": {
|
|
||||||
"age": [
|
|
||||||
{
|
|
||||||
"recipient": "age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d",
|
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVZ0ErYjZTb2o1LzdZY2tz\nNUR0dy9DWkVyQlZBQU1WSmFja0pUN3NJSkNvClNLbTU5RFFwUkJQVUNML291eG5N\nZDlCK0JvMjVDL3lvMURMbFptQ1Z4ZWsKLS0tIFA3OEUrL2tXZGM3TFk4L2l6RUo0\nMVBZOFBYS2lablRuR0hneU02eURYQWMK1M9ng/GcFH+NEmknJ8SHOUxc8atX3p1E\nB/3+4dVWSwVdTEkG2VqQTdo/irjbTKpqZ0m5bg9zDhxZpyQ2lr2ePA==\n-----END AGE ENCRYPTED FILE-----\n"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"lastmodified": "2025-12-04T19:04:02Z",
|
|
||||||
"mac": "ENC[AES256_GCM,data:nWV/knCo/MeWTBrfq1VlV6SPEQ2i2P+le82S2So0BIxPfz8tqan0MdaIaKLFlapsT9VRJOv8ZCCXSLWeGcbEvfmEz4MP1E4iHcU/4YaO+n895D1JrjeyP1cgGisnXqe01xMXCsDY178sqxHcnDDlXp9foCem+mGjIlKGPYGu5Oo=,iv:qbavbW3MF4fx+E3aybBYaz/T/Hb63ggWml4Oe9WFz+I=,tag:05vBbBGDGRNaXJWoZn1bVw==,type:str]",
|
|
||||||
"pgp": [
|
|
||||||
{
|
|
||||||
"created_at": "2025-12-04T17:59:06Z",
|
|
||||||
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//bwwqP095CUku9qYMYLJToU9iuL7USF7UxfKQLgP7Lx3a\nilbrofOS508V2og32sZD8y8GGDCMc7HMQv8TcgIk/kq6jX5dHUYN68nVMQ8ZG0As\nW1kpo/cLZAPHoWWEG5E1INX+KSN3b/KhZgXohuVyrax3aTy0kcKeApAJlntr+gyV\nfjPjjvGxXrCXZHN6DzKZ+zqEIs18T0ByLtqLsYzTlD4FszISGCnf6Kr5jpj43BcA\ny1Hj6avzk1bQqPEFovf5JcB+O3DnkIwus+GlXihu/6gIiatbdshVKk/vDdR6TR1/\noDg2EV98uX1K+gEe1JvJdC1JrAPZkOtx4hiFcLVc5G6phdQ08hY4PZ8On4Yajkby\nj46FkPNLB4TwwSC2Ga03CadpaUK0twNGAH7oya3VXUiHqqu2rnVgUjrsZCr6yA4d\nJmumRiTHvnQjECQB5J837wXoDOivaaY0OszELM41p6UIhMTG4/SkkEvfgAI3goGN\nV5g4uBES/TGCedU5NS5EMtsjRoJSQDyvhfkzMUBDcUm8xQ3RKRtdqTZVkT75Ti6M\nmnZolAkqq3uWwmSTIXTgC7T2dnWLRVgfpj7hzZX43ucf5bXCn6QXoZscMUL9LKR5\nd3lyh66PoHghatrb0u3E1ub6XJQWkbDDkKDHRuYjU02Ai12oPd48nhyTuhnmeLCF\nAgwDC9FRLmchgYQBEACgklMklJy3J1U542h3ofmkH5otjNaWv14oVr2yNdOxhlIG\nDYTb9vuLL1lAwxOB7JW6sgPbS9TmiCU6ZBYDeQDmfth7yPWK3/Epmd5wmXDENqra\njoZcpNSvvMnescS0MJWsSF2BHJiwPJewuOCAiL0EXGYVNB7z54kAt342okScNDK2\ndS6/ddjVKFsSi73HmLqQk7wmYpZuqIGoJQXH+E2to8h19e35YxOEsnG2DcVyC7xZ\nqHeUfuM9BTVJmUvqFdovz3lYJ+xg2CjBf8u0jRKOhhufS8JAu9H2ye9dWPktslMF\nRjfRbTAwryVGYmajnlmfoge+OD0XsubSaT79BixZ6xwXgA8xrCvM8in8ZeYsug66\nrgA/I7sO2PPQBh+FNVfuxVVr4MC1Nehk3/JghYzF9Ip7uAvoB9bzi0Yx7L3wGY8i\nr5Rss81IIYvZY4NmPwsOkeX+v9k6GbrcBDa521nl9gz3Ll9Q59jicZBaNyuIvJ3f\nP/bmh1nZc9CM+uIP3A5e/5tUTS5E7judEmOeqlotOjZGdoqyGsG1VqJcrcyTzscY\n8LxCIJtQEeM4KoptKaIXt0Mu/puMzQxIpcx9eFDZ+SE7Cl1QXC6HRLW5N99AuD5f\nSmxquKsmc+xB+gNGkYuySeTqfklK3FLTvISXZmoAQKgqdgO0d+hpCpOQ9lkprtJc\nAbMyytjCe+RLnIWHXi1hjQyspcF8JvBgnRp0zWEZwn+C7QI7ChHlSIrudMohS76L\nN2rF646oaFcxr8mDHy9bebQDXlWahbDB/2jFm3/SuyARtKSg8/PaNcuh+c8=\n=LxIo\n-----END PGP MESSAGE-----",
|
|
||||||
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"unencrypted_suffix": "_unencrypted",
|
|
||||||
"version": "3.11.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"data": "ENC[AES256_GCM,data:8MWVw/6bXo/1lp3IKzN/9rt3RKoU+2bv8voov+CLQzYWZ8yzOCp3ZxtK1qT8ol4oalTdf5KLnVcHjBCrI2vECO10otXQMmr7oyDpe6ORvIFSSjc3wCfA5Ddaot4qd7Eqwg261mjk2xtk+rNG1mkIfshMDXwX0GKXEocp7kGFncagMNB5armJjMC/HeukQMi7yxe5ahpz4K10/mkQiluZKVYxzzFkBMAyAUgzNYJxRbxnalq0nNmtb7pSHaVJk0JnapFEy2Jnswl8NmbmmC7O91EdDxEWUX6MRI9DMoLehFcU/Ij/Nn994jC3RNywgkPDv29uEvz5BPw3y9KNYrqzuCj0GFTODgNBykjw/fmmYPfSfgXrpS4QRE3ZklLsFvADPMIwnW7F65XCx7VVy5j9OGT3NObdwweFpsqh1+gyIq/Ity/RpkQ6uqqseRclO1vQYAqDzuh1SOi3SBP3C7J2HNMfJy5TkhzyzRTBItaYbKqVPWm1nsBf8ZldCQ==,iv:wYfg9ZesEPMsF9GbM2r4vZoiOABPRyWOHUrZJMetPVQ=,tag:pJJ7yGSme2EXmk4duQ+0RA==,type:str]",
|
"data": "ENC[AES256_GCM,data:UKXEKxP1SDqQWktd3eQzkoqsk6k3m9Rj+JNk3xmdZmp5p+pXnY+uDltSIL2PTsOy7wtf4gp16jze1PhHvYojuN2nnou/D1KJALPHBgGiR8CgBlbX5nrCbtHrs4SZq+M7QihRV8lsG8gU0aIm0lDO83cJ0boUfnZdexDPjcuhYJj5nmgOG1bV60LOJNg7yn//hlVhovrf7ygXOk9HirDMmK9MVkKw5utD7iE4Cm7txrK1z9rQLJYM3kzwsWJAGkIc/IbI4Css10ScNK9VMKU4B596Dv2eCHvSIUJ8Y8AJrE/1+jp8XQW4aUMcFsbKpwjL2mOm0DSFupr/D60vJ1j5ovEIT4Vt51H4cpcBduBUCHoRZ1S/fZePxYaPunEI9lJVSQeANGevqXmvd8SSpO8YFN2S06CsFcx8hadQpq79uD7hm4tZzNUFOm2fytY9WMl0YWlSM4g3U30tKVVo+RMmm43oMaStOiyXUyohXjKY5QJqI+rJRRifKUhfze4Z4aGn,iv:nOU57gwkc3hld/+IqqHYtEiJYXzOFwTaG6cNEl7ZNHk=,tag:kRp580c9haQSQmOw2hBvrw==,type:str]",
|
||||||
"sops": {
|
"sops": {
|
||||||
"age": [
|
"age": [
|
||||||
{
|
{
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdEhDamZTRUhQZFNDTTl4\nVVVNNGZXa2h2THVzY0JWMjE2WjNJT0ZoblV3ClYzeEt4c0dWRzlISnN3NGthR21M\nTEtDQ011dFdhRVdPWlpweS9ma0N3dmsKLS0tIHFPQzQ5VzkyODZyY1JpcE4xR2Nl\nY2MrSERXTWkvNVZCR2xHUGh4ZXMvYTgK7pxPjnh3idl4QzBkR6LHyRskgqA3apS2\nkbg7As6wlEs34TAO8reyZknKTUd3Xif1v9RXiTcu1sEKHqkcqEoDog==\n-----END AGE ENCRYPTED FILE-----\n"
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqdEhDamZTRUhQZFNDTTl4\nVVVNNGZXa2h2THVzY0JWMjE2WjNJT0ZoblV3ClYzeEt4c0dWRzlISnN3NGthR21M\nTEtDQ011dFdhRVdPWlpweS9ma0N3dmsKLS0tIHFPQzQ5VzkyODZyY1JpcE4xR2Nl\nY2MrSERXTWkvNVZCR2xHUGh4ZXMvYTgK7pxPjnh3idl4QzBkR6LHyRskgqA3apS2\nkbg7As6wlEs34TAO8reyZknKTUd3Xif1v9RXiTcu1sEKHqkcqEoDog==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastmodified": "2025-12-03T16:34:02Z",
|
"lastmodified": "2025-12-22T01:24:25Z",
|
||||||
"mac": "ENC[AES256_GCM,data:OBETnq727ZC90fB5eZsgGGpLz8tImqaRH4LEQsxzDWbLBeGz/eFTBAHiB5MRHV1X87M2RLgtLsylu58AKmctPxQtAwuDl/oy6AIyGhEbK0bohzryHX7hv4JlWasTWoBg64nCu63YlvuWLiLPNOuqDe6ODa7kLfk+SW8rOoVzJSc=,iv:+5SgpVThJnJUeqZUc2Sn1nkYjnaDGMjjRaSgn0gDCo8=,tag:lIsAjeaO9R6zluwdibD2BQ==,type:str]",
|
"mac": "ENC[AES256_GCM,data:NtGHAadNGMfyCOqiaE/XRZqu4CnQ1IujgI3/IraY6E3luqzFVxJk/CgWD2rjbhLmaL7hd3Tay2LjL5uFxzM7kAE9QaaZtcxYKbudhznUdi/UEZ2ZtqyXqafXfCjEVbETaTAP3YGmQwJ/kAMj+FZp9yx7d6B8SVqWu1PatJGsOIA=,iv:OW6Xsr2MmEJq70TnEIJFgwLi3iMmKFV2Fy05a5G6Ibw=,tag:8KtNH6tEj/rQoht7FRDN3Q==,type:str]",
|
||||||
"pgp": [
|
"pgp": [
|
||||||
{
|
{
|
||||||
"created_at": "2025-12-01T23:06:36Z",
|
"created_at": "2025-12-01T23:06:36Z",
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,15 @@
|
||||||
isBtrfs = true;
|
isBtrfs = true;
|
||||||
isNixos = true;
|
isNixos = true;
|
||||||
isLinux = true;
|
isLinux = true;
|
||||||
proxyHost = "eagleland";
|
proxyHost = "twothreetunnel"; # mail shall not be proxied through twothreetunnel
|
||||||
|
server = {
|
||||||
|
wireguard.interfaces = {
|
||||||
|
wgProxy = {
|
||||||
|
isClient = true;
|
||||||
|
serverName = "twothreetunnel";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
} // lib.optionalAttrs (!minimal) {
|
} // lib.optionalAttrs (!minimal) {
|
||||||
|
|
||||||
|
|
@ -34,6 +42,8 @@
|
||||||
mailserver = true;
|
mailserver = true;
|
||||||
dns-hostrecord = true;
|
dns-hostrecord = true;
|
||||||
postgresql = true;
|
postgresql = true;
|
||||||
|
nginx = true;
|
||||||
|
wireguard = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
swarselprofiles = {
|
swarselprofiles = {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,16 @@
|
||||||
rootDisk = "/dev/sda";
|
rootDisk = "/dev/sda";
|
||||||
swapSize = "8G";
|
swapSize = "8G";
|
||||||
networkKernelModules = [ "igb" ];
|
networkKernelModules = [ "igb" ];
|
||||||
|
server = {
|
||||||
|
wireguard.interfaces = {
|
||||||
|
wgHome = {
|
||||||
|
isServer = true;
|
||||||
|
peers = [
|
||||||
|
"winters"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // lib.optionalAttrs (!minimal) {
|
} // lib.optionalAttrs (!minimal) {
|
||||||
|
|
@ -42,7 +52,7 @@
|
||||||
|
|
||||||
swarselmodules = {
|
swarselmodules = {
|
||||||
server = {
|
server = {
|
||||||
nginx = lib.mkForce false; # we get this from the server profile
|
wireguard = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"data": "ENC[AES256_GCM,data:0KCJFnho4v+hEcPsJkK3bSUaSZnaOcXDKIQ5loWxmRkvEYxoDgOEgcgnm9zzuZWGwxPLeN2HxeRIWsG7rDk5xxTiRF4rIVUvIObeDChMDsgL2G26VVzYc4+Vm7kT6GHINDiKMGspktNQRhqCh/0HaGkle62z9lBPn3IO+c/1dumWI6UwC9zqa9PTcsH8nWy8lpovdhD7B4+A/aPZhnC2qpBZGmveh3dJe+zR/iiRRqjFgQ1rdQr5USjQjA2wJvKzx1HdkRbw9OXnINdMeVGi05SItsRz0KekzpCwq2wwhyOon8Qlour4CugV20w+csbsqmbXdGaaB2BK4oMWJh74lb77HBk0zbWCXw==,iv:P9lXQtmHkq5q6BkKuF8N/Yvm3gul4SQ7bYqS7nzNIyU=,tag:lixSTKRQ5WJOozWfTj6V+A==,type:str]",
|
"data": "ENC[AES256_GCM,data:mi/EbLHjvOmJyK30E719clNAN/hq6FCS1ld0pLG4ahuuDkOfgbUr0vPEmhlxoIrkmD3HNkDufTlFsWezZ9s6OiZKS1ASRSPI96Js43BwVLotub1/YJaV0JMFNVoKTo9ag/5soaAbta0GNq0wExIjBNaVExCmNOs3puXCod4nOI9qmcn/ytx+98+3iZk8p87NTauX5W3jb87QjMqucWaEWxo4DLerkLI54baEMKJUULYRO4/BJ102pFq1twOVNm7v4R8FLbjknNL0A5T2ymmAJqOSpRLApcFJjSda6JkVoMV380a7Wa9cawLF/9xHRJn2K5R5uRx7JTLxL2VuW1olYMSrImO/d08277ZHymxeV07nJCyO/Y/0aR36P5YxJrUwNwKe31oR2RSm3Ns7u/DoC3gymYzbBLlBYMfocl34lL4EkK56W2qiGAfuEf6v/kXqS9X6si+rGDEaXkuS/0UEtsP7AxsUpRYHWngk/DGOUTzKXPkMsNv6IbxHSK4wpA1Xka93r13DrKTzcaoXOqEe+K9GWiJsJl0zAM4UEmYcXF7sh7WzYeeY3D1RT7nt4I0AHaPkt7PKsdo/DR3xQPUluQ553vVUe2rAMokqRVHHzM5OuGwng5iLb3u0fZaD,iv:bmp/x16E/gRXCDqcg5sUt+DRFCRsHIO0/01nr+uFR7Y=,tag:wFw8Efid68B88gTkAbCzuw==,type:str]",
|
||||||
"sops": {
|
"sops": {
|
||||||
"age": [
|
"age": [
|
||||||
{
|
{
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXc3VHa0p2MVdIdHRrbEVi\ndUwxMXA3cFpDODA0Z0MyUC9aemF4U2RXeUhrCmZjSDBLZ0twRk5rZG16blorQVVZ\nRE5SNE51bGlhYTVqcThFUVIvTWxwOW8KLS0tIEVHZ3Z6VVZHK2FUQWZQNVlOTkpL\nYUpNUSsyQllQL0lUa0FaODZiSjBDSk0KSJHdYoiOuma7YFjLpssAgw8BfBo5tl+o\nRvNt9rsXUlXEwMlcmYpkgUlsSAJnus+uE9AdBSvTyFRb9Wo696YFRg==\n-----END AGE ENCRYPTED FILE-----\n"
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXc3VHa0p2MVdIdHRrbEVi\ndUwxMXA3cFpDODA0Z0MyUC9aemF4U2RXeUhrCmZjSDBLZ0twRk5rZG16blorQVVZ\nRE5SNE51bGlhYTVqcThFUVIvTWxwOW8KLS0tIEVHZ3Z6VVZHK2FUQWZQNVlOTkpL\nYUpNUSsyQllQL0lUa0FaODZiSjBDSk0KSJHdYoiOuma7YFjLpssAgw8BfBo5tl+o\nRvNt9rsXUlXEwMlcmYpkgUlsSAJnus+uE9AdBSvTyFRb9Wo696YFRg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastmodified": "2025-12-15T22:09:17Z",
|
"lastmodified": "2025-12-22T09:31:39Z",
|
||||||
"mac": "ENC[AES256_GCM,data:C2Jwz+4Rz76ZVa/kT1OxtNp0gvdrEDd7QmlIgDv3WeocVb05TaWKap1Z9ytjR1U8ZBpYWiLJ4DGNh3WEL3/kQpTuO3WsaTP/VWQiQdPn9AKpTPjlFblRxcAUiN8yxj+OVScvb8FUBfTCHSXII8oqHmGHRXbsduauGtiFh3RKK4Y=,iv:5YpsTABeP1TNh3CeAsDEG2WloCFXvTR5sESOTpvvRgY=,tag:ezYnBZ34kQZ/sAJLjUrD7g==,type:str]",
|
"mac": "ENC[AES256_GCM,data:rOOL5gRTILzOnIU7LveEAI3HeLkf16wTZL4toxBqDiReWwXllCeUaFJ+n5awehit44LL1HrFVgZ/uUsnJBpF6WciPjXTKeRZsazhEKEuBhvcfJzvDQvj/ls5QsEXr/xuDmVaLNM7s7QCok+iefSS4Cu9IHhrmmdo1GyIw6gvNP0=,iv:pDnLtzMbGWR0PnIshenuNNvHIglvNFD+DJuUOapWGQI=,tag:9azzi8367Nq0Z0yGW8H5sg==,type:str]",
|
||||||
"pgp": [
|
"pgp": [
|
||||||
{
|
{
|
||||||
"created_at": "2025-12-15T22:09:23Z",
|
"created_at": "2025-12-15T22:09:23Z",
|
||||||
|
|
|
||||||
48
hosts/nixos/x86_64-linux/hintbooth/secrets/secrets.yaml
Normal file
48
hosts/nixos/x86_64-linux/hintbooth/secrets/secrets.yaml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
wireguard-private-key: ENC[AES256_GCM,data:DBCK92h8mGxDshB5OIEbyUENc6a4jmvzKPvljUn50AM1I5vBm/bSTDRStIM=,iv:K/OiPnAlXNt3RqBiBiiZqIY8vqsIw0kmKE+aeeVhr+Q=,tag:eloCJ7yjI2tpHMxwNxZDDw==,type:str]
|
||||||
|
sops:
|
||||||
|
age:
|
||||||
|
- recipient: age1wmx8y2hs83j2u5srdnfxljrzxm8jtxl6fr0mq7xf2ldxyglpzf2qq89rpx
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwTzZxNUdxbWUzbkp5eDE4
|
||||||
|
a3NGaWwrRXZxaXRvTmJjQUZHZU5wY3FpTTNrCmNxN21hU0dBd2piZUNCNndNaUNo
|
||||||
|
K252RGYyWVpXanZiVGMveXRnc0ViOFEKLS0tIFQ1T0dXUjlYdUNOcXJYZzA2YmtN
|
||||||
|
YWlkK0xrclpXYTkxUXFiNGMxU1NnMGcKCZzLfTPjeeGxyD43dOGDYsQVsw24cyHI
|
||||||
|
jz0B9VV07p33OP448eLyLgwpVFaNG0q+hXPH+0fb3V3foBT2QSeuPA==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2025-12-22T08:58:44Z"
|
||||||
|
mac: ENC[AES256_GCM,data:GnnNiw5DwXDCXEWqMa6eGYVNK4GyNvoNf9WK5wYE+uT8nolKD/pFEjqt++vHHlmEbPePhErAAu2vr7QGH/p8c+oEOEjiLJicMxJ72Bx8+5RLe4WuKO3GLTizgCy2f9Fr3gDWaKG8W9XF6xVzwPzzguRpfo1F0fmrPW6/EiGJDJ0=,iv:DWclKhUVp9UYc0F1J1k5+Y80dPK/RXoPDmylYlbmtiE=,tag:VgBHoVWPhOIwn7vuDwxKSw==,type:str]
|
||||||
|
pgp:
|
||||||
|
- created_at: "2025-12-22T08:56:58Z"
|
||||||
|
enc: |-
|
||||||
|
-----BEGIN PGP MESSAGE-----
|
||||||
|
|
||||||
|
hQIMAwDh3VI7VctTAQ/9E8KBoKOUyeIflZzmSriaoQ2/I0EnqKd9cLLFyqFFd4Gp
|
||||||
|
ZyOfaTqQE9/NWOG3KkG3iuHyCEdHjP14QolJDPPfuqjVnIkc0hKJ/TqwWb5OXurZ
|
||||||
|
hbkFZEYtuGWXGNugL0T/BnSUqXhd5sFBJueZD0LU7xBsmaDqMFlY//iheNEgq0RA
|
||||||
|
a3HeQL9gH4d1eUPje9XfcJ+onj9yYgejQ905ZIOAyrYTLVjnSc9HKJ3kz+rpin1J
|
||||||
|
2JHULBZEzigNiFXE2XmAatIM6PNBVJ21VL7CEPTt/qauRVHLsrz4PKcR/VMTzwJ/
|
||||||
|
A0hdMrYbYRKOL0rHDYyjpoeuKsUDNV0Gi//WQDXN9DGMREG5P4PH7+yPBcc+vgLK
|
||||||
|
E7B6RJcUFyuRh/n/KPGzKk1KX3KOQMjIKUaUGy7Ru91K8rG+/EH1ker6csDpe2aY
|
||||||
|
bYjtPnjiIvd/dR++JLALQJfCuFC6pUhGAC71Bchr4U2Rg+s9pRZBOYco7pJMJubd
|
||||||
|
rkt61MYFNpcZkyQ9mYAVCd13JcmoTsAtwmUkdU098tfCVA8sMRgFF1f2DK8iyRrq
|
||||||
|
jfh6pX1/UqFtOug8hElBJHMQkl9eAKla6COQeGtZC3LkxkKhkNLTcMLf4I5Tzf8o
|
||||||
|
ftxFw1eW4174Psg9vo+/T1zcOYQTVIUfnlPuK/oiCJIAWZ2U92HnCa9pwQe8nkSF
|
||||||
|
AgwDC9FRLmchgYQBD/4lFaFk9tlyBnTWY5yWJmpcV1gPSwLyeMnax/89/Nnixu1/
|
||||||
|
205CvMGEReFEQ4CDTp+WXwp7DA3PKqhg/hEq/x9cmH0kAkQg1n9QoJcd2UzDadfp
|
||||||
|
89ABsW5fBZJSLdHn3P06VIihe516GnsDA/KL88PdkYXpElgfqWXC8g2URKW6QeO5
|
||||||
|
j/XzOXDiMdO2+K37NcbwSQsMd0pc2BAJ4mmjvjm0aZe6ddF1917WYFkOZi09clNh
|
||||||
|
iYW8Vk4hmOkGqEO3zNjQkzZ6Ra9Cm4qr1BG7k+n4sxuwoae2T14/DlCSYh/llSTw
|
||||||
|
N25tWEeXeaAtQgVwoWYLrmSdCKYtxyACPrt6uEYaGE7wbXgBgCX91HuznlHiUvnG
|
||||||
|
uagiFMxr0x4G2Q+C8OuptKBneBcR6a21q3HaGdl/99F3fM7C2bvzv2y+ZScBP6fH
|
||||||
|
LvZjF/r3qrLONCqtaQ4Kw9LPzow8wMkCkshC7K0KNRq10ww7s9kbY8io4+QVLv3p
|
||||||
|
ZHbN+U+9BheVOAF8uX8V+OQfeFdp0VTbPZa7v1mLdbjshPNi7SEhlCjrtB8yqRtd
|
||||||
|
cl2tinqfWAosYt0xdUmH9uoY7bz9+BKIZ6FVl1huP2DEa5JAjnVItyLG+n2GpIqN
|
||||||
|
1SBaC/OCbJFawPmZgaWou+kxpLr7hu6kmPdCcdtHa4TYuanLkOTk0r0mztzhjNJe
|
||||||
|
Af5UVQLJJ7tduvLAB+vh/z91qgv0ftVDq4Kkr7Ma37OYAx4VzuHwEXNLKu2C6CwE
|
||||||
|
M7sp4ZglesyABMbOEhwxqg/kCYGS76kThwkrJfrgf82FgnMdUyYCMhhgy6iFow==
|
||||||
|
=izPI
|
||||||
|
-----END PGP MESSAGE-----
|
||||||
|
fp: 4BE7925262289B476DBBC17B76FD3810215AE097
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.11.0
|
||||||
|
|
@ -43,10 +43,6 @@
|
||||||
server = true;
|
server = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
swarselmodules.server = {
|
|
||||||
nginx = lib.mkForce false;
|
|
||||||
};
|
|
||||||
|
|
||||||
microvm.vms =
|
microvm.vms =
|
||||||
let
|
let
|
||||||
mkMicrovm = guestName: {
|
mkMicrovm = guestName: {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ self, lib, minimal, ... }:
|
{ self, lib, minimal, globals, ... }:
|
||||||
{
|
{
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
|
|
@ -15,11 +15,10 @@
|
||||||
loader.efi.canTouchEfiVariables = true;
|
loader.efi.canTouchEfiVariables = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# globals.hosts.${config.node.name}.ipv4 = config.repo.secrets.local.ipv4;
|
networking.hosts = {
|
||||||
# globals.networks.home.hosts.${config.node.name} = {
|
${globals.networks.home-lan.hosts.hintbooth.ipv4} = [ "server.hintbooth.${globals.domains.main}" ];
|
||||||
# ipv4 = config.repo.secrets.local.home-ipv4;
|
${globals.networks.home-lan.hosts.hintbooth.ipv6} = [ "server.hintbooth.${globals.domains.main}" ];
|
||||||
# mac = config.repo.secrets.local.home-mac;
|
};
|
||||||
# };
|
|
||||||
|
|
||||||
swarselsystems = {
|
swarselsystems = {
|
||||||
info = "ASRock J4105-ITX, 32GB RAM";
|
info = "ASRock J4105-ITX, 32GB RAM";
|
||||||
|
|
@ -32,10 +31,16 @@
|
||||||
isNixos = true;
|
isNixos = true;
|
||||||
proxyHost = "twothreetunnel";
|
proxyHost = "twothreetunnel";
|
||||||
server = {
|
server = {
|
||||||
wireguard = {
|
wireguard.interfaces = {
|
||||||
|
wgProxy = {
|
||||||
isClient = true;
|
isClient = true;
|
||||||
serverName = "twothreetunnel";
|
serverName = "twothreetunnel";
|
||||||
};
|
};
|
||||||
|
wgHome = {
|
||||||
|
isClient = true;
|
||||||
|
serverName = "hintbooth";
|
||||||
|
};
|
||||||
|
};
|
||||||
restic = {
|
restic = {
|
||||||
bucketName = "SwarselWinters";
|
bucketName = "SwarselWinters";
|
||||||
paths = [
|
paths = [
|
||||||
|
|
@ -67,37 +72,36 @@
|
||||||
|
|
||||||
swarselmodules.server = {
|
swarselmodules.server = {
|
||||||
diskEncryption = lib.mkForce false;
|
diskEncryption = lib.mkForce false;
|
||||||
wireguard = lib.mkDefault true;
|
nginx = true; # for php stuff
|
||||||
nfs = lib.mkDefault true;
|
acme = false; # cert handled by proxy
|
||||||
nginx = lib.mkDefault true;
|
wireguard = true;
|
||||||
kavita = lib.mkDefault true;
|
|
||||||
restic = lib.mkDefault true;
|
nfs = true;
|
||||||
jellyfin = lib.mkDefault true;
|
kavita = true;
|
||||||
navidrome = lib.mkDefault true;
|
restic = true;
|
||||||
spotifyd = lib.mkDefault true;
|
jellyfin = true;
|
||||||
mpd = lib.mkDefault true;
|
navidrome = true;
|
||||||
postgresql = lib.mkDefault true;
|
spotifyd = true;
|
||||||
matrix = lib.mkDefault true;
|
mpd = true;
|
||||||
nextcloud = lib.mkDefault true;
|
postgresql = true;
|
||||||
immich = lib.mkDefault true;
|
matrix = true;
|
||||||
paperless = lib.mkDefault true;
|
nextcloud = true;
|
||||||
transmission = lib.mkDefault true;
|
immich = true;
|
||||||
syncthing = lib.mkDefault true;
|
paperless = true;
|
||||||
grafana = lib.mkDefault true;
|
transmission = true;
|
||||||
emacs = lib.mkDefault true;
|
syncthing = true;
|
||||||
freshrss = lib.mkDefault true;
|
grafana = true;
|
||||||
jenkins = lib.mkDefault false;
|
emacs = true;
|
||||||
kanidm = lib.mkDefault true;
|
freshrss = true;
|
||||||
firefly-iii = lib.mkDefault true;
|
kanidm = true;
|
||||||
koillection = lib.mkDefault true;
|
firefly-iii = true;
|
||||||
radicale = lib.mkDefault true;
|
koillection = true;
|
||||||
atuin = lib.mkDefault true;
|
radicale = true;
|
||||||
forgejo = lib.mkDefault true;
|
atuin = true;
|
||||||
ankisync = lib.mkDefault true;
|
forgejo = true;
|
||||||
# snipeit = lib.mkDefault false;
|
ankisync = true;
|
||||||
homebox = lib.mkDefault true;
|
homebox = true;
|
||||||
opkssh = lib.mkDefault true;
|
opkssh = true;
|
||||||
garage = lib.mkDefault false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2244
index.html
2244
index.html
File diff suppressed because it is too large
Load diff
24
modules/home/common/attic-store-push.nix
Normal file
24
modules/home/common/attic-store-push.nix
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
{ lib, config, pkgs, ... }:
|
||||||
|
{
|
||||||
|
options.swarselmodules.attic-store-push = lib.mkEnableOption "enable automatic attic store push";
|
||||||
|
config = lib.mkIf config.swarselmodules.attic-store-push {
|
||||||
|
|
||||||
|
systemd.user.services.attic-store-push = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Attic store pusher";
|
||||||
|
Requires = [ "graphical-session.target" ];
|
||||||
|
After = [ "graphical-session.target" ];
|
||||||
|
PartOf = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "graphical-session.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${lib.getExe pkgs.attic-client} watch-store ${config.swarselsystems.mainUser}:${config.swarselsystems.mainUser}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
endme
|
endme
|
||||||
git-replace
|
git-replace
|
||||||
prstatus
|
prstatus
|
||||||
|
swarsel-gens
|
||||||
|
swarsel-switch
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@
|
||||||
serverAliveCountMax = 3;
|
serverAliveCountMax = 3;
|
||||||
hashKnownHosts = false;
|
hashKnownHosts = false;
|
||||||
userKnownHostsFile = "~/.ssh/known_hosts";
|
userKnownHostsFile = "~/.ssh/known_hosts";
|
||||||
controlMaster = "auto";
|
controlMaster = "no";
|
||||||
controlPath = "~/.ssh/master-%r@%n:%p";
|
controlPath = "~/.ssh/master-%r@%n:%p";
|
||||||
controlPersist = "5m";
|
controlPersist = "no";
|
||||||
};
|
};
|
||||||
} // confLib.getConfig.repo.secrets.common.ssh.hosts;
|
} // confLib.getConfig.repo.secrets.common.ssh.hosts;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,13 @@ in
|
||||||
description = "List of external dns nameservers";
|
description = "List of external dns nameservers";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
|
# largely based on https://github.com/oddlama/nix-config/blob/main/modules/secrets.nix
|
||||||
{ config, inputs, lib, ... }:
|
{ config, inputs, lib, nodes, ... }:
|
||||||
let
|
let
|
||||||
# If the given expression is a bare set, it will be wrapped in a function,
|
# If the given expression is a bare set, it will be wrapped in a function,
|
||||||
# so that the imported file can always be applied to the inputs, similar to
|
# so that the imported file can always be applied to the inputs, similar to
|
||||||
|
|
@ -53,7 +53,7 @@ in
|
||||||
|
|
||||||
secrets = lib.mkOption {
|
secrets = lib.mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
default = lib.mapAttrs (_: x: importEncrypted x inputs) config.repo.secretFiles;
|
default = lib.mapAttrs (_: x: importEncrypted x { inherit lib nodes inputs; }) config.repo.secretFiles;
|
||||||
type = lib.types.unspecified;
|
type = lib.types.unspecified;
|
||||||
description = "Exposes the loaded repo secrets. This option is read-only.";
|
description = "Exposes the loaded repo secrets. This option is read-only.";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, globals, ... }:
|
{ lib, config, globals, ... }:
|
||||||
{
|
{
|
||||||
topology.self = {
|
topology.self = {
|
||||||
icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server";
|
icon = lib.mkIf config.swarselsystems.isCloud "devices.cloud-server";
|
||||||
|
|
|
||||||
45
modules/nixos/server/acme.nix
Normal file
45
modules/nixos/server/acme.nix
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
{ self, pkgs, lib, config, globals, ... }:
|
||||||
|
let
|
||||||
|
inherit (config.repo.secrets.common) dnsProvider dnsBase dnsMail;
|
||||||
|
|
||||||
|
sopsFile = self + "/secrets/nginx/acme.json";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.swarselmodules.server.acme = lib.mkEnableOption "enable acme on server";
|
||||||
|
config = lib.mkIf config.swarselmodules.server.acme {
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
lego
|
||||||
|
];
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
secrets = {
|
||||||
|
acme-creds = { format = "json"; key = ""; group = "acme"; inherit sopsFile; mode = "0660"; };
|
||||||
|
};
|
||||||
|
templates."certs.secret".content = ''
|
||||||
|
ACME_DNS_API_BASE = ${dnsBase}
|
||||||
|
ACME_DNS_STORAGE_PATH=${config.sops.secrets.acme-creds.path}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.acme.members = lib.mkIf config.swarselmodules.server.nginx [ "nginx" ];
|
||||||
|
|
||||||
|
security.acme = {
|
||||||
|
acceptTerms = true;
|
||||||
|
defaults = {
|
||||||
|
inherit dnsProvider;
|
||||||
|
email = dnsMail;
|
||||||
|
environmentFile = "${config.sops.templates."certs.secret".path}";
|
||||||
|
reloadServices = [ "nginx" ];
|
||||||
|
dnsPropagationCheck = true;
|
||||||
|
};
|
||||||
|
certs."${globals.domains.main}" = {
|
||||||
|
domain = "*.${globals.domains.main}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.persistence."/persist" = lib.mkIf config.swarselsystems.isImpermanence {
|
||||||
|
directories = [{ directory = "/var/lib/acme"; }];
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
54
modules/nixos/server/attic-setup.nix
Normal file
54
modules/nixos/server/attic-setup.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{ lib, config, pkgs, globals, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options.swarselmodules.server.attic-setup = lib.mkEnableOption "enable attic setup";
|
||||||
|
config = lib.mkIf config.swarselmodules.server.attic-setup {
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
attic-client
|
||||||
|
];
|
||||||
|
|
||||||
|
sops = {
|
||||||
|
secrets = {
|
||||||
|
attic-cache-key = { };
|
||||||
|
};
|
||||||
|
templates = {
|
||||||
|
"attic-env".content = ''
|
||||||
|
DOMAIN=https://${globals.services.attic.domain}
|
||||||
|
TOKEN=${config.sops.placeholder.attic-cache-key}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.attic-cache-setup = {
|
||||||
|
description = "Ensure attic is authenticated to cache";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
EnvironmentFile = [
|
||||||
|
config.sops.templates.attic-env.path
|
||||||
|
];
|
||||||
|
};
|
||||||
|
script =
|
||||||
|
let
|
||||||
|
attic = lib.getExe pkgs.attic-client;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
set -eu
|
||||||
|
if ${attic} cache info ${config.swarselsystems.mainUser} >/dev/null 2>&1; then
|
||||||
|
echo "cache already authenticated"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "cache not authenticated, attempting login..."
|
||||||
|
${attic} login ${config.swarselsystems.mainUser} "$DOMAIN" "$TOKEN" --set-default
|
||||||
|
${attic} use ${config.swarselsystems.mainUser}
|
||||||
|
'';
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,11 @@ let
|
||||||
"/persist/${hostKeyPathBase}"
|
"/persist/${hostKeyPathBase}"
|
||||||
else
|
else
|
||||||
"${hostKeyPathBase}";
|
"${hostKeyPathBase}";
|
||||||
|
|
||||||
|
# this key is only used only for ssh to stage 1 in initial provisioning (in nix store)
|
||||||
|
generatedHostKey = pkgs.runCommand "initrd-hostkey" { } ''
|
||||||
|
${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f $out
|
||||||
|
'';
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options.swarselmodules.server.diskEncryption = lib.mkEnableOption "enable disk encryption config";
|
options.swarselmodules.server.diskEncryption = lib.mkEnableOption "enable disk encryption config";
|
||||||
|
|
@ -20,15 +25,15 @@ in
|
||||||
config = lib.mkIf (config.swarselmodules.server.diskEncryption && config.swarselsystems.isCrypted) {
|
config = lib.mkIf (config.swarselmodules.server.diskEncryption && config.swarselsystems.isCrypted) {
|
||||||
|
|
||||||
|
|
||||||
system.activationScripts."createPersistentStorageDirs" = lib.mkIf config.swarselsystems.isImpermanence {
|
# as soon as we hit a stable system, we will use a persisted key
|
||||||
deps = [ "ensureInitrdHostkey" ];
|
# @future me: dont mkIf this to minimal, we need to create this as soon as possible
|
||||||
};
|
system.activationScripts.ensureInitrdHostkey = {
|
||||||
system.activationScripts.ensureInitrdHostkey = lib.mkIf (config.swarselprofiles.server || minimal) {
|
|
||||||
text = ''
|
text = ''
|
||||||
[[ -e ${hostKeyPath} ]] || ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f ${hostKeyPath}
|
[[ -e ${hostKeyPath} ]] || ${pkgs.openssh}/bin/ssh-keygen -t ed25519 -N "" -f ${hostKeyPath}
|
||||||
'';
|
'';
|
||||||
deps = [
|
deps = [
|
||||||
"etc"
|
"users"
|
||||||
|
"createPersistentStorageDirs"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,7 +46,7 @@ in
|
||||||
"ip=${localIp}::${gatewayIp}:${subnetMask}:${config.networking.hostName}::none"
|
"ip=${localIp}::${gatewayIp}:${subnetMask}:${config.networking.hostName}::none"
|
||||||
];
|
];
|
||||||
initrd = {
|
initrd = {
|
||||||
secrets."${hostKeyPathBase}" = lib.mkIf (!minimal) hostKeyPathBase;
|
secrets."/tmp${hostKeyPathBase}" = if minimal then (lib.mkForce generatedHostKey) else (lib.mkForce hostKeyPath); # need to mkForce this or it behaves stateful
|
||||||
availableKernelModules = config.swarselsystems.networkKernelModules;
|
availableKernelModules = config.swarselsystems.networkKernelModules;
|
||||||
network = {
|
network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
@ -53,34 +58,13 @@ in
|
||||||
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/public/ssh/yubikey.pub"}''
|
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/public/ssh/yubikey.pub"}''
|
||||||
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/public/ssh/magicant.pub"}''
|
''command="/bin/systemctl default" ${builtins.readFile "${self}/secrets/public/ssh/magicant.pub"}''
|
||||||
];
|
];
|
||||||
hostKeys = [ hostKeyPathBase ];
|
hostKeys = [ "/tmp${hostKeyPathBase}" ]; # use a tmp file otherwise persist mount will be unhappy
|
||||||
};
|
};
|
||||||
# postCommands = ''
|
|
||||||
# echo 'cryptsetup-askpass || echo "Unlock was successful; exiting SSH session" && exit 1' >> /root/.profile
|
|
||||||
# '';
|
|
||||||
};
|
};
|
||||||
systemd = {
|
systemd = {
|
||||||
initrdBin = with pkgs; [
|
initrdBin = with pkgs; [
|
||||||
cryptsetup
|
cryptsetup
|
||||||
];
|
];
|
||||||
# NOTE: the below does put the text into /root/.profile, but the command will not be run
|
|
||||||
# services = {
|
|
||||||
# unlock-luks = {
|
|
||||||
# wantedBy = [ "initrd.target" ];
|
|
||||||
# after = [ "network.target" ];
|
|
||||||
# before = [ "systemd-cryptsetup@cryptroot.service" ];
|
|
||||||
# path = [ "/bin" ];
|
|
||||||
|
|
||||||
# serviceConfig = {
|
|
||||||
# Type = "oneshot";
|
|
||||||
# RemainAfterExit = true;
|
|
||||||
# };
|
|
||||||
|
|
||||||
# script = ''
|
|
||||||
# echo "systemctl default" >> /root/.profile
|
|
||||||
# '';
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
{ lib, config, globals, dns, confLib, ... }:
|
{ lib, config, globals, dns, confLib, ... }:
|
||||||
let
|
let
|
||||||
inherit (config.swarselsystems) sopsFile;
|
inherit (config.swarselsystems) sopsFile;
|
||||||
inherit (confLib.gen { name = "mailserver"; dir = "/var/lib/dovecot"; user = "virtualMail"; group = "virtualMail"; port = 443; }) serviceName serviceDir servicePort serviceUser serviceGroup serviceDomain serviceProxy proxyAddress4 proxyAddress6;
|
inherit (confLib.gen { name = "mailserver"; dir = "/var/lib/dovecot"; user = "virtualMail"; group = "virtualMail"; port = 443; }) serviceName serviceDir servicePort serviceUser serviceGroup serviceAddress serviceDomain serviceProxy proxyAddress4 proxyAddress6;
|
||||||
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 alias2_2 user3;
|
inherit (config.repo.secrets.local.mailserver) user1 alias1_1 alias1_2 alias1_3 alias1_4 user2 alias2_1 alias2_2 user3;
|
||||||
baseDomain = globals.domains.main;
|
baseDomain = globals.domains.main;
|
||||||
|
|
||||||
|
roundcubeDomain = config.repo.secrets.common.services.domains.roundcube;
|
||||||
|
endpointAddress4 = globals.hosts.${config.node.name}.wanAddress4 or null;
|
||||||
|
endpointAddress6 = globals.hosts.${config.node.name}.wanAddress6 or null;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
|
|
@ -12,13 +16,21 @@ in
|
||||||
config = lib.mkIf config.swarselmodules.server.${serviceName} {
|
config = lib.mkIf config.swarselmodules.server.${serviceName} {
|
||||||
|
|
||||||
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
|
nodes.stoicclub.swarselsystems.server.dns.${globals.services.${serviceName}.baseDomain}.subdomainRecords = {
|
||||||
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
|
"${globals.services.${serviceName}.subDomain}" = dns.lib.combinators.host endpointAddress4 endpointAddress6;
|
||||||
|
"${globals.services.roundcube.subDomain}" = dns.lib.combinators.host proxyAddress4 proxyAddress6;
|
||||||
};
|
};
|
||||||
|
|
||||||
globals.services.${serviceName} = {
|
globals.services = {
|
||||||
|
${serviceName} = {
|
||||||
domain = serviceDomain;
|
domain = serviceDomain;
|
||||||
|
proxyAddress4 = endpointAddress4;
|
||||||
|
proxyAddress6 = endpointAddress6;
|
||||||
|
};
|
||||||
|
roundcube = {
|
||||||
|
domain = roundcubeDomain;
|
||||||
inherit proxyAddress4 proxyAddress6;
|
inherit proxyAddress4 proxyAddress6;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
sops.secrets = {
|
sops.secrets = {
|
||||||
user1-hashed-pw = { inherit sopsFile; owner = serviceUser; };
|
user1-hashed-pw = { inherit sopsFile; owner = serviceUser; };
|
||||||
|
|
@ -83,7 +95,7 @@ in
|
||||||
enable = true;
|
enable = true;
|
||||||
# this is the url of the vhost, not necessarily the same as the fqdn of
|
# this is the url of the vhost, not necessarily the same as the fqdn of
|
||||||
# the mailserver
|
# the mailserver
|
||||||
hostName = serviceDomain;
|
hostName = roundcubeDomain;
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
$config['imap_host'] = "ssl://${config.mailserver.fqdn}";
|
$config['imap_host'] = "ssl://${config.mailserver.fqdn}";
|
||||||
$config['smtp_host'] = "ssl://${config.mailserver.fqdn}";
|
$config['smtp_host'] = "ssl://${config.mailserver.fqdn}";
|
||||||
|
|
@ -96,10 +108,11 @@ in
|
||||||
# the rest of the ports are managed by snm
|
# the rest of the ports are managed by snm
|
||||||
networking.firewall.allowedTCPPorts = [ 80 servicePort ];
|
networking.firewall.allowedTCPPorts = [ 80 servicePort ];
|
||||||
|
|
||||||
nodes.${serviceProxy}.services.nginx = {
|
services.nginx = {
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
"${serviceDomain}" = {
|
"${roundcubeDomain}" = {
|
||||||
enableACME = true;
|
useACMEHost = globals.domains.main;
|
||||||
|
enableACME = false;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
acmeRoot = null;
|
acmeRoot = null;
|
||||||
locations = {
|
locations = {
|
||||||
|
|
@ -112,5 +125,31 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nodes.${serviceProxy}.services.nginx = {
|
||||||
|
upstreams = {
|
||||||
|
${serviceName} = {
|
||||||
|
servers = {
|
||||||
|
"${serviceAddress}:${builtins.toString servicePort}" = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
virtualHosts = {
|
||||||
|
"${roundcubeDomain}" = {
|
||||||
|
useACMEHost = globals.domains.main;
|
||||||
|
|
||||||
|
forceSSL = true;
|
||||||
|
acmeRoot = null;
|
||||||
|
locations = {
|
||||||
|
"/" = {
|
||||||
|
proxyPass = "https://${serviceName}";
|
||||||
|
extraConfig = ''
|
||||||
|
client_max_body_size 0;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
{ pkgs, lib, config, globals, ... }:
|
{ pkgs, lib, config, ... }:
|
||||||
let
|
let
|
||||||
inherit (config.repo.secrets.common) dnsProvider dnsBase dnsMail;
|
|
||||||
|
|
||||||
serviceUser = "nginx";
|
serviceUser = "nginx";
|
||||||
serviceGroup = serviceUser;
|
serviceGroup = serviceUser;
|
||||||
|
|
||||||
|
|
@ -81,40 +79,12 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
config = lib.mkIf config.swarselmodules.server.nginx {
|
config = lib.mkIf config.swarselmodules.server.nginx {
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
lego
|
|
||||||
];
|
|
||||||
|
|
||||||
sops = lib.mkIf (config.node.name == config.swarselsystems.proxyHost) {
|
swarselmodules.server.acme = lib.mkDefault true;
|
||||||
secrets = {
|
|
||||||
acme-creds = { format = "json"; key = ""; group = "acme"; sopsFile = config.node.secretsDir + "/acme.json"; mode = "0660"; };
|
|
||||||
};
|
|
||||||
templates."certs.secret".content = ''
|
|
||||||
ACME_DNS_API_BASE = ${dnsBase}
|
|
||||||
ACME_DNS_STORAGE_PATH=${config.sops.secrets.acme-creds.path}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
users.groups.acme.members = [ "nginx" ];
|
|
||||||
|
|
||||||
security.acme = lib.mkIf (config.node.name == config.swarselsystems.proxyHost) {
|
|
||||||
acceptTerms = true;
|
|
||||||
defaults = {
|
|
||||||
inherit dnsProvider;
|
|
||||||
email = dnsMail;
|
|
||||||
environmentFile = "${config.sops.templates."certs.secret".path}";
|
|
||||||
reloadServices = [ "nginx" ];
|
|
||||||
dnsPropagationCheck = true;
|
|
||||||
};
|
|
||||||
certs."${globals.domains.main}" = {
|
|
||||||
domain = "*.${globals.domains.main}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
environment.persistence."/persist" = lib.mkIf config.swarselsystems.isImpermanence {
|
environment.persistence."/persist" = lib.mkIf config.swarselsystems.isImpermanence {
|
||||||
directories = [{ directory = "/var/lib/acme"; }];
|
|
||||||
files = [ dhParamsPathBase ];
|
files = [ dhParamsPathBase ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ with dns.lib.combinators; {
|
||||||
SOA = {
|
SOA = {
|
||||||
nameServer = "soa";
|
nameServer = "soa";
|
||||||
adminEmail = "admin@${globals.domains.main}"; # this option is not parsed as domain (we cannot just write "admin")
|
adminEmail = "admin@${globals.domains.main}"; # this option is not parsed as domain (we cannot just write "admin")
|
||||||
serial = 2025120506; # update this on changes for secondary dns
|
serial = 2025122204; # update this on changes for secondary dns
|
||||||
};
|
};
|
||||||
|
|
||||||
useOrigin = false;
|
useOrigin = false;
|
||||||
|
|
@ -13,7 +13,23 @@ with dns.lib.combinators; {
|
||||||
"srv"
|
"srv"
|
||||||
] ++ globals.domains.externalDns;
|
] ++ globals.domains.externalDns;
|
||||||
|
|
||||||
CAA = letsEncrypt config.repo.secrets.common.dnsMail;
|
CAA = [
|
||||||
|
{
|
||||||
|
issuerCritical = false;
|
||||||
|
tag = "issue";
|
||||||
|
value = "letsencrypt.org";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
issuerCritical = false;
|
||||||
|
tag = "issuewild";
|
||||||
|
value = "letsencrypt.org";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
issuerCritical = false;
|
||||||
|
tag = "iodef";
|
||||||
|
value = "mailto:${config.repo.secrets.common.dnsMail}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
A = [ config.repo.secrets.local.dns.homepage-ip ];
|
A = [ config.repo.secrets.local.dns.homepage-ip ];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@
|
||||||
emacs
|
emacs
|
||||||
vim
|
vim
|
||||||
sops
|
sops
|
||||||
swarsel-deploy
|
|
||||||
tmux
|
tmux
|
||||||
busybox
|
busybox
|
||||||
|
swarsel-deploy
|
||||||
|
swarsel-gens
|
||||||
|
swarsel-switch
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,176 +1,217 @@
|
||||||
{ self, lib, pkgs, config, confLib, nodes, globals, ... }:
|
{ self, lib, pkgs, config, confLib, nodes, globals, ... }:
|
||||||
let
|
let
|
||||||
wgInterface = "wg0";
|
inherit (confLib.gen {
|
||||||
inherit (confLib.gen { name = "wireguard"; port = 52829; user = "systemd-network"; group = "systemd-network"; }) servicePort serviceName serviceUser serviceGroup;
|
name = "wireguard";
|
||||||
|
port = 52829;
|
||||||
|
user = "systemd-network";
|
||||||
|
group = "systemd-network";
|
||||||
|
}) servicePort serviceName serviceUser serviceGroup;
|
||||||
|
|
||||||
inherit (config.swarselsystems) sopsFile;
|
inherit (config.swarselsystems) sopsFile;
|
||||||
wgSopsFile = self + "/secrets/repo/wg.yaml";
|
wgSopsFile = self + "/secrets/repo/wg.yaml";
|
||||||
inherit (config.swarselsystems.server.wireguard) peers isClient isServer serverName serverNetConfigPrefix ifName;
|
|
||||||
|
cfg = config.swarselsystems.server.wireguard;
|
||||||
|
inherit (cfg) interfaces;
|
||||||
|
ifaceList = builtins.attrValues interfaces;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} settings";
|
swarselmodules.server.${serviceName} =
|
||||||
|
lib.mkEnableOption "enable ${serviceName} settings";
|
||||||
|
|
||||||
swarselsystems.server.wireguard = {
|
swarselsystems.server.wireguard = {
|
||||||
isServer = lib.mkEnableOption "set this as a wireguard server";
|
interfaces = lib.mkOption {
|
||||||
isClient = lib.mkEnableOption "set this as a wireguard client";
|
type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
isServer = lib.mkEnableOption "set this interface as a wireguard server";
|
||||||
|
isClient = lib.mkEnableOption "set this interface as a wireguard client";
|
||||||
|
|
||||||
serverName = lib.mkOption {
|
serverName = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "";
|
default = "";
|
||||||
|
description = "Hostname of the WireGuard server this interface connects to (when isClient = true).";
|
||||||
};
|
};
|
||||||
|
|
||||||
serverNetConfigPrefix = lib.mkOption {
|
serverNetConfigPrefix = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "${if nodes.${serverName}.config.swarselsystems.isCloud then nodes.${serverName}.config.node.name else "home"}";
|
default =
|
||||||
|
let
|
||||||
|
serverCfg = nodes.${config.serverName}.config;
|
||||||
|
in
|
||||||
|
if serverCfg.swarselsystems.isCloud
|
||||||
|
then serverCfg.node.name
|
||||||
|
else "home";
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
|
description = "Prefix used to look up the server network in globals.networks.\"<prefix>-wg\".";
|
||||||
};
|
};
|
||||||
|
|
||||||
ifName = lib.mkOption {
|
ifName = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = wgInterface;
|
default = name;
|
||||||
|
description = "Name of the WireGuard interface.";
|
||||||
};
|
};
|
||||||
|
|
||||||
peers = lib.mkOption {
|
peers = lib.mkOption {
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = "Wireguard peer config names";
|
description = "WireGuard peer config names (clients when this host is server, or additional peers).";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = { };
|
||||||
|
description = "WireGuard interfaces defined on this host.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
|
||||||
config = lib.mkIf config.swarselmodules.server.${serviceName} {
|
config = lib.mkIf config.swarselmodules.server.${serviceName} {
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
wireguard-tools
|
wireguard-tools
|
||||||
];
|
];
|
||||||
|
|
||||||
sops = {
|
sops.secrets =
|
||||||
secrets = {
|
lib.mkMerge (
|
||||||
wireguard-private-key = { inherit sopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; };
|
[
|
||||||
# create this secret only if this is a simple client with only one peer (the server)
|
{
|
||||||
"wireguard-${serverName}-${config.node.name}-presharedKey" = lib.mkIf (isClient && peers == [ ]) { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; };
|
# shared host private key
|
||||||
|
wireguard-private-key = {
|
||||||
|
inherit sopsFile;
|
||||||
|
owner = serviceUser;
|
||||||
|
group = serviceGroup;
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
# create these secrets only if this host has multiple peers
|
] ++ (map
|
||||||
// lib.optionalAttrs (peers != [ ]) (builtins.listToAttrs (map
|
(i:
|
||||||
(clientName: {
|
let
|
||||||
name = "wireguard-${config.node.name}-${clientName}-presharedKey";
|
simpleClientSecrets =
|
||||||
value = { sopsFile = wgSopsFile; owner = serviceUser; group = serviceGroup; mode = "0600"; };
|
lib.optionalAttrs (i.isClient && i.peers == [ ]) {
|
||||||
})
|
"wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey" = {
|
||||||
peers));
|
sopsFile = wgSopsFile;
|
||||||
|
owner = serviceUser;
|
||||||
|
group = serviceGroup;
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
multiPeerSecrets =
|
||||||
|
lib.optionalAttrs (i.peers != [ ]) (builtins.listToAttrs (map
|
||||||
|
(clientName: {
|
||||||
|
name = "wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey";
|
||||||
|
value = {
|
||||||
|
sopsFile = wgSopsFile;
|
||||||
|
owner = serviceUser;
|
||||||
|
group = serviceGroup;
|
||||||
|
mode = "0600";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
i.peers));
|
||||||
|
in
|
||||||
|
simpleClientSecrets // multiPeerSecrets
|
||||||
|
)
|
||||||
|
ifaceList)
|
||||||
|
);
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
firewall.checkReversePath = lib.mkIf isClient "loose";
|
firewall.checkReversePath =
|
||||||
firewall.allowedUDPPorts = [ servicePort ];
|
lib.mkIf (lib.any (i: i.isClient) ifaceList) "loose";
|
||||||
# nat = lib.mkIf (config.swarselsystems.isCloud && isServer) {
|
|
||||||
# enable = true;
|
firewall.allowedUDPPorts =
|
||||||
# enableIPv6 = true;
|
lib.mkIf (lib.any (i: i.isServer) ifaceList) [ servicePort ];
|
||||||
# externalInterface = "enp0s6";
|
|
||||||
# internalInterfaces = [ ifName ];
|
|
||||||
# };
|
|
||||||
# interfaces.${ifName}.mtu = 1280; # the default (1420) is not enough!
|
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.network = {
|
systemd.network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
||||||
networks."50-${ifName}" = {
|
networks = lib.mkMerge (map
|
||||||
|
(i:
|
||||||
|
let
|
||||||
|
inherit (i) ifName;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"50-${ifName}" = {
|
||||||
matchConfig.Name = ifName;
|
matchConfig.Name = ifName;
|
||||||
linkConfig = {
|
linkConfig = {
|
||||||
MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???)
|
MTUBytes = 1408; # TODO: figure out where we lose those 12 bits (8 from pppoe maybe + ???)
|
||||||
};
|
};
|
||||||
|
|
||||||
# networkConfig = lib.mkIf (config.swarselsystems.isCloud && isServer) {
|
|
||||||
# IPv4Forwarding = true;
|
|
||||||
# IPv6Forwarding = true;
|
|
||||||
# };
|
|
||||||
|
|
||||||
address =
|
address =
|
||||||
if isServer then [
|
if i.isServer then [
|
||||||
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv4
|
globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
|
||||||
globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${config.node.name}.cidrv6
|
globals.networks."${config.swarselsystems.server.netConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
|
||||||
] else [
|
] else [
|
||||||
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv4
|
globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv4
|
||||||
globals.networks."${serverNetConfigPrefix}-wg".hosts.${config.node.name}.cidrv6
|
globals.networks."${i.serverNetConfigPrefix}-${ifName}".hosts.${config.node.name}.cidrv6
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
ifaceList);
|
||||||
|
|
||||||
netdevs."50-${ifName}" = {
|
netdevs = lib.mkMerge (map
|
||||||
|
(i:
|
||||||
|
let
|
||||||
|
inherit (i) ifName;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
"50-${ifName}" = {
|
||||||
netdevConfig = {
|
netdevConfig = {
|
||||||
Kind = "wireguard";
|
Kind = "wireguard";
|
||||||
Name = ifName;
|
Name = ifName;
|
||||||
};
|
};
|
||||||
|
|
||||||
wireguardConfig = {
|
wireguardConfig = {
|
||||||
ListenPort = lib.mkIf isServer servicePort;
|
ListenPort = lib.mkIf i.isServer servicePort;
|
||||||
|
|
||||||
# ensure file is readable by `systemd-network` user
|
|
||||||
PrivateKeyFile = config.sops.secrets.wireguard-private-key.path;
|
PrivateKeyFile = config.sops.secrets.wireguard-private-key.path;
|
||||||
|
|
||||||
# To automatically create routes for everything in AllowedIPs,
|
RouteTable = lib.mkIf i.isClient "main";
|
||||||
# add RouteTable=main
|
|
||||||
RouteTable = lib.mkIf isClient "main";
|
|
||||||
|
|
||||||
# FirewallMark marks all packets send and received by wg0
|
|
||||||
# with the number 42, which can be used to define policy rules on these packets.
|
|
||||||
# FirewallMark = 42;
|
|
||||||
};
|
};
|
||||||
wireguardPeers = lib.optionals isClient [
|
|
||||||
|
wireguardPeers =
|
||||||
|
lib.optionals i.isClient [
|
||||||
{
|
{
|
||||||
PublicKey = builtins.readFile "${self}/secrets/public/wg/${serverName}.pub";
|
PublicKey =
|
||||||
PresharedKeyFile = config.sops.secrets."wireguard-${serverName}-${config.node.name}-presharedKey".path;
|
builtins.readFile "${self}/secrets/public/wg/${i.serverName}.pub";
|
||||||
Endpoint = "server.${serverName}.${globals.domains.main}:${toString servicePort}";
|
|
||||||
# Access to the whole network is routed through our entry node.
|
PresharedKeyFile =
|
||||||
|
config.sops.secrets."wireguard-${i.serverName}-${config.node.name}-${i.ifName}-presharedKey".path;
|
||||||
|
|
||||||
|
Endpoint =
|
||||||
|
"server.${i.serverName}.${globals.domains.main}:${toString servicePort}";
|
||||||
|
|
||||||
PersistentKeepalive = 25;
|
PersistentKeepalive = 25;
|
||||||
|
|
||||||
AllowedIPs =
|
AllowedIPs =
|
||||||
let
|
let
|
||||||
wgNetwork = globals.networks."${serverNetConfigPrefix}-wg";
|
wgNetwork = globals.networks."${i.serverNetConfigPrefix}-${i.ifName}";
|
||||||
in
|
in
|
||||||
(lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4)
|
(lib.optional (wgNetwork.cidrv4 != null) wgNetwork.cidrv4)
|
||||||
++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6);
|
++ (lib.optional (wgNetwork.cidrv6 != null) wgNetwork.cidrv6);
|
||||||
}
|
}
|
||||||
] ++ lib.optionals isServer (map
|
]
|
||||||
|
++ lib.optionals i.isServer (map
|
||||||
(clientName: {
|
(clientName: {
|
||||||
PublicKey = builtins.readFile "${self}/secrets/public/wg/${clientName}.pub";
|
PublicKey =
|
||||||
PresharedKeyFile = config.sops.secrets."wireguard-${config.node.name}-${clientName}-presharedKey".path;
|
builtins.readFile "${self}/secrets/public/wg/${clientName}.pub";
|
||||||
# PersistentKeepalive = 25;
|
|
||||||
|
PresharedKeyFile =
|
||||||
|
config.sops.secrets."wireguard-${config.node.name}-${clientName}-${i.ifName}-presharedKey".path;
|
||||||
|
|
||||||
AllowedIPs =
|
AllowedIPs =
|
||||||
let
|
let
|
||||||
clientInWgNetwork = globals.networks."${config.swarselsystems.server.netConfigPrefix}-wg".hosts.${clientName};
|
clientInWgNetwork =
|
||||||
|
globals.networks."${config.swarselsystems.server.netConfigPrefix}-${i.ifName}".hosts.${clientName};
|
||||||
in
|
in
|
||||||
(lib.optional (clientInWgNetwork.ipv4 != null) (lib.net.cidr.make 32 clientInWgNetwork.ipv4))
|
(lib.optional (clientInWgNetwork.ipv4 != null)
|
||||||
++ (lib.optional (clientInWgNetwork.ipv6 != null) (lib.net.cidr.make 128 clientInWgNetwork.ipv6));
|
(lib.net.cidr.make 32 clientInWgNetwork.ipv4))
|
||||||
|
++ (lib.optional (clientInWgNetwork.ipv6 != null)
|
||||||
|
(lib.net.cidr.make 128 clientInWgNetwork.ipv6));
|
||||||
})
|
})
|
||||||
peers);
|
i.peers);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
})
|
||||||
|
ifaceList);
|
||||||
};
|
};
|
||||||
|
|
||||||
# networking = {
|
|
||||||
# wireguard = {
|
|
||||||
# enable = true;
|
|
||||||
# interfaces = {
|
|
||||||
# wg1 = {
|
|
||||||
# privateKeyFile = config.sops.secrets.wireguard-private-key.path;
|
|
||||||
# ips = [ "192.168.178.201/24" ];
|
|
||||||
# peers = [
|
|
||||||
# {
|
|
||||||
# publicKey = "PmeFInoEJcKx+7Kva4dNnjOEnJ8lbudSf1cbdo/tzgw=";
|
|
||||||
# presharedKeyFile = config.sops.secrets.wireguard-home-preshared-key.path;
|
|
||||||
# name = "moonside";
|
|
||||||
# persistentKeepalive = 25;
|
|
||||||
# # endpoint = "${config.repo.secrets.common.ipv4}:51820";
|
|
||||||
# endpoint = "${config.repo.secrets.common.wireguardEndpoint}";
|
|
||||||
# # allowedIPs = [
|
|
||||||
# # "192.168.3.0/24"
|
|
||||||
# # "192.168.1.0/24"
|
|
||||||
# # ];
|
|
||||||
# allowedIPs = [
|
|
||||||
# "192.168.178.0/24"
|
|
||||||
# ];
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@
|
||||||
config.swarselsystems.proxyHost != config.node.name
|
config.swarselsystems.proxyHost != config.node.name
|
||||||
then
|
then
|
||||||
if
|
if
|
||||||
config.swarselsystems.server.wireguard.isClient
|
config.swarselsystems.server.wireguard.interfaces.wgProxy.isClient
|
||||||
then
|
then
|
||||||
globals.networks."${config.swarselsystems.server.wireguard.serverNetConfigPrefix}-wg".hosts.${config.node.name}.ipv4
|
globals.networks."${config.swarselsystems.server.wireguard.interfaces.wgProxy.serverNetConfigPrefix}-wgProxy".hosts.${config.node.name}.ipv4
|
||||||
else
|
else
|
||||||
globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4
|
globals.networks.${config.swarselsystems.server.netConfigName}.hosts.${config.node.name}.ipv4
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
{ self, homeConfig, lib, pkgs, ... }:
|
{ self, homeConfig, lib, pkgs, config, ... }:
|
||||||
let
|
let
|
||||||
mkPackages = names: pkgs: builtins.listToAttrs (map
|
mkPackages = names: pkgs: builtins.listToAttrs (map
|
||||||
(name: {
|
(name: {
|
||||||
inherit name;
|
inherit name;
|
||||||
value = pkgs.callPackage "${self}/pkgs/config/${name}" { inherit self name homeConfig; };
|
value = pkgs.callPackage "${self}/pkgs/config/${name}" { inherit self name homeConfig config; };
|
||||||
})
|
})
|
||||||
names);
|
names);
|
||||||
packageNames = lib.swarselsystems.readNix "pkgs/config";
|
packageNames = lib.swarselsystems.readNix "pkgs/config";
|
||||||
|
|
|
||||||
9
pkgs/config/swarsel-gens/default.nix
Normal file
9
pkgs/config/swarsel-gens/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ name, writeShellApplication, config, ... }:
|
||||||
|
|
||||||
|
writeShellApplication {
|
||||||
|
inherit name;
|
||||||
|
runtimeInputs = [ config.nix.package ];
|
||||||
|
text = ''
|
||||||
|
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
|
||||||
|
'';
|
||||||
|
}
|
||||||
9
pkgs/config/swarsel-switch/default.nix
Normal file
9
pkgs/config/swarsel-switch/default.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{ name, writeShellApplication, config, ... }:
|
||||||
|
|
||||||
|
writeShellApplication {
|
||||||
|
inherit name;
|
||||||
|
runtimeInputs = [ config.nix.package ];
|
||||||
|
text = ''
|
||||||
|
sudo nix-env --switch-generation "$1" -p /nix/var/nix/profiles/system && sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
swarselmodules = {
|
swarselmodules = {
|
||||||
anki = lib.mkDefault true;
|
anki = lib.mkDefault true;
|
||||||
anki-tray = lib.mkDefault true;
|
anki-tray = lib.mkDefault true;
|
||||||
|
attic-store-push = lib.mkDefault true;
|
||||||
atuin = lib.mkDefault true;
|
atuin = lib.mkDefault true;
|
||||||
autotiling = lib.mkDefault true;
|
autotiling = lib.mkDefault true;
|
||||||
batsignal = lib.mkDefault true;
|
batsignal = lib.mkDefault true;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
diskEncryption = lib.mkDefault true;
|
diskEncryption = lib.mkDefault true;
|
||||||
packages = lib.mkDefault true;
|
packages = lib.mkDefault true;
|
||||||
ssh = lib.mkDefault true;
|
ssh = lib.mkDefault true;
|
||||||
nginx = lib.mkDefault true;
|
attic-setup = lib.mkDefault true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
32
secrets/nginx/acme.json
Normal file
32
secrets/nginx/acme.json
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"swarsel.win": {
|
||||||
|
"fulldomain": "ENC[AES256_GCM,data:CVasUSMRn/KWzVRlcYfTO/RL+W5Cz2JpDj0JLAKITXrDZrl+Wsg46X8zv4hX6NLj/wAyvXQ=,iv:N3DL4JPX8vWTbllFWcpNulwtDJ57xpHrAwoUxWhTzxs=,tag:CYWoK9uT121rFXQ5h69CZA==,type:str]",
|
||||||
|
"subdomain": "ENC[AES256_GCM,data:uM457vEJa10IV4SovBDUzLLlW+mPwh1SiWr8thQisFoe6zAk,iv:Tdbd5a20Gv/thkPfsvNiAbI86JjcDs70MAfk4yCZLgs=,tag:MulJiRWPs215x0bc+1jBiA==,type:str]",
|
||||||
|
"username": "ENC[AES256_GCM,data:ePE2BEKL5uaXqzGngW9ArhwP3qwDzwULtfwUfb5Q56VGGURp,iv:/GZRbyXHorcq1PIYlhfOmUVwCg0I/N4ZraEzSrc8qmA=,tag:wM5B1U0BsRsBAJg3qNOXpA==,type:str]",
|
||||||
|
"password": "ENC[AES256_GCM,data:RGzdi8IMqm+rtiuU4RtWGQ4N/7FYBbp5Pir8/k2V1QEdM8z7SIn0FQ==,iv:ThFbY9eZuEZoyzcWV5DwtSi8ugNwM49JfRof560Qx/Y=,tag:sgMaLrPB8WgpXWPzaCwOBQ==,type:str]",
|
||||||
|
"server_url": "ENC[AES256_GCM,data:zJdXoO7ED7qeskYJ9Wu0Rdprbvj/uP+Z,iv:ce+QXocqCjNKCsZRyVt6koUyc2lsTwPNMcfQyqbktN0=,tag:bQSE4/6va+V0TORWANLdUA==,type:str]"
|
||||||
|
},
|
||||||
|
"sops": {
|
||||||
|
"age": [
|
||||||
|
{
|
||||||
|
"recipient": "age1g7atkxdlt4ymeh7v7aa2yzr2hq2qkvzrc4r49ugttm3n582ymv9qrmpk8d",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBWmFOUGZrbkNlQ2ppbnFw\nTVd3RVYrK1RocjU3Z0pPOUNpc05YZ0FKK2hJClAvdkZ0aFRtaE5PRWFNbWdWSjN3\nbWc1WUpuTTVDTlNldTh0ejBGakZvbDgKLS0tIHJaRmwwSEtqQXprcFZ3TlllWmJa\nczN6eE8wWUppc3o1VTRpcjF0VUM1azQKdWhbP34mx6yR6TXUMpP/npA9TjAayjqz\nHC7ztK5/zu4ML7BRCsoLNLDDVtMsmhEVKO8VV9sbMvusSq0WNu0I7g==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"recipient": "age1cmzh82q8k59yzceuuy2epmqu22g7m84gqvq056mhgehwpmvjadfsc3glc8",
|
||||||
|
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxVUM5eTMrZ3lCeDgxVHlj\naWx4QUZ5c0NGV2xEaXliNHFyVktkTnBYR0d3CnRMcUgyUU1hNzhLcWhaYzJCMndR\nQWJyNEZJV2xNVVBSc2xnbzRqdEx1eXMKLS0tIDJhTGhVYkxJcGZ6N3dHZmV3QlBo\nNzBORDJXb1pRbVNiWHZiVjBKQjNwWDAK1z/XA6gRor2fNX70UooBqHjCFfIIP34j\n+vHx10dtoue5tSPgM3cA8QZzqM6Ht+U282JFMztrlDtiz/j/JofTNg==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastmodified": "2025-12-04T19:04:02Z",
|
||||||
|
"mac": "ENC[AES256_GCM,data:nWV/knCo/MeWTBrfq1VlV6SPEQ2i2P+le82S2So0BIxPfz8tqan0MdaIaKLFlapsT9VRJOv8ZCCXSLWeGcbEvfmEz4MP1E4iHcU/4YaO+n895D1JrjeyP1cgGisnXqe01xMXCsDY178sqxHcnDDlXp9foCem+mGjIlKGPYGu5Oo=,iv:qbavbW3MF4fx+E3aybBYaz/T/Hb63ggWml4Oe9WFz+I=,tag:05vBbBGDGRNaXJWoZn1bVw==,type:str]",
|
||||||
|
"pgp": [
|
||||||
|
{
|
||||||
|
"created_at": "2025-12-22T14:07:12Z",
|
||||||
|
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMAwDh3VI7VctTAQ//XZNxhn6vCEDo6SAtlIcA5OxNuj3326ITbjjv+XwiTHk/\n28cErtXOF+4bnjIXLwXGbbewWgvrnK0Lx5nBqpidMrhANHVEWDp3iBrW79QPdRl9\ntIcofQUK+6Dwh+XqJK4eorEAeAKlu6l5y3pc19L4j7BiDOxcXBYqTx4ScnZhFFoc\nRVC6ngRjck+2e6bL/+lopntHML41yrXpAHMBlobTbzYP8cnfMKroUZzLoNareVIS\nNlcE7oaCwAvCXYBbQN5qQCIFbLBFB+vD4ArOrL/zNxWVjnEeM4RhBdIjd0bdq1FQ\nLBsO1crEniz4Lgp5N4cWOzuOCz5fHlLJEKtNIIFt8rcocBEdyQf1OmZ2VrY57nN+\nSeCYGN+fPA87UoH+iZcmLNjDvMy+MHNIiGCEuY9jWLzgcDDvtFwtQdl2CpI8a/Ax\nKG9RgMFyjLtPCgNzDkn6LrvHKtnFkcsx22f8PHB4RZIgP43loH//xieOVnA9vo/k\nV3pRHZuZkTp3qmAED3KhbjE7aKP3bjUkJdrTATsal5YyRd76pjPvtXkX6MchgTgh\n6emt6DssvWJy5vhgitM0Ucq1IeeaLwIDTXqP5GShcQrWJ2P5ilzLGp2OKYzOqSBf\n//LfA3EHq4aFaTGuOVxjf/VS1vEeIAMaAo4eo86unIIhcQ6OBVAKzKfrSgzV9iiF\nAgwDC9FRLmchgYQBEACFwFYn12YCzYIwpSfJ7Apo5nEiLYbcD1wXR7bx7MFjJFxc\ncrS6yB/44y6a+OJfTLEVpDTPahKiOFAlmMAb8B05bDd/jqairwJPS+Sw2t/Tb6Ry\nToHi8ucg0+P8b0j+VeXoE0DlnuSMKbKQGvIq9fd8G6FymHppA4TpuKFl0QPUAbX7\nGLQbApk7gRoZK1XTQ/HKjyXdhfRogo8/07oRt6iO3nxC5NkLS/uxk/0ODqiFTGVg\nESkGQK3YQcr8hhhM467S49nzh+AQODgCTm7jSFO8kJwDP6eb5vF63qrIBZNUGc6j\nIoNHzQxqDoaFUd2GZcKg2Zsyizb91qYEMZdHUh51h1XH+jhg8G+L7I+hnBbzIj/o\naZfXALcmYNiI630SsiqA4iSufWy1bONnP0kHPSxVBqilLXpmfzIuNUwrZSQB+ZbR\nkIIA5lRqu1jWIcG/3CGQQMDfjqxus4Wt8bvGfOrbQk2qNs+l3uPb0+OBDNKQfVHD\nenXkTGrKIHt4YqnDc3ziWNAULwvRPviPQZPkJwPCDHdfA2bcQqLJOIYiBF1TdN9o\nv2eMQoTalEXfHOI5ndULjlyy5DaW2ZBKAgtH/WXg/O7ey5Q9e9QcnmwbOezEWx6x\nNNY3eoQs5LYxoWO7cEUv2MiEqY7ZWkrwmwcWzRV/7UmspvPHKULQV/fiNWb1yNJc\nATKv+sla0n0DzD+7BSiFcYC0ZvGAErYAwNIYhlgMEN7okuCscB+tz1d0yLhNt8DK\nZAn0NkIVnTn6esHqhp233ZmCrCmUezccMMINs8xQbqJR8bkns5hTDYLY48s=\n=v2/q\n-----END PGP MESSAGE-----",
|
||||||
|
"fp": "4BE7925262289B476DBBC17B76FD3810215AE097"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"unencrypted_suffix": "_unencrypted",
|
||||||
|
"version": "3.11.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
secrets/public/wg/hintbooth.pub
Normal file
1
secrets/public/wg/hintbooth.pub
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
M5vKsS+gw13pS7TTMktxBXJRooIMKiTXjZ6NJgQDAEY=
|
||||||
|
|
@ -31,6 +31,8 @@ github-nixpkgs-review-token: ENC[AES256_GCM,data:/4ssZAEwEc9fZeR69GCvLMm4eRv4uab
|
||||||
#ENC[AES256_GCM,data:PI5MX6PgK1y0lqyoYA0=,iv:25UAvFaANHFD04GRafGlCzOc5h+15YPtSES2z2tmpXw=,tag:+XLwQ01+AtGWjtsSQhQ1AQ==,type:comment]
|
#ENC[AES256_GCM,data:PI5MX6PgK1y0lqyoYA0=,iv:25UAvFaANHFD04GRafGlCzOc5h+15YPtSES2z2tmpXw=,tag:+XLwQ01+AtGWjtsSQhQ1AQ==,type:comment]
|
||||||
anki-user: ENC[AES256_GCM,data:WoGaNDAHFw==,iv:ZSjHfKMIjlgOuvGl7hVxJc1fE80nfxxXYLgsKangBCs=,tag:UP8ZI7gzOrJJjNDHovIkyg==,type:str]
|
anki-user: ENC[AES256_GCM,data:WoGaNDAHFw==,iv:ZSjHfKMIjlgOuvGl7hVxJc1fE80nfxxXYLgsKangBCs=,tag:UP8ZI7gzOrJJjNDHovIkyg==,type:str]
|
||||||
anki-pw: ENC[AES256_GCM,data:z2SCsSvZIqN2/2VK1EdmcAnl42x5A15PAiK932k3n50Vj1jczGRoSw==,iv:keQCutY4vizVzu5YzPBJLgDLveYDb2VGeEnYmO7CeQw=,tag:KGplFfC5xktNAOTbIlt+Tg==,type:str]
|
anki-pw: ENC[AES256_GCM,data:z2SCsSvZIqN2/2VK1EdmcAnl42x5A15PAiK932k3n50Vj1jczGRoSw==,iv:keQCutY4vizVzu5YzPBJLgDLveYDb2VGeEnYmO7CeQw=,tag:KGplFfC5xktNAOTbIlt+Tg==,type:str]
|
||||||
|
#ENC[AES256_GCM,data:veUC1sj6BSqHBA==,iv:L36lv9aQ38/WEaIccQDgOw2PB9U9k/t8x00wIw2Y858=,tag:3s2LBCwGzYpUk8WBj70UGQ==,type:comment]
|
||||||
|
attic-cache-key: ENC[AES256_GCM,data:2Xw8YX6wiQg2yb2pbZ/UowmzUdhtb2iRTVZZD2ypGaiwhI3mteG3qUgQm1oCz0bp+5jip6+kVzt576qVbUGim/m+dUZYU6mqm64/78bfuTvd/UBlJnmjNtWE2ILjnP+M4EodzbYlBlxwGhFS28wrVOHo77rzbcrPJEwZiqIzSgGIWKdNzzo5AXL2b1lKAngXO6Bi5Jc9W4lkTVFJ/Ixh6aOoHpq9TzsHHx2Aak22969pnxmFFpXKof4eiNGnoGBZDAr8pC7oSwVqDYbZwxH1ulRq863KVQkve+HBR2JJLAQjYHHUJJGhJG9jWYT03WjBNHwIDMTTvC9Fiw9Cr0TG0B8Bxwm3dhgLirjUyLOiST2CbDxxld1M8DJFkBwrih6hMJXmJw8Dlqy/D+3EZXT947BI8ythYjuL3jIHHQhUjfEf+sLdqPSngHolAAKqKE84Xv2FDn2wXGwe8UY3NMmIeaWYZsyDu77KnQR2R+6TuJTOw6vOdDoUJ55YRPdb9UR186b+TiSrP0SZOujoSYGs9dattEvN3XKlm3cQztB9UygmdEk/stDZ/CJIRUNXsu46o1nR5FWPkgoW91Fzxs00QgQMpYlnXM2CWknYMSHL45t0BYA7yuFwq9MYNUK/vrdCr3mtHxA6R28HajDUWoZA6uS+DF/i1nF79sYfam7SdKNCqu2r/1CGLblHQwKT27HmrTCXdjeLqe+Yv7sJzlEbV+sKD+ccW8jI4NZRjCbVJVKydK23YWj94NEt/M2rtxzV30XKw8GClqsdEF+v4nu48oB894RPZCy9qQjaFHnqYpiqSa0oXluiQQmRfA0jtQLRTXN5ri7U/GtfH1za179MFWwMorRMK6qdTt3pi8Fie4UgzGyGq6CugN8HxeMNl70pPVIKjGNO8Npezk6T3YDUpB3/OGY56jhSYxIEadBvW9CqDS7al7zEKgD1wx1gzT2mQh60H2B/InWg9p96qOqVEQxOFDklxlcnygLu3z7Y0mAds/HXOJJnJbagjfxVi+qROOtVrR5y/kySR0pM9Syk8GvqdtRct7qorONAV/yonarEgz+eEFj10kderSsPdz1sgiYe93VLmPp07cdVsUsaDtLW8gXafc3aWOZ8JIkSUhYDbR49pf2bTeoMDoyi9d6pgLr+cJGQbJC/1LmsAIqOQ7WPiTeAZG2lStNf3bwClpUuL0t78UabZyNzJJN5TFDZqGkwXlaJmQ==,iv:6sa44WnyrXW3KQHdGIKuiGWwqp3qtQu4Q9RSXA45PYs=,tag:MbtS4Xx5K8O3mFAlriuuIA==,type:str]
|
||||||
#ENC[AES256_GCM,data:KCqwghIJ8tlGFxMt94svo6285cA1YRbYoeivx6A=,iv:qlZCGrCn5fU1xPQF9wfOMarU6Z7oa3mLtd1LzVzMbuI=,tag:Qq5lBtUsd3lQMx6ffk+kzQ==,type:comment]
|
#ENC[AES256_GCM,data:KCqwghIJ8tlGFxMt94svo6285cA1YRbYoeivx6A=,iv:qlZCGrCn5fU1xPQF9wfOMarU6Z7oa3mLtd1LzVzMbuI=,tag:Qq5lBtUsd3lQMx6ffk+kzQ==,type:comment]
|
||||||
builder-key: ENC[AES256_GCM,data:OOoA7oRIFJwS48qs42WmIXU4vLTQLRi6Nzb6IUNXAwnj7E9Q/uzOnmJ6ZihqUr3uP3/kqICdZqkB5Lf+lwUqrPmGi8PH8c4uq3L9ZVQyRTKRWvS5biYRMd/NI1ACRevxFJygKZ/q1dH8Cf++m26Jo9On24liepQbogwIctmN8bLXuXrUYVYMcLyGb2W2uznj5Jtwyji87S1xc/TTh/IOFexPY7yAnlwSZ7IoPTOj8o/00Hny8KIwRVf0uLBmtarIS8u4kfjkFUN38X9xmzQqhITaZNRmwerb3JDbD3SYapfsyeLzkzVgsDooOniCRehX1pg7KJu/qHnFM8t7e4qZe9u4PZP08aVAS3tqChuG/Nm4fv3vnF0SwctGQsar2HDmby1IXAw3fSNCW/v/l8VY4IaRX9s7e6c95gd5NX7/CJ2CJUDb4s3e7U0SkftOUz/B1zX47xBHSibZ2Js24N6Tvq/5S4OJFwryvt57Ed+cY+zSROlJwjrTgaGcuwH3MHLfHJlA,iv:2RpiHF4b7+520UJcHVobfJs165EjgxaTATSyOx7HJik=,tag:tGddPi0YeO3E0kHl+E7uGA==,type:str]
|
builder-key: ENC[AES256_GCM,data:OOoA7oRIFJwS48qs42WmIXU4vLTQLRi6Nzb6IUNXAwnj7E9Q/uzOnmJ6ZihqUr3uP3/kqICdZqkB5Lf+lwUqrPmGi8PH8c4uq3L9ZVQyRTKRWvS5biYRMd/NI1ACRevxFJygKZ/q1dH8Cf++m26Jo9On24liepQbogwIctmN8bLXuXrUYVYMcLyGb2W2uznj5Jtwyji87S1xc/TTh/IOFexPY7yAnlwSZ7IoPTOj8o/00Hny8KIwRVf0uLBmtarIS8u4kfjkFUN38X9xmzQqhITaZNRmwerb3JDbD3SYapfsyeLzkzVgsDooOniCRehX1pg7KJu/qHnFM8t7e4qZe9u4PZP08aVAS3tqChuG/Nm4fv3vnF0SwctGQsar2HDmby1IXAw3fSNCW/v/l8VY4IaRX9s7e6c95gd5NX7/CJ2CJUDb4s3e7U0SkftOUz/B1zX47xBHSibZ2Js24N6Tvq/5S4OJFwryvt57Ed+cY+zSROlJwjrTgaGcuwH3MHLfHJlA,iv:2RpiHF4b7+520UJcHVobfJs165EjgxaTATSyOx7HJik=,tag:tGddPi0YeO3E0kHl+E7uGA==,type:str]
|
||||||
nixbuild-net-key: ENC[AES256_GCM,data:aAa6iyZsjH1sAb6ucSPJb2R+QiG2bTj46Csnjg58+2ngYdfuim6SzWEid8IHJV1+M0s/hVTbZWiPsU2KQ+JCdJ84as520avxs6I0URvNx+VmFi6DNGbBJJJJKdTXIKvtmLHqHobs9XtIHahQKoyUpXiSY88DcwAt4e2mUTa6olgrDv66+/fEGeexP4S7AVB0wYeegyMgWODRrA9gS/YLMxMdqk/VHuwIQpWkhxX+AY8mXkx7LalxrbtV/24qdNtr2GittrvYBAkYGWAVZYotBVKjaWVUVzqF3BU+wmg0c56OG5qtt9eD1THAqNauN3iIfUnV301S+TvVtYjpy7gOj3WzntO/kh4kD+7FnfleLXIVSLgBRc0vHhd+7HKKtVRnAINyPkyjaBpnnBa4cksBvHtI0uis0Pi+4JtObD3m+5dywTeL+HDQfHwu+7CgjvXHQYKvEaJ8z6alyXL88Q6uT2Ikaoyrkpi7OJsuIBiNbs5YzRReSfLVyepm8SAtA8UIwnMiTtgFvwGUEW19ne96,iv:2HN9X9CA1liWuY+LYqTCX6Zy3xARMS/TOL61r2UKsE8=,tag:XcPBwYrQjqhexI7u+0zXQw==,type:str]
|
nixbuild-net-key: ENC[AES256_GCM,data:aAa6iyZsjH1sAb6ucSPJb2R+QiG2bTj46Csnjg58+2ngYdfuim6SzWEid8IHJV1+M0s/hVTbZWiPsU2KQ+JCdJ84as520avxs6I0URvNx+VmFi6DNGbBJJJJKdTXIKvtmLHqHobs9XtIHahQKoyUpXiSY88DcwAt4e2mUTa6olgrDv66+/fEGeexP4S7AVB0wYeegyMgWODRrA9gS/YLMxMdqk/VHuwIQpWkhxX+AY8mXkx7LalxrbtV/24qdNtr2GittrvYBAkYGWAVZYotBVKjaWVUVzqF3BU+wmg0c56OG5qtt9eD1THAqNauN3iIfUnV301S+TvVtYjpy7gOj3WzntO/kh4kD+7FnfleLXIVSLgBRc0vHhd+7HKKtVRnAINyPkyjaBpnnBa4cksBvHtI0uis0Pi+4JtObD3m+5dywTeL+HDQfHwu+7CgjvXHQYKvEaJ8z6alyXL88Q6uT2Ikaoyrkpi7OJsuIBiNbs5YzRReSfLVyepm8SAtA8UIwnMiTtgFvwGUEW19ne96,iv:2HN9X9CA1liWuY+LYqTCX6Zy3xARMS/TOL61r2UKsE8=,tag:XcPBwYrQjqhexI7u+0zXQw==,type:str]
|
||||||
|
|
@ -144,8 +146,8 @@ sops:
|
||||||
L0gzWDFia2Jha0lDaGZaSWEwOWFmb1EKJqqjxODIgVeiMKtV6361sjYQa559pKCG
|
L0gzWDFia2Jha0lDaGZaSWEwOWFmb1EKJqqjxODIgVeiMKtV6361sjYQa559pKCG
|
||||||
1pKczlzXxL1FliBQoZZGq55NR4azWYEl/yV5tee1dtUohJW0pAyScA==
|
1pKczlzXxL1FliBQoZZGq55NR4azWYEl/yV5tee1dtUohJW0pAyScA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-12-01T19:57:43Z"
|
lastmodified: "2025-12-23T01:11:36Z"
|
||||||
mac: ENC[AES256_GCM,data:2CLFlduO1fsxtvF1fbH18kadQuawMwIYEjsJBvZ65tecIdjT5efPD07+czmysKWBh6FQuVPL8a3uVlqT2WUW57AjQZtxloCMAFS9m2S//I6I8GsLVccGnmudiHUdXFnt+gI1gtb6ukZMEps4m/LSqUHGSptVwqrIN2gBM6Yy9Mo=,iv:S/crBYhr2HTzMYn83bK2YYO7kwfDspF0gvkoiuI9J7o=,tag:+sO+jFMFGZSsCb7PGnlUmw==,type:str]
|
mac: ENC[AES256_GCM,data:e0WoFBQSR5q3GOQ+GMJGBd4lNBAMqlnVjtUq3snxrdvcytb9YvKnoYQH+GjbdGIiqrND8pOVnZt34AjkR8YfpWe+VrkP3Vj/3l+1GjF1XIHbzBNKOQHdYPSVsH2NZwftcAdphbStf3GTlb+b+cpTn4a9Y4pTNGVoOaOA1tBr8bM=,iv:sPXktitTNMkBhHr6E/QRZCVKrgyED9/o9hiivbObACI=,tag:tTNr4UEf92UrtI0Jvi5o3g==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2025-12-15T21:53:36Z"
|
- created_at: "2025-12-15T21:53:36Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,7 +1,8 @@
|
||||||
wireguard-twothreetunnel-winters-presharedKey: ENC[AES256_GCM,data:v+RyEcJh7dSBuOUgJFG6f3C8CYchEDy1mk2vUXlJbeeqAFcU3d9/M7QbHz0=,iv:GGJ61LsTq1lKcg0xjO3Co1PVqGW56Tgb0dWtT+7suz8=,tag:WCAsVbBsOeo7xmqRwdCinA==,type:str]
|
wireguard-twothreetunnel-winters-wgProxy-presharedKey: ENC[AES256_GCM,data:FZWARdSb8o3KpgJikYIC7hYLZ+WUaulZoisE4Ifdpsr8tBazY9bVlf6D9p4=,iv:QSUUWFR6uUoX62l0kMiVKkmlI0lEXuDEV7PSfBLJymM=,tag:eupex55cEm7lDKHFbJOkmg==,type:str]
|
||||||
wireguard-twothreetunnel-moonside-presharedKey: ENC[AES256_GCM,data:vkUcgip1lrYEYwcbLF5WSPUK8m7ouuyDtVykcl4Lah21asBhCmDtqqNzvvw=,iv:1zVhRsxLQvBpHcSjcswwSCotelZk7SWI9NkXdrAS21Y=,tag:0DvNJMaiYl93flbjNQBVwg==,type:str]
|
wireguard-twothreetunnel-moonside-wgProxy-presharedKey: ENC[AES256_GCM,data:Y/EwbaVbGljiz9XZmr7+/udBfeaY+CLMfnKzekXP50Hu8ek8aA1/SKs2qd0=,iv:BijEDkfpRWox8CPwCoZLA42WihYIqHJJgSgOfsOGcG4=,tag:8+qEnqTsqyNdD4oVPiuQuQ==,type:str]
|
||||||
wireguard-twothreetunnel-eagleland-presharedKey: ENC[AES256_GCM,data:5JMTgXPcRzcr3GfGinAeLvldweArGyB8gyqRNtxlKa1RPY9pPa7s8Pxhdng=,iv:Mk6fLKpf8XbSGEU8b/j+ZZcQxcxhKGHRPSmk5Q9lrXQ=,tag:GACQf8x46LVQMwrlp6+NSA==,type:str]
|
wireguard-twothreetunnel-eagleland-wgProxy-presharedKey: ENC[AES256_GCM,data:dF8VPApd6iYKIZjBXB2rjIXIxyy2+U76TdyFuyUW0zSbtjzqn1ZKrhX4w/M=,iv:GqOHsS97di9sHqjndlq0EdWLcJ1EMLmDOnFJlBgTvYU=,tag:PdxEYlg3lPShUJYlANLjhg==,type:str]
|
||||||
wireguard-twothreetunnel-belchsfactory-presharedKey: ENC[AES256_GCM,data:MKla1VJiFzpWxrxXA+FUU10KQmrO926wKdBCM0tQDvkQWrR1FpvbbeBfdzM=,iv:5aIhbhiAsfIXUojuLwRsuhZAPvGkORZTOo+0Rc5/bpY=,tag:nG++1kDULmAMfCx0a8P40Q==,type:str]
|
wireguard-twothreetunnel-belchsfactory-wgProxy-presharedKey: ENC[AES256_GCM,data:NAbVE7ysGDD6TT0RxdL6bTNloac4RBU1JWeTFqYo9PO6ZU2f/yq6aboi2AA=,iv:Ky4UvgRDEG1UgDmi+m5mHWHO+yUGzphQPYIuyAXDkhw=,tag:WP+/8q8jfitNC/rXN5Mp2A==,type:str]
|
||||||
|
wireguard-hintbooth-winters-wgHome-presharedKey: ENC[AES256_GCM,data:57KGUxn1BibZ+9H9mXg9EYmcy1JBX+M79ACL3Qt0XEMl0dFlk9Wq6cr3JTg=,iv:9QHdykNlUU1H0uco21zA8leQH73PAeL+xTVi6V9zx7U=,tag:6mfSCddnVGMBEAqCHDIIrw==,type:str]
|
||||||
sops:
|
sops:
|
||||||
age:
|
age:
|
||||||
- recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza
|
- recipient: age1s0vssf9fey2l456hucppzx2x58xep279nsdcglvkqm30sr9ht37s8rvpza
|
||||||
|
|
@ -112,8 +113,8 @@ sops:
|
||||||
THZaSXhMNldUbHpBMVZQWXYwaVVQYWsKpUbG+lC37W6bzOuu9MaUmEZ5T1b5EC9k
|
THZaSXhMNldUbHpBMVZQWXYwaVVQYWsKpUbG+lC37W6bzOuu9MaUmEZ5T1b5EC9k
|
||||||
VIY9XUoA7h0Z6G5Jrx/lrf6qsghMqd59gPA1qh8KlCJBAUJPHzQKVg==
|
VIY9XUoA7h0Z6G5Jrx/lrf6qsghMqd59gPA1qh8KlCJBAUJPHzQKVg==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-12-03T15:54:14Z"
|
lastmodified: "2025-12-22T09:11:50Z"
|
||||||
mac: ENC[AES256_GCM,data:yPPp6WQvcMB6mV/V62Y0Ki8Fq2trV3HKTykP5HD7J7ZgUiFNmLPbAApMeefe7Bb8pF7ETrkjRhET7/pXJX7anaOd6Y6pCyF75/xQDzwJ0Ac3FSPgeoOwlA/W+OrRMm9Hla9Q5gNPzgYirIHXoO+aScLcTQp46tiQv8B0Ol0ZSoI=,iv:eIT/EcVpWk79eerrxqy7AqtqNtpJi5sOIe0wmHRjYfI=,tag:4KPyZE9s62fCisjgihH4Jg==,type:str]
|
mac: ENC[AES256_GCM,data:D6qKXhSuYGPm9K7Al/la3O++DmOTQN5++96k44IIvgSR5Q3kTkMYxPsf3PWNyjMm09+9aRauuHPHj098+W1rXaq43Iqr24JAuaZNwLyxtqkaibv/Zhx1RgEWGXyOHDtlfIPoULNKVZ0ls2mtk40oQHsfhnRyS42m+HMQnL+tCF4=,iv:uzKbpZu9P05KbaXnBUxN4rA9nYOXpeK+E/scWoFxpcs=,tag:PuMdBx3JOT1EfFkOPV0G2g==,type:str]
|
||||||
pgp:
|
pgp:
|
||||||
- created_at: "2025-12-15T21:53:40Z"
|
- created_at: "2025-12-15T21:53:40Z"
|
||||||
enc: |-
|
enc: |-
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue