97 Commits

Author SHA1 Message Date
Shelvacu
a0f11550c5 stuff 2024-07-03 17:51:25 -07:00
Shelvacu
80b2ff8951 stuff 2024-07-03 17:47:37 -07:00
Shelvacu
d7b37b0353 stuff 2024-07-03 17:42:04 -07:00
Shelvacu
ab5168632e stuff 2024-07-03 17:39:55 -07:00
Shelvacu
569043b6ca stuff 2024-07-03 17:36:30 -07:00
Shelvacu
620fec48ea give up and update everything to 24.05 2024-07-03 17:35:22 -07:00
Shelvacu
3d734769cd stuff 2024-07-03 17:32:34 -07:00
Shelvacu
14fce1d271 stuff 2024-07-03 17:30:11 -07:00
Shelvacu
d09117418f stuff 2024-07-03 17:29:05 -07:00
Shelvacu
0c4c590dc3 stuff 2024-07-03 17:28:17 -07:00
Shelvacu
06d40673dd stuff 2024-07-03 17:23:48 -07:00
Shelvacu
63e44f4766 stuff 2024-07-03 17:19:03 -07:00
Shelvacu
4b54a38998 stuff 2024-07-03 16:54:59 -07:00
Shelvacu
e9c0ba445c stuff 2024-07-03 16:51:57 -07:00
Shelvacu
13564a3655 stuff 2024-07-03 16:50:35 -07:00
Shelvacu
c30b275bb7 stuff 2024-07-03 16:48:37 -07:00
Shelvacu
f809262290 stuff 2024-07-03 16:41:37 -07:00
Shelvacu
789dc5397d stuff 2024-07-03 16:39:50 -07:00
Shelvacu
5464a052ed Merge branch 'liam-relay' of git.uninsane.org:shelvacu/nix-stuff into liam-relay 2024-07-03 16:19:35 -07:00
Shelvacu
7d0c463de1 stuff 2024-07-03 16:17:11 -07:00
Shelvacu
ce37f30c39 stuff 2024-07-03 16:02:57 -07:00
Shelvacu
52a54f1b50 stuff 2024-07-03 15:52:46 -07:00
Shelvacu
a5585d8bb7 stuff 2024-07-01 21:46:35 -07:00
Shelvacu
4f31ae0727 stuff 2024-07-01 21:45:34 -07:00
Shelvacu
08a778a4d5 stuff 2024-07-01 21:43:31 -07:00
Shelvacu
26194a2994 stuff 2024-07-01 21:39:14 -07:00
Shelvacu
7055fe0678 stuff 2024-07-01 21:34:31 -07:00
Shelvacu
a0cd2fb6a2 stuff 2024-07-01 21:34:13 -07:00
Shelvacu
cba177bc03 stuff 2024-07-01 21:31:52 -07:00
Shelvacu
18f1c074de stuff 2024-07-01 21:20:22 -07:00
Shelvacu
c08442e624 stuff 2024-07-01 21:18:53 -07:00
Shelvacu
540531634b stuff 2024-07-01 21:14:16 -07:00
Shelvacu
e39fe28776 stuff 2024-07-01 21:13:33 -07:00
Shelvacu
5bbf66e323 stuff 2024-07-01 21:12:13 -07:00
Shelvacu
992c0301e3 stuff 2024-07-01 21:07:04 -07:00
Shelvacu
603cb25f95 stuff 2024-07-01 21:04:52 -07:00
Shelvacu
be2071785d stuff 2024-07-01 21:01:10 -07:00
Shelvacu
2977a455db stuff 2024-07-01 20:59:46 -07:00
Shelvacu
b3d3ff1c96 stuff 2024-07-01 20:50:37 -07:00
Shelvacu
9a79e42184 stuff 2024-07-01 20:48:08 -07:00
Shelvacu
4fbbbaad24 stuff 2024-07-01 20:41:47 -07:00
Shelvacu
f363261a26 stuff 2024-07-01 20:40:10 -07:00
Shelvacu
9b62f51b4e stuff 2024-07-01 20:36:49 -07:00
Shelvacu
52d81bc607 stuff 2024-07-01 20:34:50 -07:00
Shelvacu
4624dbea90 stuff 2024-07-01 20:33:10 -07:00
Shelvacu
df117c4eed stuff 2024-07-01 20:30:38 -07:00
Shelvacu
35edf8667b stuff 2024-07-01 20:28:47 -07:00
Shelvacu
7d773121c4 stuff 2024-07-01 20:28:32 -07:00
Shelvacu
b544246cf0 stuff 2024-07-01 19:43:34 -07:00
Shelvacu
a39ee64db6 stuff 2024-07-01 19:42:57 -07:00
Shelvacu
e54d387104 stuff 2024-07-01 19:42:14 -07:00
Shelvacu
56dee4d47c stuff 2024-07-01 19:41:15 -07:00
Shelvacu
044359ac25 this is my first official try 2024-07-01 19:39:02 -07:00
Shelvacu
3f5200b574 wip 2024-07-01 16:43:20 -07:00
Shelvacu
702d48e825 stuff 2024-07-01 16:38:01 -07:00
Shelvacu
6d6ab0baf4 wip 2024-07-01 16:36:59 -07:00
Shelvacu
e304d4d20b stuff 2024-06-29 15:47:06 -07:00
Shelvacu
95d8f3b836 stuff 2024-06-29 15:45:51 -07:00
Shelvacu
aadbf8e874 stuff 2024-06-29 15:43:54 -07:00
Shelvacu
9d9ee9b083 stuff 2024-06-29 15:41:11 -07:00
Shelvacu
b918fff3dd stuff 2024-06-29 14:47:17 -07:00
Shelvacu
0e15d716f0 stuff 2024-06-29 14:33:52 -07:00
Shelvacu
b45f539fb1 stuff 2024-06-29 14:33:24 -07:00
Shelvacu
0b63217f7b stuff 2024-06-29 14:06:54 -07:00
Shelvacu
73b465bd30 stuff 2024-06-29 14:06:44 -07:00
Shelvacu
55338e81ac stuff 2024-06-29 14:02:56 -07:00
Shelvacu
6e005ff10f stuff 2024-06-29 13:35:19 -07:00
Shelvacu
2f5cc60b00 stuff 2024-06-29 13:28:18 -07:00
Shelvacu
a6f8543ac9 stuff 2024-06-29 13:22:58 -07:00
Shelvacu
d7cff14bae stuff 2024-06-29 13:05:36 -07:00
Shelvacu
9049153ff4 stuff 2024-06-29 13:04:17 -07:00
shelvacu
2434e6693f stuff 2024-06-28 16:26:14 -07:00
shelvacu
77e3232ad7 stuff 2024-06-28 16:19:28 -07:00
shelvacu
782aea9f1a stuff 2024-06-28 16:18:54 -07:00
shelvacu
64c6bcbe7a stuff 2024-06-28 16:18:38 -07:00
shelvacu
4d4a6c13cc stuff 2024-06-28 16:16:05 -07:00
shelvacu
217fba6035 stuff 2024-06-28 16:07:34 -07:00
shelvacu
e7a60417a2 stuff 2024-06-28 16:07:16 -07:00
shelvacu
e3196b48ca stuff 2024-06-28 15:50:36 -07:00
shelvacu
d69fffef05 add mar to passdb 2024-06-28 15:47:06 -07:00
Shelvacu
eff8c52c91 *actually* re-encrypt 2024-06-28 15:42:31 -07:00
Shelvacu
378d98b277 reencrypt secrets with new keys 2024-06-28 15:34:24 -07:00
shelvacu
3773e5abf5 stuff 2024-06-28 15:27:50 -07:00
shelvacu
31a661f9b9 stuff 2024-06-28 15:15:16 -07:00
shelvacu
862ecfd4b6 stuff 2024-06-28 15:11:37 -07:00
Shelvacu
89373871ac stuff 2024-06-27 13:48:46 -07:00
Shelvacu
452120fa68 stuff 2024-06-27 12:31:52 -07:00
Shelvacu
7c6325a22a stuff 2024-06-27 12:30:22 -07:00
Shelvacu
afbd1ee645 stuff 2024-06-27 12:29:13 -07:00
Shelvacu
4584200632 stuff 2024-06-27 12:28:49 -07:00
Shelvacu
90fc0c3f5b stuff 2024-06-27 12:27:25 -07:00
Shelvacu
b69d831569 stuff 2024-06-27 12:26:24 -07:00
Shelvacu
b288aa824d stuff 2024-06-26 20:02:05 -07:00
Shelvacu
b4a5e9515d stuff 2024-06-26 19:58:00 -07:00
Shelvacu
ea3e3e3ef3 stuff 2024-06-24 17:55:30 -07:00
Shelvacu
3a774033ee stuff 2024-06-23 20:41:06 -07:00
Shelvacu
71a27e50f4 stuff 2024-06-23 01:59:55 -07:00
19 changed files with 552 additions and 151 deletions

View File

@@ -1,8 +1,15 @@
shel_keys: &shel_keys shel_keys: &shel_keys
- &pixel-termux age1y4zp4ddq6xyffd8fgmn2jkl78qfh4m94gcls2cu6vvjnwwznx5uqywjekm - &a age1y4zp4ddq6xyffd8fgmn2jkl78qfh4m94gcls2cu6vvjnwwznx5uqywjekm
- &t460s age1g9sh8u6s344569d3cg8h30g9h7thld5pexcwzc4549jc84jvceqqjt9cfh - &b age1g9sh8u6s344569d3cg8h30g9h7thld5pexcwzc4549jc84jvceqqjt9cfh
- &pixel-nix age1t5s3txyj403rfecdhq5q2z3cnavy6m543gzyhkl2nu5t8fz0zctqtvm2tj - &c age1t5s3txyj403rfecdhq5q2z3cnavy6m543gzyhkl2nu5t8fz0zctqtvm2tj
- &compute-deck-user age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj - &d age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj
- &e age197a33mlf5294amjx59hycctu6wm4l3cu3w7n9rv3fs9340ql64rqjzpr7s
- &f age1sqj8z3feqm2dk3gj8mxpfn5dpqnsmus862e8ayd0d4cdresqffdswcf9ru
- &g age1rz75dqzfd6gulwh270ukmt5amcau6j8dpxgzx8fm6u8sjkyx9usq69y4s2
- &h age148huz6rc3q9xx5t873ncx75sja2sazlescwspxl7lsmxsqkz0apsy8cldp
- &i age1ck6lhd8thjcrdcnkn2epc8npztg0sfswahunjkwcf57rr0xaevys8fh0x6
- &j age13j6l33g0ghk4vezn0qwfal2qmcgqwkv89ejwezpe3n47mw8yxyuslj6y7d
- &k age13x0f3glnz4jvqty2v92cxrrnjcna6ed4qegrhulw9jjy08zuy3aqzvrfc6
machine_host_keys: machine_host_keys:
- &trip age10lv32k2guszr5y69sez3z5xj92wzmdxvfejd6hm8xr0pmclw2cvq0hk6pe - &trip age10lv32k2guszr5y69sez3z5xj92wzmdxvfejd6hm8xr0pmclw2cvq0hk6pe
- &compute-deck-host age1hcqem868xhjdj3lzsvgf0duylwrdp9nqs06a9d0043cpsuhms4as7cqnv4 - &compute-deck-host age1hcqem868xhjdj3lzsvgf0duylwrdp9nqs06a9d0043cpsuhms4as7cqnv4
@@ -15,10 +22,17 @@ creation_rules:
- path_regex: ^secrets/liam/ - path_regex: ^secrets/liam/
key_groups: key_groups:
- age: - age:
- *pixel-termux - *a
- *t460s - *b
- *pixel-nix - *c
- *compute-deck-user - *d
- *e
- *f
- *g
- *h
- *i
- *j
- *k
- *liam - *liam
- path_regex: ^tests/test_secrets/ - path_regex: ^tests/test_secrets/
key_groups: key_groups:

View File

@@ -59,6 +59,9 @@
openssh openssh
dig dig
bash bash
termscp
usbutils
ruby
git''; git'';
plainPackageOpts = map (name: { name = name; value = { enable = lib.mkDefault true; }; }) packageNames; plainPackageOpts = map (name: { name = name; value = { enable = lib.mkDefault true; }; }) packageNames;
packageOpts = lib.recursiveUpdate (builtins.listToAttrs plainPackageOpts) { packageOpts = lib.recursiveUpdate (builtins.listToAttrs plainPackageOpts) {

View File

@@ -1,6 +1,10 @@
{ lib, pkgs, config, inputs, utils, ... }: { lib, pkgs, config, inputs, utils, ... }:
{ {
imports = [ ./common-config.nix ]; imports = [ ./common-config.nix ];
options.vacu.underTest = lib.mkOption {
default = false;
type = lib.types.bool;
};
options.vacu.acmeCertDependencies = lib.mkOption { options.vacu.acmeCertDependencies = lib.mkOption {
default = {}; default = {};
example = '' example = ''

55
deterministic-certs.nix Normal file
View File

@@ -0,0 +1,55 @@
{ nixpkgs ? import <nixpkgs> }: let
pkgs = nixpkgs;
lib = nixpkgs.lib;
defaultCertTemplate = {
serial = 1;
activation_date = "1970-01-01 00:00:00 UTC";
expiration_date = "2500-01-01 00:00:00 UTC";
};
keyValToConfigLines = (key: value:
if (builtins.isString value) || (builtins.isPath value) then "${key} = \"${value}\"" else
if builtins.isInt value then "${key} = ${builtins.toString value}" else
if builtins.isList value then map (innerValue: keyValToConfigLines key innerValue) else
if builtins.isBool value then (if value then "${key}" else "# no ${key}") else
throw "don't know how to handle ${builtins.typeOf value}"
);
mkTemplateConfig = config: lib.concatStringsSep "\n" (lib.lists.flatten (lib.attrsets.mapAttrsToList keyValToConfigLines config));
certCfg = pkgs.writeText "deterministic-cert.cfg" ''
serial = 1
activation_date = "1970-01-01 00:00:00 UTC"
expiration_date = "2500-01-01 00:00:00 UTC"
'';
privKeyFile = name: let
keySizeBits = 256;
keySizeHex = builtins.toString (keySizeBits / 4);
in pkgs.runCommand "deterministic-privkey-${name}.pem" {} ''
seed=$(echo ${lib.escapeShellArg (builtins.toJSON name)} | ${pkgs.ruby_3_2}/bin/ruby -rjson -e 'name = JSON.parse(STDIN.gets); print name.unpack("H*")[0].ljust(${keySizeHex}, "0")')
${pkgs.gnutls}/bin/certtool --generate-privkey --outfile=$out --key-type=rsa --sec-param=high --seed=$seed
'';
generateCert = { name, config, args, preCommands ? "" }: let
deriv = pkgs.runCommand "deterministic-cert-${name}" {} ''
mkdir -p $out
cd $out
ln -s ${privKeyFile name} privkey.pem
ln -s ${pkgs.writeText "${name}-template.cfg" (mkTemplateConfig (defaultCertTemplate // config))} template.cfg
${preCommands}
${pkgs.gnutls}/bin/certtool ${lib.escapeShellArgs args} --load-privkey=privkey.pem --outfile=cert.pem --template=template.cfg
'';
in deriv // { privateKeyPath = "${deriv}/privkey.pem"; certificatePath = "${deriv}/cert.pem"; };
in {
inherit privKeyFile;
selfSigned = name: config: generateCert { inherit name config; args = [ "--generate-self-signed" ]; };
caSigned = name: ca: config: generateCert {
inherit name config;
preCommands = ''
ln -s ${ca.privateKeyPath} ca-privkey.pem
ln -s ${ca.certificatePath} ca-cert.pem
'';
args = [
"--generate-certificate"
"--load-ca-certificate=ca-cert.pem"
"--load-ca-privkey=ca-privkey.pem"
];
};
}

88
flake.lock generated
View File

@@ -24,11 +24,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1717915259, "lastModified": 1719864345,
"narHash": "sha256-VsGPboaleIlPELHY5cNTrXK4jHVmgUra8uC6h7KVC5c=", "narHash": "sha256-e4Pw+30vFAxuvkSTaTypd9zYemB/QlWcH186dsGT+Ms=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "1bbdb06f14e2621290b250e631cf3d8948e4d19b", "rev": "544a80a69d6e2da04e4df7ec8210a858de8c7533",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -182,11 +182,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1717931644, "lastModified": 1720045378,
"narHash": "sha256-Sz8Wh9cAiD5FhL8UWvZxBfnvxETSCVZlqWSYWaCPyu0=", "narHash": "sha256-lmE7B+QXw7lWdBu5GQlUABSpzPk3YBb9VbV+IYK5djk=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "3d65009effd77cb0d6e7520b68b039836a7606cf", "rev": "0a30138c694ab3b048ac300794c2eb599dc40266",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -204,11 +204,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1717685136, "lastModified": 1720025282,
"narHash": "sha256-S+C/DX5HOhlhJAmcGxbB+Tv6oqZOkr3z/WzPuydXI14=", "narHash": "sha256-I70ARXPm1YjGJ0efykd5zsapUZtmVZ/sIgwJ0F0j17w=",
"owner": "Jovian-Experiments", "owner": "Jovian-Experiments",
"repo": "Jovian-NixOS", "repo": "Jovian-NixOS",
"rev": "fd13986ede9b94c50e84aecb2c88863e297bbb52", "rev": "8dd0f8383bd60b8ed66cd27c1b49cdbf7be4ad9d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -226,11 +226,11 @@
"spectrum": "spectrum" "spectrum": "spectrum"
}, },
"locked": { "locked": {
"lastModified": 1717441449, "lastModified": 1720034501,
"narHash": "sha256-juxjgmLnFbl+/hhIO2cVtIa6caCO4pLKlZWUMwAOznM=", "narHash": "sha256-fzZpuVnhw5uOtA4OuXw3a+Otpy8C+QV0Uu5XfhGEPSg=",
"owner": "astro", "owner": "astro",
"repo": "microvm.nix", "repo": "microvm.nix",
"rev": "e3a4dd5b381fb580804105594cc9c71dc45abdb5", "rev": "a808af7775f508a2afedd1e4940a382fe1194f21",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -395,13 +395,28 @@
"type": "github" "type": "github"
} }
}, },
"nixos-hardware": {
"locked": {
"lastModified": 1719895800,
"narHash": "sha256-xNbjISJTFailxass4LmdWeV4jNhAlmJPwj46a/GxE6M=",
"owner": "nixos",
"repo": "nixos-hardware",
"rev": "6e253f12b1009053eff5344be5e835f604bb64cd",
"type": "github"
},
"original": {
"owner": "nixos",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1717786204, "lastModified": 1709961763,
"narHash": "sha256-4q0s6m0GUcN7q+Y2DqD27iLvbcd1G50T2lv08kKxkSI=", "narHash": "sha256-6H95HGJHhEZtyYA3rIQpvamMKAGoa8Yh2rFV29QnuGw=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "051f920625ab5aabe37c920346e3e69d7d34400e", "rev": "3030f185ba6a4bf4f18b87f345f104e6a6961f34",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -429,11 +444,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1717880976, "lastModified": 1719663039,
"narHash": "sha256-BRvSCsKtDUr83NEtbGfHLUOdDK0Cgbezj2PtcHnz+sQ=", "narHash": "sha256-tXlrgAQygNIy49LDVFuPXlWD2zTQV9/F8pfoqwwPJyo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "4913a7c3d8b8d00cb9476a6bd730ff57777f740c", "rev": "4a1e673523344f6ccc84b37f4413ad74ea19a119",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -445,11 +460,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1717786204, "lastModified": 1719848872,
"narHash": "sha256-4q0s6m0GUcN7q+Y2DqD27iLvbcd1G50T2lv08kKxkSI=", "narHash": "sha256-H3+EC5cYuq+gQW8y0lSrrDZfH71LB4DAf+TDFyvwCNA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "051f920625ab5aabe37c920346e3e69d7d34400e", "rev": "00d80d13810dbfea8ab4ed1009b09100cca86ba8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -458,13 +473,13 @@
"type": "indirect" "type": "indirect"
} }
}, },
"nixpkgs2405": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1718810994, "lastModified": 1720023543,
"narHash": "sha256-qrHSG34MeJdbK7WO3+NCehOf2p8ptW50UiMTAcs9wHU=", "narHash": "sha256-5zeNYG6y8/rcdKL/Onhh84WP6/8gYgTC7fC63ZM2+5Y=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "79f152a46bd42ba3a9fe96513e0fd9ac88190079", "rev": "ab02aaff3517c7667aad7b72b1f7e126decbef12",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -473,21 +488,6 @@
"type": "indirect" "type": "indirect"
} }
}, },
"nixpkgs_2": {
"locked": {
"lastModified": 1717861563,
"narHash": "sha256-qekkLNkKoTJkk9IUJ1wizquB1d1FHWaZP3NQTLorFdI=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a6c3bf2daa3bf17c0e76597c36e221ed7dcb2413",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-23.11-small",
"type": "indirect"
}
},
"nmd": { "nmd": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -649,9 +649,9 @@
"nix-inspect": "nix-inspect", "nix-inspect": "nix-inspect",
"nix-on-droid": "nix-on-droid", "nix-on-droid": "nix-on-droid",
"nix-search-cli": "nix-search-cli", "nix-search-cli": "nix-search-cli",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_2",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
"nixpkgs2405": "nixpkgs2405",
"padtype": "padtype", "padtype": "padtype",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"vscode-server": "vscode-server" "vscode-server": "vscode-server"
@@ -705,11 +705,11 @@
"nixpkgs-stable": "nixpkgs-stable" "nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1717902109, "lastModified": 1719873517,
"narHash": "sha256-OQTjaEZcByyVmHwJlKp/8SE9ikC4w+mFd3X0jJs6wiA=", "narHash": "sha256-D1dxZmXf6M2h5lNE1m6orojuUawVPjogbGRsqSBX+1g=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "f0922ad001829b400f0160ba85b47d252fa3d925", "rev": "a11224af8d824935f363928074b4717ca2e280db",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -3,8 +3,7 @@
inputs = { inputs = {
nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; #todo: put this back to -small once jovian-nixos is fixed nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; #todo: put this back to -small once jovian-nixos is fixed
nixpkgs.url = "nixpkgs/nixos-23.11-small"; nixpkgs.url = "nixpkgs/nixos-24.05-small";
nixpkgs2405.url = "nixpkgs/nixos-24.05-small";
nix-inspect = { nix-inspect = {
url = "github:bluskript/nix-inspect"; url = "github:bluskript/nix-inspect";
#inputs.nixpkgs.follows = "nixpkgs"; #inputs.nixpkgs.follows = "nixpkgs";
@@ -45,6 +44,7 @@
url = "github:astro/microvm.nix"; url = "github:astro/microvm.nix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nixos-hardware.url = "github:nixos/nixos-hardware";
}; };
outputs = { self, nixpkgs, nix-on-droid, ... }@inputs: { outputs = { self, nixpkgs, nix-on-droid, ... }@inputs: {
@@ -85,7 +85,7 @@
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
}; };
nixosConfigurations.fw = inputs.nixpkgs2405.lib.nixosSystem { nixosConfigurations.fw = nixpkgs.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
modules = [ ./fw ]; modules = [ ./fw ];
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
@@ -96,8 +96,6 @@
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = { inherit inputs; };
}; };
diskoConfigurations.compute-deck = import ./compute-deck/partitioning.nix;
checks = nixpkgs.lib.genAttrs [ "x86_64-linux" ] (system: checks = nixpkgs.lib.genAttrs [ "x86_64-linux" ] (system:
let let
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
@@ -117,25 +115,44 @@
hostPkgs = pkgs; hostPkgs = pkgs;
imports = [ config ./tests/triple-dezert.nix ]; imports = [ config ./tests/triple-dezert.nix ];
}; };
# trip_haproxy_config = let
# hacfg = self.nixosConfigurations.triple-dezert.config.containers.frontproxy.config.services.haproxy;
# in pkgs.stdenvNoCC.mkDerivation {
# name = "trip-haproxy-config-check";
# script = ''
# mkdir -p certs/shelvacu.com/
# touch certs/shelvacu.com/full.pem
# ${hacfg.package}/bin/haproxy \
# -f ${pkgs.writeText "haproxy-config" hacfg.config} \
# -c \
# -dW \
# -dD \
# -C $PWD
# '';
# };
} }
); );
nixosModules.common = import ./common-config.nix; nixosModules.common = import ./common-config.nix;
packages.x86_64-linux.digitalOceanImage = import ./generic-digitalocean-nixos.nix { inherit inputs; }; packages.x86_64-linux.digitalOceanImage = import ./generic-digitalocean-nixos.nix { inherit inputs; };
qb = /* qb is "quick build" */ let
toplevelOf = name: self.nixosConfigurations.${name}.config.system.build.toplevel;
deterministicCerts = import ./deterministic-certs.nix { nixpkgs = inputs.nixpkgs.legacyPackages.x86_64-linux; };
in rec {
# nix-on-droid is impure >:(
# nod = self.nixOnDroidConfigurations.default.activationPackage;
fw = toplevelOf "fw";
triple-dezert = toplevelOf "triple-dezert";
trip = triple-dezert;
compute-deck = toplevelOf "compute-deck";
cd = compute-deck;
liam = toplevelOf "liam";
lp0 = toplevelOf "lp0";
devver = toplevelOf "devver";
shel-installer = toplevelOf "shel-installer";
iso = self.nixosConfigurations.shel-installer.config.system.build.isoImage;
do = self.packages.x86_64-linux.digitalOceanImage;
check-triple-dezert = self.checks.x86_64-linux.trip.driver;
check-trip = check-triple-dezert;
check-liam = self.checks.x86_64-linux.liam.driver;
dc.priv = deterministicCerts.privKeyFile "test";
dc.cert = deterministicCerts.selfSigned "test" {};
};
all = let
pkgs = nixpkgs.legacyPackages.x86_64-linux;
symlinkCommands = pkgs.lib.mapAttrsToList (name: pkg: "ln -s ${pkg} ${name}") self.qb;
in pkgs.runCommand "nix-stuff-all" {} ''
mkdir $out
cd $out
${pkgs.lib.concatStringsSep "\n" symlinkCommands}
'';
}; };
} }

51
fw/apex.nix Normal file
View File

@@ -0,0 +1,51 @@
# everything to interact with my apex flex, pcsc stuff, fido2 stuff, etc
{ pkgs, ... }: {
# apparently this is already enabled??
# nixpkgs.overlays = [ ( final: prev: {
# libfido2 = prev.libfido2.override { withPcsclite = true; };
# } ) ];
vacu.packages.libfido2.enable = true;
vacu.packages.pcsclite.enable = true;
vacu.packages.pcsc-tools.enable = true;
vacu.packages.scmccid.enable = true;
vacu.packages.opensc.enable = true;
services.pcscd.enable = true;
# conflicts with pcscd, see https://stackoverflow.com/questions/55144458/unable-to-claim-usb-interface-device-or-resource-busy-stuck
boot.blacklistedKernelModules = [ "pn533_usb" "pn533" "nfc" ];
# bunch of stuff from https://wiki.nixos.org/wiki/Web_eID
# Tell p11-kit to load/proxy opensc-pkcs11.so, providing all available slots
# (PIN1 for authentication/decryption, PIN2 for signing).
environment.etc."pkcs11/modules/opensc-pkcs11".text = ''
module: ${pkgs.opensc}/lib/opensc-pkcs11.so
'';
environment.etc."opensc.conf".text = ''
app default {
reader_driver pcsc {
enable_pinpad = false;
}
}
'';
environment.systemPackages = [
# Wrapper script to tell to Chrome/Chromium to use p11-kit-proxy to load
# security devices, so they can be used for TLS client auth.
# Each user needs to run this themselves, it does not work on a system level
# due to a bug in Chromium:
#
# https://bugs.chromium.org/p/chromium/issues/detail?id=16387
(pkgs.writeShellScriptBin "setup-browser-eid" ''
NSSDB="''${HOME}/.pki/nssdb"
mkdir -p ''${NSSDB}
${pkgs.nssTools}/bin/modutil -force -dbdir sql:$NSSDB -add p11-kit-proxy \
-libfile ${pkgs.p11-kit}/lib/p11-kit-proxy.so
'')
];
programs.firefox.enable = true;
programs.firefox.policies.SecurityDevices.p11-kit-proxy = "${pkgs.p11-kit}/lib/p11-kit-proxy.so";
}

View File

@@ -1,11 +1,14 @@
{ config, inputs, pkgs, lib, ... }: { { config, inputs, pkgs, lib, ... }: {
imports = [ imports = [
../common-nixos-config.nix ../common-nixos-config.nix
inputs.nixos-hardware.nixosModules.framework-16-7040-amd
./apex.nix
]; ];
system.nixos.tags = [ "host-${config.networking.hostName}" ]; system.nixos.tags = [ "host-${config.networking.hostName}" ];
boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
networking.networkmanager.enable = true; networking.networkmanager.enable = true;
# boot.kernelParams = [ "nvme.noacpi=1" ]; # DONT DO IT: breaks shit even more
vacu.packages.bitwarden-desktop.enable = true; vacu.packages.bitwarden-desktop.enable = true;
vacu.packages.nheko.enable = true; vacu.packages.nheko.enable = true;
vacu.packages.librewolf.enable = true; vacu.packages.librewolf.enable = true;
@@ -19,6 +22,16 @@
vacu.packages.iio-sensor-proxy.enable = true; vacu.packages.iio-sensor-proxy.enable = true;
vacu.packages.power-profiles-daemon.enable = true; vacu.packages.power-profiles-daemon.enable = true;
vacu.packages.acpi.enable = true; vacu.packages.acpi.enable = true;
vacu.packages.jellyfin-media-player.enable = true;
vacu.packages.vlc.enable = true;
vacu.packages.dmidecode.enable = true;
vacu.packages.prismlauncher.enable = true;
vacu.packages.ffmpeg_7-full.enable = true;
services.fwupd.enable = true;
#fwupd gets confused by the multiple EFI partitions, I think I just have to pick one
#update: it didn't work, I dunno why. Leaving this here anyways
services.fwupd.daemonSettings.EspLocation = lib.mkForce "/boot0";
services.xserver.enable = true; services.xserver.enable = true;
services.displayManager.sddm.enable = true; services.displayManager.sddm.enable = true;

View File

@@ -9,6 +9,7 @@
./mail.nix ./mail.nix
./dkim.nix ./dkim.nix
./sieve.nix ./sieve.nix
./network.nix
]; ];
options = let options = let
@@ -29,6 +30,10 @@
"shop.theviolincase.com" "shop.theviolincase.com"
]; ];
domains = mkReadOnly (config.vacu.liam.shel_domains ++ config.vacu.liam.julie_domains); domains = mkReadOnly (config.vacu.liam.shel_domains ++ config.vacu.liam.julie_domains);
relayhost = lib.options.mkOption {
type = lib.types.str;
default = "[smtp.migadu.com]:465";
};
reservedIpLocal = mkReadOnly "10.46.0.7"; reservedIpLocal = mkReadOnly "10.46.0.7";
}; };
}; };
@@ -39,13 +44,6 @@
networking.domain = "dis8.net"; networking.domain = "dis8.net";
# networking.interfaces."ens3".useDHCP = false; # networking.interfaces."ens3".useDHCP = false;
# from `curl -fsSL http://169.254.169.254/metadata/v1.json | jq '.interfaces.public[0].anchor_ipv4'`
# {
# "ip_address": "10.46.0.7",
# "netmask": "255.255.0.0",
# "gateway": "10.46.0.1"
# }
services.openssh.enable = true; services.openssh.enable = true;
virtualisation.digitalOcean.setSshKeys = false; virtualisation.digitalOcean.setSshKeys = false;
@@ -54,4 +52,4 @@
system.stateVersion = "23.11"; system.stateVersion = "23.11";
}; };
} }

View File

@@ -75,13 +75,13 @@
userdb { userdb {
driver = passwd-file driver = passwd-file
args = username_format=%n /run/secrets/dovecot-passwd args = username_format=%n ${config.sops.secrets."dovecot-passwd".path}
override_fields = uid=${config.services.dovecot2.mailUser} gid=${config.services.dovecot2.mailGroup} user=%n override_fields = uid=${config.services.dovecot2.mailUser} gid=${config.services.dovecot2.mailGroup} user=%n
} }
passdb { passdb {
driver = passwd-file driver = passwd-file
args = username_format=%n /run/secrets/dovecot-passwd args = username_format=%n ${config.sops.secrets."dovecot-passwd".path}
override_fields = user=%n override_fields = user=%n
} }
@@ -93,4 +93,4 @@
# mail_debug = yes # mail_debug = yes
''; '';
}; };
} }

View File

@@ -1,8 +1,8 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }: let
let inherit (config.vacu.liam) shel_domains julie_domains domains relayhost;
inherit (config.vacu.liam) shel_domains julie_domains domains; debug = false;
fqdn = config.networking.fqdn; fqdn = config.networking.fqdn;
dovecot_transport = "lmtp:unix:private/dovecot-lmtp"; dovecot_transport = "lmtp:unix:private/dovecot-lmtp";
in { in {
networking.firewall.allowedTCPPorts = [ 25 465 ]; networking.firewall.allowedTCPPorts = [ 25 465 ];
@@ -16,12 +16,14 @@ in {
virtual = '' virtual = ''
julie@shelvacu.com julie julie@shelvacu.com julie
mom@shelvacu.com julie mom@shelvacu.com julie
mar@shelvacu.com mar
psv@shelvacu.com psv psv@shelvacu.com psv
'' + (lib.concatMapStringsSep "\n" (d: "@${d} shelvacu") shel_domains) + "\n" '' + (lib.concatMapStringsSep "\n" (d: "@${d} shelvacu") shel_domains) + "\n"
+ (lib.concatMapStringsSep "\n" (d: "@${d} julie") julie_domains); + (lib.concatMapStringsSep "\n" (d: "@${d} julie") julie_domains);
transport = '' transport = ''
shelvacu@${fqdn} ${dovecot_transport} shelvacu@${fqdn} ${dovecot_transport}
mar@${fqdn} ${dovecot_transport}
julie@${fqdn} ${dovecot_transport} julie@${fqdn} ${dovecot_transport}
psv@${fqdn} ${dovecot_transport} psv@${fqdn} ${dovecot_transport}
backup@${fqdn} ${dovecot_transport} backup@${fqdn} ${dovecot_transport}
@@ -37,15 +39,22 @@ in {
mapFiles.sender_access = pkgs.writeText "sender-access" (lib.concatMapStringsSep "\n" (d: "${d} REJECT") domains); mapFiles.sender_access = pkgs.writeText "sender-access" (lib.concatMapStringsSep "\n" (d: "${d} REJECT") domains);
# hack to get postfix to add a X-Original-To header # hack to get postfix to add a X-Original-To header
mapFiles.add_envelope_to = pkgs.writeText "addenvelopeto" "/(.+)/ PREPEND X-Envelope-To: $1"; mapFiles.add_envelope_to = pkgs.writeText "addenvelopeto" "/(.+)/ PREPEND X-Envelope-To: $1";
mapFiles.sender_transport = pkgs.writeText "sender-transport" "@shelvacu.com relayservice";
mapFiles.sender_relay = pkgs.writeText "sender-relay" "@shelvacu.com ${relayhost}";
# verbatim appended to main.cf # verbatim appended to main.cf
extraConfig = '' extraConfig = ''
smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt
virtual_alias_domains = virtual_alias_domains =
${lib.concatStringsSep ",\n " domains} ${lib.concatStringsSep ",\n " domains}
sender_dependent_default_transport_maps = hash:/etc/postfix/sender_transport
sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
header_checks = pcre:/etc/postfix/header_checks header_checks = pcre:/etc/postfix/header_checks
smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/sender_access smtpd_sender_restrictions = check_sender_access hash:/etc/postfix/sender_access
smtpd_recipient_restrictions = check_recipient_access pcre:/etc/postfix/add_envelope_to smtpd_recipient_restrictions = check_recipient_access pcre:/etc/postfix/add_envelope_to
recipient_delimiter = +
#we should never use these transport methods unless thru transport map #we should never use these transport methods unless thru transport map
# RFC3463: # RFC3463:
@@ -65,14 +74,28 @@ in {
# not actually 1024 bits, this applies to all DHE >= 1024 bits # not actually 1024 bits, this applies to all DHE >= 1024 bits
smtpd_tls_dh1024_param_file = ${lib.optionalString config.services.dovecot2.enableDHE config.security.dhparams.params.dovecot2.path} smtpd_tls_dh1024_param_file = ${lib.optionalString config.services.dovecot2.enableDHE config.security.dhparams.params.dovecot2.path}
# smtp_bind_address = 10.46.0.7
${lib.optionalString config.services.opendkim.enable (assert (config.services.opendkim.socket == "local:/run/opendkim/opendkim.sock"); '' ${lib.optionalString config.services.opendkim.enable (assert (config.services.opendkim.socket == "local:/run/opendkim/opendkim.sock"); ''
smtpd_milters = unix:/run/opendkim/opendkim.sock smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/run/opendkim/opendkim.sock non_smtpd_milters = unix:/run/opendkim/opendkim.sock
'')} '')}
''; '';
masterConfig."relayservice" = {
command = "smtp";
type = "unix";
args = [
"-o" "smtp_sasl_auth_enable=yes"
"-o" "smtp_sasl_security_options=noanonymous"
"-o" "smtp_tls_security_level=secure"
"-o" "smtp_sasl_password_maps=texthash:${config.sops.secrets.relay_creds.path}"
"-o" "smtp_tls_wrappermode=yes"
#"-o" "relayhost=${relayhost}"
] ++ (if debug then ["-v"] else []);
};
masterConfig.qmgr = lib.mkIf debug { args = ["-v"]; };
masterConfig.cleanup = lib.mkIf debug { args = ["-v"]; };
masterConfig.smtpd = lib.mkIf debug { args = ["-v"]; };
submissionsOptions = { submissionsOptions = {
smtpd_tls_key_file = config.security.acme.certs."liam.dis8.net".directory + "/key.pem"; smtpd_tls_key_file = config.security.acme.certs."liam.dis8.net".directory + "/key.pem";
smtpd_tls_cert_file = config.security.acme.certs."liam.dis8.net".directory + "/full.pem"; smtpd_tls_cert_file = config.security.acme.certs."liam.dis8.net".directory + "/full.pem";
@@ -101,4 +124,4 @@ in {
}; };
} }

26
liam/network.nix Normal file
View File

@@ -0,0 +1,26 @@
{ lib, config, ... }: let
# from `curl -fsSL http://169.254.169.254/metadata/v1.json | jq '.interfaces.public[0].anchor_ipv4'`
# {
# "ip_address": "10.46.0.7",
# "netmask": "255.255.0.0",
# "gateway": "10.46.0.1"
# }
interface_conf = {
useDHCP = true;
ipv4.addresses = [{
address = "10.46.0.7";
prefixLength = 24;
}];
ipv4.routes = [{
address = "0.0.0.0";
prefixLength = 0;
via = "10.46.0.1";
options.scope = "global";
options.src = "10.46.0.7";
options.metric = "1200";
}];
};
in {
networking.interfaces."ens3" = lib.mkIf (!config.vacu.underTest) interface_conf;
networking.interfaces."eth0" = lib.mkIf ( config.vacu.underTest) interface_conf;
}

View File

@@ -59,15 +59,18 @@
sieve_text = '' sieve_text = ''
require ["fileinto", "mailbox"]; require ["fileinto", "mailbox"];
if header :is "X-Envelope-To" "brandcrowd@shelvacu.com" { if header :is "Delivered-To" "shelvacu@liam.dis8.net" {
discard; if header :is "X-Envelope-To" "brandcrowd@shelvacu.com" {
discard;
}
elsif header :is "X-Envelope-To" "gmailfwd-fc2e10bec8b2@shelvacu.com" {
fileinto :create "gmail";
}
${concatStrings email_filters}
${concatStrings domain_filters}
} }
elsif header :is "X-Envelope-To" "gmailfwd-fc2e10bec8b2@shelvacu.com" {
fileinto :create "gmail";
}
${concatStrings email_filters}
${concatStrings domain_filters}
''; '';
in { in {
services.dovecot2.sieveScripts.before = pkgs.writeText "blargsieve" sieve_text; services.dovecot2.sieve.extensions = [ "fileinto" "mailbox" ];
} services.dovecot2.sieve.scripts.before = pkgs.writeText "blargsieve" sieve_text;
}

View File

@@ -20,5 +20,9 @@
restartUnits = [ "opendkim.service" ]; restartUnits = [ "opendkim.service" ];
owner = config.services.opendkim.user; owner = config.services.opendkim.user;
}; };
sops.secrets.relay_creds = {
restartUnits = [ "postfix.service" ];
owner = config.services.postfix.user;
};
}; };
} }

View File

@@ -1,4 +1,4 @@
dovecot-passwd: ENC[AES256_GCM,data:cZt43pgPNbORpqX6KyXvzVt1Q8tNz1cMF9YVUyL7saZyFqA5XA+uywU5yVerjdsTXfx4QeoYbA+bDE7qwdjTQBpEoEMm99WBb77rac652VGXXCas4nrbwMmZbUY2Z57PKd4GPN/i57VAD6eHiTV8HCd5OwiX7AlpmHXImgL9jr4P9skyTPIEnLF3NUVxktmAjn+X7IwmBH1mtn5Gesc5Q+6hoTQMwLn7ilYWfcOvaf5UOsHS6zvuTlGPuISaLPEvx2CLBccu7I38kKafCLTc1FOhdrFRu2n9/6gD1yIxUnbCkDWpcIV1e/3FlU5aQM7c7duQFVuIW9KpY2U0R2Y5Miv0ciU2D1GaJWMud7S/HCxPrQo=,iv:Arppozvg9+bjNCIJl7kRwbwGm2fuf7CjBfEfDT45+MQ=,tag:+PeAznYRW9S0Ok5uEn/qpQ==,type:str] dovecot-passwd: ENC[AES256_GCM,data:K54kOi2MB37Jra6ce+yDrVqFlie3+mJnVWD/A6c6d3nGV5fLi2ppn9Gkevuzz490QKNpZDbRa3CSnOHLrID5zJ2JTlOnXGAIPOd2XQZSZdW+lcnfKk2WjffRHkFoQIdKnKDqh8x0i+Ymrpy1TBg3USAAilvYliLHQDjd1djj0kFsxRScQyCc9F3YGM11X1pRNX2R7YyKKNxQVcTkCRxWdh8hs/o8aybpy7EeAHZoJyI+vywRKJK1FYLhX+tj3dTqLVsvpT1OePQJRVdrSifpGVP9uHoYZRVMrhb2nyCXjuJ/k3pHbHhKXt+Gnhh+2/cvvKApFE0YJoyqg6wey1GcmIw7tnE7dRfO/HGkDgHwzLQVPcdb2fdQs/C+AeJhtHAVMowYWroiEylMMqsv5QmAdDmFJjXRqhW7Zh/uaKOTZLa/xMUEf0/59pP8PWXvTrRB77c+EAcM+b804bvsa/cUly/vz+8AcWhCrZJIbmmbkToP3NGy4K3bbD7y4A6I01svSBlOXQGOF6D6QLK6snZ6ox4ZrdqClCzhSfZYSu4ZGtzr323Z,iv:JAvVAHK6OwutD2gph6rHlBxdaPh4OjL7Kr82kVz9dh0=,tag:+3HCNdV0+wbhNpYVPGAaaw==,type:str]
dkim_key: ENC[AES256_GCM,data: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,iv:7LF3l52m6YRKGd/8rxDady3AbSEcXuVRsIaLlgNfKOs=,tag:UCjMRgFZFHQyXY5NfbZRcg==,type:str] dkim_key: ENC[AES256_GCM,data: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,iv:7LF3l52m6YRKGd/8rxDady3AbSEcXuVRsIaLlgNfKOs=,tag:UCjMRgFZFHQyXY5NfbZRcg==,type:str]
dkim_pub: ENC[AES256_GCM,data:XLYRTAviK+r6DnRU4+lc58elI3FJ+FPsB1A5sQOk+pb+fNu7zFCiZdz/MwTVkE9izDP1Onv+VhV8sRgmxacTv4nW5GcukCrm3FmCp2jm6QF1/40/WRv6Lkbek0tV1bMOQPy9Zj8wdO9M05XCXUVXk4x17rj+lw8ApwJS2pJMoultMFx34tx2pNEnmO3MFtuBOxzeU2yP+NhF2sJNA62to78AiH5EblkoF0a6sUYk553U+sv3Ob0lo1nSv6c8zwl7y1WSNQnLK+/3WxSVGfePHVsVM8Zze1KFTVLQQggIzWTdcr7AgcTGbk3kaYCeucfQ60pVlqOyPnkJoUJ8HR1RSajFk6Ylzw0xBpY85qAXNT2YIRiq0HTUc1s5lD0luXLQEP+g+XUwZfzFRZgt1nWBlPmpbj2Ylj1FfrA7EXsIK9nyo+rf0qRn/4HusJATr9ddYmZdxwazl1FXkOKLHPyu1NlzwoTNSQQgMHlzxzUvrrv7+mI2nQvXRx82TSRytqrMvoBTF1NFX+pRjhNg9fcq0oPJ2ORqOVQsxzhLhB+tw7Cg+UHGWlnKnkqaKH1JDmOFyJDB96aPUnSQT2J8qkyb+hMBXz9mme8rZopkHrA4WyDXv3zpEi0P5Sj0DDwdRxKMdDdZ4hw79YQIrd63cIorN8XG6Icevb25LfekLEq/C2FS8+kADagyOM0uzCw2p/qacNz37ZNGqPK6gYkjnyoAfSm14zbgoLX/5dnf7eCuMatevTm4AcE53RawQfzz0YNJuEv5uqD/WUy+UIKHIwxPYY9FWBBPmH+8eaPC1mMPh54I444b39FwpnPU8GwxEPsjRg8TSnohawNmmhEWEpmlawEKw+C+BE6A2DmVJzyeBvVRwe/W6CPgyYxgSGWUuvfZFm1GrzwZDjCOEMRn7qMwMBxh1nr2BOAiNxA38UtsymaZO5ZOknClWlKIkIFl8NJdVITNNsI48KMuSY20o1puzkxMaAUH3OrGEhtoHrEOeIq+KCFzH2gZo6L5hbv9CHM7QgCYsbtVIMwL+cRZZaSNubS3K48OmWJnHNuqkcrSI4lqfjLhz1DbnQ==,iv:/cNMmlpq9LSOk0MwVq8NaWvp47q68lKWTx4s5nkwF5c=,tag:ZNX+yZsSxdhFsavDpX380g==,type:str] dkim_pub: ENC[AES256_GCM,data:XLYRTAviK+r6DnRU4+lc58elI3FJ+FPsB1A5sQOk+pb+fNu7zFCiZdz/MwTVkE9izDP1Onv+VhV8sRgmxacTv4nW5GcukCrm3FmCp2jm6QF1/40/WRv6Lkbek0tV1bMOQPy9Zj8wdO9M05XCXUVXk4x17rj+lw8ApwJS2pJMoultMFx34tx2pNEnmO3MFtuBOxzeU2yP+NhF2sJNA62to78AiH5EblkoF0a6sUYk553U+sv3Ob0lo1nSv6c8zwl7y1WSNQnLK+/3WxSVGfePHVsVM8Zze1KFTVLQQggIzWTdcr7AgcTGbk3kaYCeucfQ60pVlqOyPnkJoUJ8HR1RSajFk6Ylzw0xBpY85qAXNT2YIRiq0HTUc1s5lD0luXLQEP+g+XUwZfzFRZgt1nWBlPmpbj2Ylj1FfrA7EXsIK9nyo+rf0qRn/4HusJATr9ddYmZdxwazl1FXkOKLHPyu1NlzwoTNSQQgMHlzxzUvrrv7+mI2nQvXRx82TSRytqrMvoBTF1NFX+pRjhNg9fcq0oPJ2ORqOVQsxzhLhB+tw7Cg+UHGWlnKnkqaKH1JDmOFyJDB96aPUnSQT2J8qkyb+hMBXz9mme8rZopkHrA4WyDXv3zpEi0P5Sj0DDwdRxKMdDdZ4hw79YQIrd63cIorN8XG6Icevb25LfekLEq/C2FS8+kADagyOM0uzCw2p/qacNz37ZNGqPK6gYkjnyoAfSm14zbgoLX/5dnf7eCuMatevTm4AcE53RawQfzz0YNJuEv5uqD/WUy+UIKHIwxPYY9FWBBPmH+8eaPC1mMPh54I444b39FwpnPU8GwxEPsjRg8TSnohawNmmhEWEpmlawEKw+C+BE6A2DmVJzyeBvVRwe/W6CPgyYxgSGWUuvfZFm1GrzwZDjCOEMRn7qMwMBxh1nr2BOAiNxA38UtsymaZO5ZOknClWlKIkIFl8NJdVITNNsI48KMuSY20o1puzkxMaAUH3OrGEhtoHrEOeIq+KCFzH2gZo6L5hbv9CHM7QgCYsbtVIMwL+cRZZaSNubS3K48OmWJnHNuqkcrSI4lqfjLhz1DbnQ==,iv:/cNMmlpq9LSOk0MwVq8NaWvp47q68lKWTx4s5nkwF5c=,tag:ZNX+yZsSxdhFsavDpX380g==,type:str]
sops: sops:
@@ -10,50 +10,113 @@ sops:
- recipient: age1y4zp4ddq6xyffd8fgmn2jkl78qfh4m94gcls2cu6vvjnwwznx5uqywjekm - recipient: age1y4zp4ddq6xyffd8fgmn2jkl78qfh4m94gcls2cu6vvjnwwznx5uqywjekm
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3S0FqZWxDYmxHYU5FZVQz YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZREpDaXVwSjBPZEtaUFU1
V2FZMFFSVXJubVRaNDZORDJPSXhHMnludmpRCjJrendscEdqU0p6K1R6eE9FUGtj d1FTYnV1STlUdW5oeis4RStVckcvUFhPcndRCnNUdndTenhxN1M1STNlZmtqcWtI
RVB4Z3dlNHlBSHRhZ0ZMODdDRkN6ZFEKLS0tIFlzUStVWmhlYWExV1JscHE0KzhG amkxZitGZ2p1ZlNTRFVaYkNvWWdnRkUKLS0tIExLYm5PYVI4aFViaER2L1dUOGMy
Vm1uUmhQRzAvL1YzTWVVbllRUlE2Z0EKwg6SBat+CG8E7/j7K0sakqGSyJYNzXqt d05BTDlqanFMQ1hjazRLUUVlaXpHL2cK+kXvv9khiwYlBK+lmqgYmHNNjMXHU5FZ
b0DMsGq9GnHE1Ph6gGVVWO+pos/FGuunSDyL0lcXk9xJE02FErnw+w== x5dpXndIiTRJ0cGtEgK78efbQmVNsHAae2X0E0IxbvrSe26S5PIbMQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1g9sh8u6s344569d3cg8h30g9h7thld5pexcwzc4549jc84jvceqqjt9cfh - recipient: age1g9sh8u6s344569d3cg8h30g9h7thld5pexcwzc4549jc84jvceqqjt9cfh
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAwNVl3ZTNGWGdMT280MnhQ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBONXlpMm5KTmZuKysybU0z
R2RHTGRWVFpjMWltMDVIWk1YSUc2eEhjbWwwCnNiTjA4dUZuOU1tNTZtd240VXpU OUJCMmdrZ0V4amI4NTNtOEFqSXVtbW92cjFVCmlCZGF4bXMycXhJS3h6OWVpV000
c0FKY3VoR1dYUVo1MDZjMEJ5MmhjeEEKLS0tIGhuT3k2VlFpTWpJdFJYM0JhZWtS SjZuQUFxelVpT3BXOVh5eU1vYnNKMjAKLS0tIG1KYjZJU1dMd1Y3bmxWaDhOSEJn
dzNFb0FDcERGTFVUOTgxN3czTmRUME0KihoqiXkph3sNWTwn6tFi29z9jnht6JRT SUp1akQ2bUU0VmQvVkhheXZ4Zk5jWVkKqJ12/g0H8l6WwpiHxA0K3g3Ry4dpPb/h
zOMNiaWjMHQ7GiR+Yv1JMWrEvKRrEjNaFXt89z0Ebx4llTtyH8W2fw== 2m84IYzpQA28BRCSHeIEeH1hQ1jU33/625XlNE1iJncPqu9YH5mXug==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1t5s3txyj403rfecdhq5q2z3cnavy6m543gzyhkl2nu5t8fz0zctqtvm2tj - recipient: age1t5s3txyj403rfecdhq5q2z3cnavy6m543gzyhkl2nu5t8fz0zctqtvm2tj
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzWE91QUFmTzdEUjJ3TTFX YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLM3NCcGVPTS9hWHQvMCsv
Y2o0Yy9BZjdkc2VVcis4a3FlcDVScDF5eGwwCkZocDFIN3B5dHdNTDNaVXI2WHBF RlJ5M0tVQWZIUm1tWSt2NlFVRGtHaTN1Rmd3CndVUHpEcU15S2lmbHpIY0h6WW1B
dDVXMDdvOXVBM3V1NW01YngzclJ1RXMKLS0tIDV5M2JURHkvWWFlbGtUNEhxZ2ZE aEpRZVgzN0puRmlMNWNQNW94TXh6UUkKLS0tIEVXSVVVL2JaMGRFcldoVnZ1TFZz
RVlDMDgvNVFOamlFR1BZMUtrMzJ4N1UK6r7QbX3nEBu+S8e7oqCk3ys6hqXHkyW4 bzJ3UGl1aGpsa0FGSVkzeGRHZDJWdmMKZgg4UtokzNDBuVZYoyYirTI1NEC3QGmm
z4hWz1rr/23JpGR2ENRS+DpHRCRo4KKRhUx2hLc6C2XijNgD4YsUCA== ilOukMvpTZFYtKbwWVOuB8kyeudlkupavzlnHYAGBbpMVccpPeZHAw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj - recipient: age1dzdf4rgep3ctk3dnrmrqtdgrchaa8nszfc4dp29gqwsst3z6jyrq57vfsj
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqelVSdDFFcVZxODBiVkEv YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOZ0tyczJoVzZxUmhIZG14
QUhYUzM5SDZLVWQ4YlB2UGorZWlidUhIa1N3Ck96TXFGTXBtSVFLdFY1b3BKK3g5 WDZjSlM0Q2F6VE9Yb1hRV0d5dGVoVmErVkJFCi9HbXdxZE9NZ0pLaFo1Nlk5QjRV
ejZFTkZOTDdqdHFsWmRKNEcyaUZZWW8KLS0tIDJtL2JaRE5XaHNvYW9HMFYrbTFP TSsrMlFqV2Z0OVlWVjRnYXpyTlNWdUUKLS0tIGZ5M2ZEWFR0NDNQUFQxMW1tTXlP
NUFlUTVvQVdiTlBZOVZqSjA1ODNhUHcK8hnqUuHjUgjF8nbZgY4BTkk58BbRCYWV dDRaYnFZajR2S3ZoZ1FFWURYVFVpSFkK8YuczSfs+j3dL1OT4sr2/kfdAxPRstJj
NOPw/jUdEZBRoTJqoEdOLAtW/x1h7Xo+mpVuDW0K7h07LiaU7FL8xQ== SeDlvg4C0e2wKrqj0QwjN5oz8t21ELerXska7yZ3cod5gaQcFxB44w==
-----END AGE ENCRYPTED FILE-----
- recipient: age197a33mlf5294amjx59hycctu6wm4l3cu3w7n9rv3fs9340ql64rqjzpr7s
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBNWlKeHh6UjNIRTAycEJ1
UVhJMi9CUVBsVld3YlBEYjVwaWE0T2V0cFJzCnpEb2ZxNkNwMDBDQ3JsQXVjY1lS
eFhqSkcvenkvOHNOclI3dkc5NytmQjAKLS0tIHkrc3ZEQjhJVVZlZWVJMVE0b0x5
QkxVMkhOK2hUS0lQVGlXYXUrVm1LVFkKyFIvkGHeykZBib8gNln1mEHtU5+Xr9rC
RpphkvAU9AA4J5/LXQs3To/WzTg9gt2fSxtrwk9TLheheRfUcHDuRQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age1sqj8z3feqm2dk3gj8mxpfn5dpqnsmus862e8ayd0d4cdresqffdswcf9ru
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6aENxNUpXUUxTcEZobkpW
SFo1UWlUSXRWbzF2bWp6WU9Idi93OWQvdGl3Ck1rdlNYZFR5dThKa3NaVFU4NWY4
dTdUNUdEQ1hkWkRsT0dNbVVqMytnTXcKLS0tIExXZlgydnhXTktyeDNrZmg0RFlt
QXAzNGk3MmRCSng2SlN5bGdiSTlJRTQKXy5hTxS47WVjw1ILaaNfMaW7YMIS3FGP
hvYeGGL2WHstUapyYb/Rgn46KJgk1gfDchYyHq+06SkpZRaUzCBDUw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1rz75dqzfd6gulwh270ukmt5amcau6j8dpxgzx8fm6u8sjkyx9usq69y4s2
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUYWl1NUQzMElhbFBrbVBu
eURzOGFJSW85dFMzLzR4M3UvOVhQUGYvS0ZRCm1qYXJTUnpUcUVWUTFtRWQ2OHBO
UVg2UC9OSDJkL21vV3VNV0l1Z3ZHcHcKLS0tIDhVaGpFZ1djSnFaRnVKckxtQU0z
YlAyNGxsYno2U1NIMDVtVXJwcFA0ZWsKdNW5iANSWOGdSRYeBf/+/gtk7b+IN/ir
lo1HtaIT1a5tA28JfAo6ixIKdF5nnSIunM6Z0JlF9zKuJbBOmdVbHw==
-----END AGE ENCRYPTED FILE-----
- recipient: age148huz6rc3q9xx5t873ncx75sja2sazlescwspxl7lsmxsqkz0apsy8cldp
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIWDd5Yk1pNGZ0UHRrc3lu
WWlPZTd5bFIvNVBqTWplR3NzdS8rQ0gyZVdVCkUvMEg5eWxCWHNyYTcvMFd6ek9y
Z0RudTRHanlTTVhYZDBuMkpsYTcwWjAKLS0tIGtDemJabDRVakJxMUdVUWQ2VjIv
NTBabFVLNENzWlNoUmZSUXU2eEJtdEEKuOXBlsIBsgjQvRZ4fKdoLfs1gqZYa4og
9o/mo+ciXYU3xPPOhnd/OTar/8pBpCBBCO0Ag+1Me/dVYbA0s8Jvvw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ck6lhd8thjcrdcnkn2epc8npztg0sfswahunjkwcf57rr0xaevys8fh0x6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCUnNZSEtpb0JVOTVjazFB
NHdXSnVxRm4vaXN6VE5leGU1Z1JGOHFEUUNVCnNwdUxweTVlanR2ODdvTzlDWkZR
NWVsY0k3WmFOWktsUVJGT1p6QUlKbGsKLS0tIEtnRVdxeWVYd29XZHVQWmZCNnhE
OElkbHNtUG1ncXdQWEpOcDNMeUg1d0EKF9OjITJDrkfZA2wI6Gm+0+MTDw4OPkQt
SDbNe5Gllo8BC1jTRM3H+uxsQ5L0TRrwnrSxNYjNdDIRHMrIxi3qcg==
-----END AGE ENCRYPTED FILE-----
- recipient: age13j6l33g0ghk4vezn0qwfal2qmcgqwkv89ejwezpe3n47mw8yxyuslj6y7d
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqVk12WUxKdWdDVWRCU1dk
VkhNZWhNeWJ6OWJJaWdXNFZwRlZMT0lOTFdJClRyYkQvank0cGlZSzJGaE1LVVpO
VURjMnBIY3VvMkVnbzlJVGF0dU1FR2MKLS0tIHZlV0U4azN4aEVRU1YzWDN6U3Nz
YlIzbFBDd1pqMTVQa0diYnZjRmRRa2MKcPAvAB0B/zNj+mcavMkJdksWl8o1j8oQ
gGG8xdIEPT9wjfbL75IvHOy/7TKJR0uVomD8IB4QuVi1MxJh6jNJQw==
-----END AGE ENCRYPTED FILE-----
- recipient: age13x0f3glnz4jvqty2v92cxrrnjcna6ed4qegrhulw9jjy08zuy3aqzvrfc6
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpbmxpNlZvV2JWYmRJS3lq
Um5GVDQ0ampMTDdzZHB1RFFqZ012bFZMd3g4CjdoMzdOUXhtSEF4Tjk1UTJlNGNG
TzAwSDAvK3VCL3ZheW1HOHFCclU0OEkKLS0tIDY5anhYeTQ5RGxNUlZNRXg5Rm1o
QVk5dm5RaWpocUZrWk02Slg3N2lONjAKxWKAmAHt9x2T/9bh2mnQIF03ufffO9wF
79jffMh/3GyX5Pk0IbjMWwOn7ahQWOEgD58C1Lja2wpixLdwb0wgfA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
- recipient: age1hkve3khk7fthyrwxjqdf4r37lrqpmnkz6mke7psuphvu2ykynqaq9g6ja5 - recipient: age1hkve3khk7fthyrwxjqdf4r37lrqpmnkz6mke7psuphvu2ykynqaq9g6ja5
enc: | enc: |
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3UDNVSG9Fb01YSWJTdXRD YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhcUJUTFRrZmxiN1MrZkZB
UFB1dWhpRUFhWmMwTzdHeTNRdlg2YXd1ZnlnCndBRXBpMTJWdFRsMVNYeDBBY2g2 V2FjSlM5ZUxyUFZMKzRoYzY1M0plcmhjckJ3CjBhY0VRT2VMRUR2N01YZWZVRkJk
ZEZKTEw4dHpHSlFNT1BsSXQvaCs4MDQKLS0tIDg3YUlJYU1nUjRTTGtIeTJBVEhR VEdqSTNvLzNBOElZVVUxZ0VBekx6RnMKLS0tIHNtVlA4V1R2bkFBaVJMYkk3eUNm
SjZLWG4xNmxoSmtaTFZweEd3TDJ2QUkKcI4MdgglGFJT58ugHebiE6YQUehEomnH TjhQY0VoNU91Zi96VzZGaitsWHptT0UKZ3Vx/iqilkHrFkAbaSeJZNmSOzXvMDX6
qPZdH0SZAtJxBPqt78wJqvndR5INt5HBmLtXMDLLEk8o43lqfIkK5Q== HhcXrrq+sVjnq0XhOqWVY72h8Hp3d0JWA9VOxNQRyM9hdVENXur8YA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-03-21T22:00:22Z" lastmodified: "2024-07-03T23:02:46Z"
mac: ENC[AES256_GCM,data:wnRif4PVGh1P29ZXv1XPF4GdFFhrsRkYmdlun4WsLDFs0Y3xIjPQRScAbDzPnhY6vaiGKZfx0+RZHHMMFyVCz4bmo85MzGuF9H2QECBfWBNgCNCKXqz7pLQHA4c0u9jiatuc9PVc42RokJ+rITn1cWV9tLGot98ealpYkJbN91w=,iv:EL2Y5WZtWB6IRwnrGmWV5QO3XiPOB8IJkATbZTY1/oY=,tag:/z3ULuFshOw/ed+G3W8OmQ==,type:str] mac: ENC[AES256_GCM,data:SlmS0pn+nA2goHKojWRcz7VJJCoUXgunkP9jlZzh/BdeH9Jo1h1J4XRlejEKzD9Zi63EHlfPzsQXIrBO7CnxHDST+9roZc+24Yb552PKjF6aiMVTR+iRiYmHvSGCExvdHU9U2GWvF9WUmdtDan33TkmtvHlO9on9FG/iF/4sDG4=,iv:CY7xoR0lvRI40iudbtY1VZNem+37s5GCoEshLGa9y4U=,tag:1jzH2fQvl1QCsdjtSo2MzA==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.8.1 version: 3.8.1

View File

@@ -1,4 +1,52 @@
{ pkgs, nodes, ... }: { { pkgs, nodes, lib, ... }: let
certs = import ../deterministic-certs.nix { nixpkgs = pkgs; };
relayDomain = "relay.test.example.com";
rootCA = certs.selfSigned "liam-test" { ca = true; cert_signing_key = true; cn = "Liam test CA"; };
relayCert = certs.caSigned "liam-relay" rootCA {
ca = false;
signing_key = true;
encryption_key = true;
data_encipherment = true;
tls_www_client = true;
tls_www_server = true;
cn = relayDomain;
dns_name = relayDomain;
};
relayUser = "foobar@shelvacu.com";
relayPass = "asdfghjkl";
relayPassFile = pkgs.writeText "relay-password-file" "${relayUser}:${relayPass}";
testAgeSecret = "AGE-SECRET-KEY-1QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQPQQ94XCHF";
testAgeSecretFile = pkgs.writeText "test-age-key" testAgeSecret;
sopsTestSecrets = {
"dovecot-passwd" = (lib.concatStringsSep "\n" (map (name: "${name}:{plain}${name}::::::") [ "shelvacu" "julie" "mar" ])) + "\nbackup:::::::";
dkim_key = ''
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANn62hMdcFw4znAB
CKth6N4JD8XrNezCYbvyrUcVpGkkMX3TC9sEyZgGV6Y2Cs/J2Q6jKakC47nXebzV
Edk/kWsApj4J7PQl4t/G3vf1rdfICQx1pIspsmqQKsYugUG18EugEZzelai3+n4U
wqsed4551aRtwaws8dJQePOEEq1BAgMBAAECgYEAummKgXpVkqiJ8sMPlPEgYnHB
aXLjJNx/FGpOwVHCzp/DK2WG6ADKHhaecmgZCuYFmDz07bKo6U9arqBQqUdxpUor
JT2SS9RFP5MTsTB6R+eRqX8oMRQhcXB/+MczoSV/087vIZsL3L//6XoGyvjuHKW/
bvUR/F8PhB84uPU6RLkCQQDzXXj80iRhY6jHDwqoGf3BXd4O4cIAzPbBXN0W41fV
L5ZBm0K0KAgLnyjVygbsSn6lXsZXzAa/wAbSstMeCn7PAkEA5Uv88nfZSLU99XvF
WB9GD7lKXsAnWlf09F8hH4a1TH/zfGUCxrDdYNmdBdG6t0XuIVjay3TZcpW68Z2Q
lLeW7wJACj7KJCKYo3z1kwPAGBmYBDb2bTv11eDLFpLZP+hsPy5UrghiQ4FX7V1S
88Ugi3wLXtzhjrqpIhNsdhxPJPmeIwJAVpx8YE4a+hbT340v/thZS4ku6Vllw/9j
XIcuaM0mYE4Yd81j3g9in7mzUUZmY+H7UAdTJfTuShT6t1dQDIzIawJBAIJ+azsj
H5M2KsE3Nuxe3RODM/D4I5M5dngTkgNZQvUAywAyj9U39ZeFPEyXJyGkKNoR2CXB
hCvgabgr0wsi1y0=
-----END PRIVATE KEY-----
'';
relay_creds = "[${relayDomain}]:465 ${relayUser}:${relayPass}";
};
sopsTestSecretsYaml = pkgs.writeText "test-secrets-plain.json.yaml" (builtins.toJSON sopsTestSecrets);
sopsTestSecretsFolder = pkgs.runCommand "test-secrets-encrypted" {} ''
mkdir -p $out/liam
SOPS_AGE_KEY="${testAgeSecret}" ${pkgs.sops}/bin/sops --verbose -e --age "$(echo "${testAgeSecret}" | ${pkgs.age}/bin/age-keygen -y)" ${sopsTestSecretsYaml} --output-type yaml > $out/liam/main.yaml
'';
in {
name = "liam-receives-mail"; name = "liam-receives-mail";
nodes.ns = { lib, nodes, ... }: let nodes.ns = { lib, nodes, ... }: let
@@ -12,8 +60,9 @@
master = true; master = true;
file = pkgs.writeText "root.zone" '' file = pkgs.writeText "root.zone" ''
$TTL 3600 $TTL 3600
. IN SOA ns. ns. ( 1 8 2 4 1 ) . IN SOA ns. fake-hostmaster.example.com. ( 1 1 1 1 1 )
. IN NS ns. . IN NS ns.
${relayDomain}. IN A ${nodes.relay.networking.primaryIPAddress}
${lib.concatMapStringsSep "\n" ${lib.concatMapStringsSep "\n"
(node: "${node.networking.hostName}. IN A ${node.networking.primaryIPAddress}") (node: "${node.networking.hostName}. IN A ${node.networking.primaryIPAddress}")
(builtins.attrValues nodes) (builtins.attrValues nodes)
@@ -21,26 +70,61 @@
${lib.concatMapStringsSep "\n" ${lib.concatMapStringsSep "\n"
(d: '' (d: ''
${d}. IN A ${nodes.liam.networking.primaryIPAddress} ${d}. IN A ${nodes.liam.networking.primaryIPAddress}
${d}. IN MX ${nodes.liam.networking.primaryIPAddress} 0 ${d}. IN MX 0 ${d}.
${d}. IN TXT ( "v=spf1 mx -all" ) ; ${d}. IN TXT ( "v=spf1 mx -all" ) ;
${liam_config.services.opendkim.selector}._domainkey.${d}. IN TXT ( "v=DKIM1; k=rsa; " ${liam_config.services.opendkim.selector}._domainkey.${d}. IN TXT ( "v=DKIM1; k=rsa; "
"p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ+toTHXBcOM5wAQirYejeCQ/F6zXswmG78q1HFaRpJDF90wvbBMmYBlemNgrPydkOoympAuO513m81RHZP5FrAKY+Cez "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZ+toTHXBcOM5wAQirYejeCQ/F6zXswmG78q1HFaRpJDF90wvbBMmYBlemNgrPydkOoympAuO513m81RHZP5FrAKY+Cez0JeLfxt739a3XyAkMdaSLKbJqkCrGLoFBtfBLoBGc3pWot/p+FMKrHneOedWkbcGsLPHSUHjzhBKtQQIDAQAB" )
0JeLfxt739a3XyAkMdaSLKbJqkCrGLoFBtfBLoBGc3pWot/p+FMKrHneOedWkbcGsLPHSUHjzhBKtQQIDAQAB" ) '') '')
liam_config.vacu.liam.domains liam_config.vacu.liam.domains
} }
''; '';
}]; }];
}; };
nodes.relay = { lib, pkgs, config, ... }: let
mailpit = pkgs.mailpit;
dir = "/var/lib/mailpit";
in {
networking.firewall.enable = false;
users.groups.mailpit = {};
users.users.mailpit = {
isSystemUser = true;
home = dir;
createHome = true;
group = config.users.groups.mailpit.name;
};
systemd.services.mailpit = {
environment = {
MP_DATABASE = "${dir}/mailpit.db";
MP_SMTP_TLS_CERT = relayCert.certificatePath;
MP_SMTP_TLS_KEY = relayCert.privateKeyPath;
MP_SMTP_REQUIRE_TLS = "true";
MP_SMTP_BIND_ADDR = "0.0.0.0:465";
MP_SMTP_AUTH_FILE = "${relayPassFile}";
MP_UI_BIND_ADDR = "0.0.0.0:8025";
};
serviceConfig.ExecStart = "${mailpit}/bin/mailpit --smtp-require-tls";
# serviceConfig.Restart = "always";
serviceConfig.User = config.users.users.mailpit.name;
serviceConfig.Group = config.users.groups.mailpit.name;
serviceConfig.AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
wantedBy = [ "multi-user.target" ];
};
};
nodes.liam = { lib, ... }: { nodes.liam = { lib, ... }: {
imports = [ ../liam ]; imports = [ ../liam ];
vacu.underTest = true;
#systemd.tmpfiles.settings."69-whatever"."/run/secretKey".L.argument = "${testAgeSecretFile}";
systemd.services."acme-liam.dis8.net".enable = lib.mkForce false; systemd.services."acme-liam.dis8.net".enable = lib.mkForce false;
systemd.timers."acme-liam.dis8.net".enable = lib.mkForce false; systemd.timers."acme-liam.dis8.net".enable = lib.mkForce false;
systemd.services."acme-selfsigned-liam.dis8.net".wantedBy = [ "postfix.service" "dovecot2.service" ]; systemd.services."acme-selfsigned-liam.dis8.net".wantedBy = [ "postfix.service" "dovecot2.service" ];
systemd.services."acme-selfsigned-liam.dis8.net".before = [ "postfix.service" "dovecot2.service" ]; systemd.services."acme-selfsigned-liam.dis8.net".before = [ "postfix.service" "dovecot2.service" ];
# sops = lib.mkForce {}; vacu.secretsFolder = "${sopsTestSecretsFolder}";
vacu.secretsFolder = ./test_secrets; vacu.liam.relayhost = "[${relayDomain}]:465";
sops.age.sshKeyPaths = [ ./test_key ]; system.activationScripts.sopsHack.text = "ln -s ${testAgeSecretFile} /run/secretKey";
system.activationScripts.setupSecrets.deps = [ "sopsHack" ];
sops.age.keyFile = "/run/secretKey";
services.do-agent.enable = false; services.do-agent.enable = false;
virtualisation.digitalOcean = { virtualisation.digitalOcean = {
seedEntropy = false; seedEntropy = false;
@@ -52,7 +136,8 @@
services.dovecot2.enableDHE = lib.mkForce false; services.dovecot2.enableDHE = lib.mkForce false;
security.acme.defaults.email = lib.mkForce "me@example.org"; security.acme.defaults.email = lib.mkForce "me@example.org";
security.acme.defaults.server = lib.mkForce "https://example.com"; # self-signed only security.acme.defaults.server = lib.mkForce "https://example.com"; # self-signed only
networking.nameservers = lib.mkForce (lib.singleton nodes.ns.networking.primaryIPAddress); networking.nameservers = lib.mkForce [ nodes.ns.networking.primaryIPAddress ];
security.pki.certificateFiles = [ rootCA.certificatePath ];
}; };
nodes.checker = { pkgs, lib, ... }: { nodes.checker = { pkgs, lib, ... }: {
@@ -60,12 +145,15 @@
pkgs.wget pkgs.wget
pkgs.python311Packages.imap-tools pkgs.python311Packages.imap-tools
pkgs.python311 pkgs.python311
(pkgs.writeScriptBin "mailtest" '' (pkgs.writers.writePython3Bin "mailtest" { libraries = with pkgs.python3Packages; [ imap-tools requests ]; } ''
#!${pkgs.python311}/bin/python # flake8: noqa
import sys # #!${pkgs.python311}/bin/python
sys.argv.insert(1, "${nodes.liam.networking.primaryIPAddress}") import sys
sys.path.append("${pkgs.python311Packages.imap-tools}/lib/python3.11/site-packages") sys.argv.insert(1, "${nodes.liam.networking.primaryIPAddress}")
${builtins.readFile ./mailtest.py} #sys.path.append("${pkgs.python311Packages.imap-tools}/lib/python3.11/site-packages")
#sys.path.append("${pkgs.python311Packages.urllib3}/lib/python3.11/site-packages")
#sys.path.append("${pkgs.python311Packages.requests}/lib/python3.11/site-packages")
${builtins.readFile ./mailtest.py}
'') '')
]; ];
networking.nameservers = lib.mkForce (lib.singleton nodes.ns.networking.primaryIPAddress); networking.nameservers = lib.mkForce (lib.singleton nodes.ns.networking.primaryIPAddress);
@@ -83,13 +171,23 @@
liam.wait_for_unit("postfix.service") liam.wait_for_unit("postfix.service")
liam.wait_for_unit("dovecot2.service") liam.wait_for_unit("dovecot2.service")
relay.wait_for_unit("mailpit.service")
checks = """ checks = """
--submission --mailfrom me@shelvacu.com --rcptto foo@example.com --username shelvacu --expect-mailpit-received --mailpit-url http://${nodes.relay.networking.primaryIPAddress}:8025
--submission --mailfrom me@dis8.net --rcptto foo@example.com --username shelvacu --expect-mailpit-not-received --mailpit-url http://${nodes.relay.networking.primaryIPAddress}:8025
# mar's emails should NOT get sieve'd like mine
--rcptto mar@shelvacu.com --username mar --imap-dir INBOX
--rcptto mar+stuff@shelvacu.com --username mar --imap-dir INBOX
# test the sieve script is working # test the sieve script is working
--mailfrom whoever@example.com --rcptto sievetest@shelvacu.com --username shelvacu --imap-dir com.shelvacu --mailfrom whoever@example.com --rcptto sievetest@shelvacu.com --username shelvacu --imap-dir com.shelvacu
--rcptto shelvacu@shelvacu.com --username shelvacu --smtp-starttls --rcptto shelvacu@shelvacu.com --username shelvacu --smtp-starttls
--rcptto mar@shelvacu.com --username mar
--rcptto mar+stuff@shelvacu.com --username mar
--rcptto shelvacu@shelvacu.com --username shelvacu --rcptto shelvacu@shelvacu.com --username shelvacu
--rcptto julie@shelvacu.com --username julie --rcptto julie@shelvacu.com --username julie
--rcptto foobar@shelvacu.com --username shelvacu --rcptto foobar@shelvacu.com --username shelvacu
@@ -102,9 +200,14 @@
--mailfrom julie@shelvacu.com --expect-recipient-refused --mailfrom julie@shelvacu.com --expect-recipient-refused
--mailfrom @vacu.store --expect-recipient-refused --mailfrom @vacu.store --expect-recipient-refused
--submission --expect-recipient-refused --mailfrom julie@shelvacu.com --username shelvacu --submission --expect-recipient-refused --mailfrom julie@shelvacu.com --username shelvacu
--submission --expect-recipient-refused --mailfrom fubar@theviolincase.com --username shelvacu --submission --expect-recipient-refused --mailfrom fubar@theviolincase.com --username shelvacu
--submission --expect-recipient-refused --mailfrom fubar@vacu.store --username julie --submission --expect-recipient-refused --mailfrom fubar@vacu.store --username julie
--submission --expect-recipient-refused --mailfrom shelvacu@shelvacu.com --username mar
--submission --expect-recipient-refused --mailfrom me@shelvacu.com --username mar
--submission --expect-recipient-refused --mailfrom shelvacu+foo@shelvacu.com --username mar
--submission --expect-recipient-refused --mailfrom me+foo@shelvacu.com --username mar
--submission --mailfrom shelvacu@shelvacu.com --rcptto foo@example.com --username shelvacu --password shelvacu --expect-sent --submission --mailfrom shelvacu@shelvacu.com --rcptto foo@example.com --username shelvacu --password shelvacu --expect-sent
--submission --mailfrom shelvacu@shelvacu.com --rcptto foo@example.com --username shelvacu@shelvacu.com --password shelvacu --expect-sent --submission --mailfrom shelvacu@shelvacu.com --rcptto foo@example.com --username shelvacu@shelvacu.com --password shelvacu --expect-sent
@@ -112,6 +215,9 @@
--submission --mailfrom foo@vacu.store --rcptto foo@example.com --username shelvacu@shelvacu.com --password shelvacu --expect-sent --submission --mailfrom foo@vacu.store --rcptto foo@example.com --username shelvacu@shelvacu.com --password shelvacu --expect-sent
--submission --mailfrom foo@violingifts.com --rcptto foo@example.com --username julie --password julie --expect-sent --submission --mailfrom foo@violingifts.com --rcptto foo@example.com --username julie --password julie --expect-sent
--submission --mailfrom foo@violingifts.com --rcptto foo@example.com --username julie@shelvacu.com --password julie --expect-sent --submission --mailfrom foo@violingifts.com --rcptto foo@example.com --username julie@shelvacu.com --password julie --expect-sent
--submission --mailfrom mar@shelvacu.com --rcptto foo@example.com --username mar --password mar --expect-sent
--submission --mailfrom mar+stuff@shelvacu.com --rcptto foo@example.com --username mar --password mar --expect-sent
""" """
for check in checks.split("\n"): for check in checks.split("\n"):
check = check.strip() check = check.strip()
@@ -120,4 +226,4 @@
res = checker.succeed("mailtest " + check.strip()) res = checker.succeed("mailtest " + check.strip())
print(res) print(res)
''; '';
} }

View File

@@ -5,6 +5,7 @@ import time
import ssl import ssl
import argparse import argparse
import uuid import uuid
import requests
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument('host', type = str) parser.add_argument('host', type = str)
@@ -24,6 +25,9 @@ parser.add_argument('--expect-recipient-refused',
) )
parser.add_argument('--expect-sent', dest = 'expect', action = 'store_const', const = 'sent') parser.add_argument('--expect-sent', dest = 'expect', action = 'store_const', const = 'sent')
parser.add_argument('--expect-imap-error', dest = 'expect', action = 'store_const', const = 'imap_error') parser.add_argument('--expect-imap-error', dest = 'expect', action = 'store_const', const = 'imap_error')
parser.add_argument('--expect-mailpit-received', dest = 'expect', action = 'store_const', const = 'mailpit_received')
parser.add_argument('--expect-mailpit-not-received', dest = 'expect', action = 'store_const', const = 'mailpit_not_received')
parser.add_argument('--mailpit-url')
args = parser.parse_args() args = parser.parse_args()
@@ -41,6 +45,9 @@ if password is None:
if (username is None or password is None) and (args.submission or args.expect == 'received'): if (username is None or password is None) and (args.submission or args.expect == 'received'):
assert False, "Bad args" assert False, "Bad args"
if args.expect.startswith("mailpit_") and args.mailpit_url is None:
assert False, "Bad args"
msg_magic = str(uuid.uuid4()) msg_magic = str(uuid.uuid4())
def mk_ctx(): def mk_ctx():
@@ -68,6 +75,19 @@ except smtplib.SMTPRecipientsRefused:
else: else:
assert (not args.expect == 'recipient_refused'), "Server was supposed to reject this message, but it didn't" assert (not args.expect == 'recipient_refused'), "Server was supposed to reject this message, but it didn't"
if args.mailpit_url is not None:
time.sleep(3)
mails = requests.get(args.mailpit_url + "/api/v1/messages").json()
found_message = False
for message_data in mails["messages"]:
if msg_magic in message_data["Snippet"]:
found_message = True
break
if args.expect == 'mailpit_received':
assert found_message, "Message not received by mailpit server"
else:
assert not found_message, "Message was received by the mailpit server when it wasn't supposed to be"
if args.expect == 'received' or args.expect == 'imap_error': if args.expect == 'received' or args.expect == 'imap_error':
time.sleep(3) time.sleep(3)
try: try:
@@ -93,4 +113,4 @@ if args.expect == 'received' or args.expect == 'imap_error':
except imaplib.IMAP4.error as e: except imaplib.IMAP4.error as e:
assert args.expect == 'imap_error', f"IMAP error: {e}" assert args.expect == 'imap_error', f"IMAP error: {e}"
else: else:
assert not args.expect == 'imap_error', "Expected an IMAP error, but didn't get one" assert not args.expect == 'imap_error', "Expected an IMAP error, but didn't get one"

View File

@@ -1,4 +1,4 @@
dovecot-passwd: ENC[AES256_GCM,data:OPlQGFnkklEQvFpQM3jrdHB1p1zM+n76TCCaLmM/DOYlJ6W3+8bGt4i1JJq+FbA05RiX0Yhpv5s=,iv:R47TNT306RVrAPSRpK5TjUoWJF4nXnBvpDpIhwpdxWg=,tag:iKTUIoano0Bcxjkb2VQeuA==,type:str] dovecot-passwd: ENC[AES256_GCM,data:Ji41+n/7D90/O/LVM+3FDNACZ6jJPT6QYVIGWLujCheIY8m6vaRmMXzPCTgbK+njDOfIv7O2Sko15U4CYqWXAi3P43Np8GKRcv5+4NE=,iv:o6+tYBHSB3reRIqvFGB39wHk3G1L5VKmkj9Fiinnvnw=,tag:wggoNMvAYyJzkh73C3bMHw==,type:str]
dkim_key: ENC[AES256_GCM,data:nzujLrGttOL38d8mxglUcAQ9EO+sL2Gh75E4Wyt6siviFEpx5ZIpXkaC9XXmD2f6Ax4BHF8FTOB1cX0dLrRYp9gNOV007CsVUWpYf34H/J5bOUo1j+urYtbtA5Idu8FoUC3ENg5Ap4CId7jTtxQ9PlS9vTKQ2T2tIqmvXGE0t0aowUdJJdPfJLN1lMENY+/m9NxwArF06K/75BAX9LaxhNDzUHNwV9PK+htD9M1g0r7McbLtZpPut8tdkzOWGiUHIisPpXSTUk8LjrFY36DNngcXAyiRZtp6WrhINVABRKMVf92dYUQixpf6r7BkCkyRT60rAHz5UbWHI/saYHgXlH2OGK5hyZZ4JueAHU2Y7Hpvbw3UIG9jumdDcRda5W0WycJyGS4a5YZST907eDP4PuZayHOmp288Cuyc+kXOxvuCGjqiuZswokj4Ba4hIUUNJU1Ys4THYrf+j+iX0nKclGS+LXvqQI1cKUE3gBecxE2SW3BNzIOGh/ywO1kg2uZlUPpfGBr+Aupke/nULcGi2HVwX5EV47jpDyoqIEiVCy3OYSeQ2gkocIQ/y74fNMoud4kWmye8bAhprxVUHHes2TBjBb6QxQdmazjhAiCvgSI3p43QlSG2fqtQMcXMiANra1heRHHsOS8GKWk/ti9/k3/0YWycXcawYE8lpg/efpBPWkgWQ+NDUxcJBbWCKbkvA2DEfoSluwcGuxUjWGa27SKaCVX/LNAUDvXcw82F61XsTpoK2i0pme7pIZeF1bfbKyPxDnpWKoLoL2i2HchD1B5AEemr+eKh3kPGqpY3SNfqPFyUYN34Fea/gg/eM1Jw/ORWGNxMwg882a/NQLRzjjseQsPEI0r0o8Xba1KqGP1mMhursrOFVRz9xXG7l5oXhx0+GsscKDnP40CXJBMf6r2tEZobrR8NagV4/Mh4r2+zYw12KwwYZ5drmS1b0ftrLZLSugJopgLaQqYC3OAnmdW1MOkNoQSWv9Y5NaPERpMQ9BJcPcGM3W3+AyEz3zRSlFQFnjZO6kk37dFz1KVbbXkrFTXhDpGw/Z/RCMdzv6eyhPqcSSccisaOxDtlLQXy95G6tOcpJV7u7qu1LzQDehyZnBjasqMQVpCJw1Q9GRxnSBjpVKzN07dEkzXqcZHh67kPR/aoH8jzbfNq5YDQ6nxK0INcSyCzJe4w18JbY5Wq0F5U0OeYwYAwHoIV/nbMdptyyw==,iv:ol3dz4SomkwyN2s4tPWDCJEYdnMuZTvHppUA95Nz3+8=,tag:IlZBYvM8e3COjxZ/dxJT7Q==,type:str] dkim_key: ENC[AES256_GCM,data:nzujLrGttOL38d8mxglUcAQ9EO+sL2Gh75E4Wyt6siviFEpx5ZIpXkaC9XXmD2f6Ax4BHF8FTOB1cX0dLrRYp9gNOV007CsVUWpYf34H/J5bOUo1j+urYtbtA5Idu8FoUC3ENg5Ap4CId7jTtxQ9PlS9vTKQ2T2tIqmvXGE0t0aowUdJJdPfJLN1lMENY+/m9NxwArF06K/75BAX9LaxhNDzUHNwV9PK+htD9M1g0r7McbLtZpPut8tdkzOWGiUHIisPpXSTUk8LjrFY36DNngcXAyiRZtp6WrhINVABRKMVf92dYUQixpf6r7BkCkyRT60rAHz5UbWHI/saYHgXlH2OGK5hyZZ4JueAHU2Y7Hpvbw3UIG9jumdDcRda5W0WycJyGS4a5YZST907eDP4PuZayHOmp288Cuyc+kXOxvuCGjqiuZswokj4Ba4hIUUNJU1Ys4THYrf+j+iX0nKclGS+LXvqQI1cKUE3gBecxE2SW3BNzIOGh/ywO1kg2uZlUPpfGBr+Aupke/nULcGi2HVwX5EV47jpDyoqIEiVCy3OYSeQ2gkocIQ/y74fNMoud4kWmye8bAhprxVUHHes2TBjBb6QxQdmazjhAiCvgSI3p43QlSG2fqtQMcXMiANra1heRHHsOS8GKWk/ti9/k3/0YWycXcawYE8lpg/efpBPWkgWQ+NDUxcJBbWCKbkvA2DEfoSluwcGuxUjWGa27SKaCVX/LNAUDvXcw82F61XsTpoK2i0pme7pIZeF1bfbKyPxDnpWKoLoL2i2HchD1B5AEemr+eKh3kPGqpY3SNfqPFyUYN34Fea/gg/eM1Jw/ORWGNxMwg882a/NQLRzjjseQsPEI0r0o8Xba1KqGP1mMhursrOFVRz9xXG7l5oXhx0+GsscKDnP40CXJBMf6r2tEZobrR8NagV4/Mh4r2+zYw12KwwYZ5drmS1b0ftrLZLSugJopgLaQqYC3OAnmdW1MOkNoQSWv9Y5NaPERpMQ9BJcPcGM3W3+AyEz3zRSlFQFnjZO6kk37dFz1KVbbXkrFTXhDpGw/Z/RCMdzv6eyhPqcSSccisaOxDtlLQXy95G6tOcpJV7u7qu1LzQDehyZnBjasqMQVpCJw1Q9GRxnSBjpVKzN07dEkzXqcZHh67kPR/aoH8jzbfNq5YDQ6nxK0INcSyCzJe4w18JbY5Wq0F5U0OeYwYAwHoIV/nbMdptyyw==,iv:ol3dz4SomkwyN2s4tPWDCJEYdnMuZTvHppUA95Nz3+8=,tag:IlZBYvM8e3COjxZ/dxJT7Q==,type:str]
dkim_pub: ENC[AES256_GCM,data:tigMKTZ5XiDViSez2WKfUPBkw9OtLKrEBrbp/I3tUk+mu7RR2YIaQEWfTH0EOzPMpDEIJ32pwlqicGQZdTf7WdpELcJZgbxKpWPWgTzjwHasgs38aJh2JIIoIuFwa1YgEuRGtSl7YT47WDhTTGbFFdvaKBlIe7vipgkFSxNX1NKGNgdkkcVczvlVgWKqbp05zzUlav1XEwBhd+3eTgPQFptYyvQbIFasiunrHBT8cbm+CQ/O8q90lUkoVrmQUu3XG6njDMa4pNULUJqsUogCyYgm/aDMdx7AN29daCbgj99g/hjnQrBFajJCzNyG36XrzQdZJGiG0AgG1oWAq98boNFxC5ux4eBDmT946FyxXFNwyZpu1p2naHkBlE01duCBS4PUuQFlw9tsCYOuL+xGR3paBafTcL6X67w=,iv:lXFMxiePwivoyQxuQu+hEHeuU0z85fJk9y7296oJNl8=,tag:0QknKaFPpNHo2v0feR+jAQ==,type:str] dkim_pub: ENC[AES256_GCM,data:tigMKTZ5XiDViSez2WKfUPBkw9OtLKrEBrbp/I3tUk+mu7RR2YIaQEWfTH0EOzPMpDEIJ32pwlqicGQZdTf7WdpELcJZgbxKpWPWgTzjwHasgs38aJh2JIIoIuFwa1YgEuRGtSl7YT47WDhTTGbFFdvaKBlIe7vipgkFSxNX1NKGNgdkkcVczvlVgWKqbp05zzUlav1XEwBhd+3eTgPQFptYyvQbIFasiunrHBT8cbm+CQ/O8q90lUkoVrmQUu3XG6njDMa4pNULUJqsUogCyYgm/aDMdx7AN29daCbgj99g/hjnQrBFajJCzNyG36XrzQdZJGiG0AgG1oWAq98boNFxC5ux4eBDmT946FyxXFNwyZpu1p2naHkBlE01duCBS4PUuQFlw9tsCYOuL+xGR3paBafTcL6X67w=,iv:lXFMxiePwivoyQxuQu+hEHeuU0z85fJk9y7296oJNl8=,tag:0QknKaFPpNHo2v0feR+jAQ==,type:str]
sops: sops:
@@ -16,8 +16,8 @@ sops:
T3dqdEJxRmkvSStuK1NmRWJkN1psWWsKuNdc6DHXXEcn63CZv/5lE30MAagPfHO0 T3dqdEJxRmkvSStuK1NmRWJkN1psWWsKuNdc6DHXXEcn63CZv/5lE30MAagPfHO0
GDOLTLCLDzNvKmd5i9dNuYBrD1JeyotNId6E4w/3oYxCFJ56SsH32Q== GDOLTLCLDzNvKmd5i9dNuYBrD1JeyotNId6E4w/3oYxCFJ56SsH32Q==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
lastmodified: "2024-03-21T22:00:58Z" lastmodified: "2024-06-28T22:08:15Z"
mac: ENC[AES256_GCM,data:147XZroz5psp5Q5zGz19FZNPFr01wPGM0ivxbNVu9IcuUPw5dhnSaFQTvdYKfZPLSW2dwMJ2sPA5NAxxW0zQTh3d4vjirJ7GVj07Fn+ipL/X+wZKM42HjNSEw9IdAD5OIArZ8XjZcC+AGu7C4wHHf43uOEu7ZbWYx9Kbq+cJGbk=,iv:V9GHCN0NPWaRZOmoWhKA5fHwfKfrdays3ODfiTBrbo8=,tag:JwiHjHEjTDc6XRqtn0Aqwg==,type:str] mac: ENC[AES256_GCM,data:G7ceHgkxOv1xinx2Oc5kWCDs5njnf/uUyHlOddzM8RBZTcBp4RVB6NJb3ERFpHlEBXtO5EXnXm2ggK9cfxH9BKL/4tZeFQDqT9QcwFvtynQbCcOmBi3ffrkt4uXKwOIpVZyT8bz8GYueLq/fu2fIHwjZ7Ll43Gn2Sp6gQuvFSuo=,iv:wg88Qpn5cIIr9tXUkc/WxfMDt/SHbA09CRCCv/FwUVU=,tag:QiG5ERsym5kl2g11LK0onw==,type:str]
pgp: [] pgp: []
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.8.1 version: 3.8.1

View File

@@ -28,6 +28,7 @@
); );
in { in {
imports = [ ../triple-dezert ]; imports = [ ../triple-dezert ];
vacu.underTest = true;
systemd.services = disableAcmes // reEnableSelfsigned; systemd.services = disableAcmes // reEnableSelfsigned;
systemd.units = disableUnits; systemd.units = disableUnits;
#vacu.secretsFolder = ./test_secrets; #vacu.secretsFolder = ./test_secrets;
@@ -93,4 +94,4 @@
triple_dezert.wait_for_open_port(80) triple_dezert.wait_for_open_port(80)
triple_dezert.succeed("curl -vv http://shelvacu.com/ --resolve shelvacu.com:80:127.0.0.1") triple_dezert.succeed("curl -vv http://shelvacu.com/ --resolve shelvacu.com:80:127.0.0.1")
''; '';
} }