Skip to content

Commit bd478cd

Browse files
committed
eve: add cache2.thalheim.io with mTLS authentication
Set up an experimental mTLS-authenticated binary cache endpoint to test the nix client certificate authentication feature from NixOS/nix#13030. The setup uses clan vars to generate a self-signed CA and client certificate pair. Nginx is configured to require client certificate verification against this CA before proxying to the harmonia backend. This allows testing the new nix substituter options: tls-certificate=/path/to/client.crt tls-private-key=/path/to/client.key Tested with: nix copy --from 'https://cache2.thalheim.io?tls-certificate=~/.nix-mtls/client.crt&tls-private-key=~/.nix-mtls/client.key' /nix/store/i3zw7h6pg3n9r5i63iyqxrapa70i4v5w-hello-2.12.2
1 parent 4c46f02 commit bd478cd

14 files changed

Lines changed: 166 additions & 0 deletions

File tree

machines/eve/configuration.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
./modules/goatcounter.nix
4343
./modules/grafana.nix
4444
./modules/harmonia.nix
45+
./modules/mtls-cache.nix
4546
./modules/knot
4647
./modules/mastodon-hnbot.nix
4748
./modules/n8n
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
{
2+
config,
3+
pkgs,
4+
...
5+
}:
6+
{
7+
# mTLS binary cache for testing nix client certificate authentication
8+
# See: https://github.com/NixOS/nix/pull/13030
9+
#
10+
# Usage with nix (once PR is merged):
11+
# nix-store --store https://cache2.thalheim.io?tls-certificate=/path/to/client.crt&tls-private-key=/path/to/client.key -r /nix/store/...
12+
13+
# Generate CA and client certificates using clan vars
14+
clan.core.vars.generators.mtls-cache = {
15+
files = {
16+
# CA certificate and key - nginx needs to read the CA cert
17+
ca-cert.owner = "nginx";
18+
ca-key.secret = true;
19+
# Client certificate and key (for testing)
20+
client-cert = { };
21+
client-key.secret = true;
22+
};
23+
24+
runtimeInputs = [ pkgs.openssl ];
25+
26+
script = ''
27+
# Generate CA key and certificate
28+
openssl ecparam -genkey -name prime256v1 -out "$out/ca-key"
29+
openssl req -new -x509 -days 3650 -key "$out/ca-key" -out "$out/ca-cert" \
30+
-subj "/CN=cache2.thalheim.io CA"
31+
32+
# Generate client key and certificate
33+
openssl ecparam -genkey -name prime256v1 -out "$out/client-key"
34+
openssl req -new -key "$out/client-key" -out /tmp/client.csr \
35+
-subj "/CN=nix-client"
36+
openssl x509 -req -in /tmp/client.csr \
37+
-CA "$out/ca-cert" -CAkey "$out/ca-key" -CAcreateserial \
38+
-out "$out/client-cert" -days 3650
39+
rm -f /tmp/client.csr
40+
'';
41+
};
42+
43+
# Nginx virtual host with mTLS
44+
services.nginx.virtualHosts."cache2.thalheim.io" = {
45+
useACMEHost = "thalheim.io";
46+
forceSSL = true;
47+
48+
# mTLS configuration
49+
extraConfig = ''
50+
ssl_client_certificate ${config.clan.core.vars.generators.mtls-cache.files.ca-cert.path};
51+
ssl_verify_client on;
52+
'';
53+
54+
# Proxy to harmonia (same backend as cache.thalheim.io)
55+
locations."/".extraConfig = ''
56+
proxy_pass http://127.0.0.1:5000;
57+
proxy_set_header Host $host;
58+
proxy_redirect http:// https://;
59+
proxy_http_version 1.1;
60+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
61+
proxy_set_header Upgrade $http_upgrade;
62+
proxy_set_header Connection $connection_upgrade;
63+
64+
# Pass client certificate info to backend (optional, for logging/debugging)
65+
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
66+
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
67+
'';
68+
};
69+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../../sops/machines/eve
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"data": "ENC[AES256_GCM,data:9IdsUQqMCnSqPG3mGzR+0Z/iSHswE20bu98GyQI80WuW/pVdWEsQsz2RKd0WLpBfWhTRGvfdsW5aVuAyqCu+jAweM0aaf5pwSWvHDRhcl4JzTpZ4TqrJnZ3M+liN4knECQg8+rzuALgyoGKvB8FH5IsnpbCAM95hwJD1AsxlnWu0zkVsQi79KmFO2uCZ4V4V5z+rV47u4LvRaP/SP373fav/5z5d/ykrE40ZTQ5/4taNqfB23OQd+VR1LsUh6rS/COLmoSnw+u08d/IVYpvwQXeBGv5abuTUowP7ueeNj74UMYp2618bHDKMNa9ZIgHY8XYts0MsjdsB4TOl/K12KqoL0XdmwcoPVTp1J13LU/pT53DrDnQ4Vp6kBHakaBZwr5OlacmytGuCmm2V1fcHjkPlvfX5lWCB2DAQlJ2zokfQcSGA5fL5zP2RQQyJ0BCu0YRN0WcJyep6ME7UW9oVAXtz/amBe/sQyt8q9jLJmkIELDPmUNdaU2WoQcWroftygKbJ+RZssopiFjw89rwTSOzp+P2qFnY/NdU87eysQcEmG1mEBth8XyKJWY5pHf9DraMs73djEMc9p33EV/3k11VUbYYYuL6k0qBS7oKj3MkUMS2mtYbGpMY9hmM3rIR0SIdyaVApgFObYcEtM2NYBd0KWF+WM7TQmZI1SRNj++vqIQkbAD71i0qTtISa0Jrwk+pJxduHygtJTO7GF1d2C/glm9SejvLWzUBcBAYo63lC5vRK7EYI2/teW08SV9BfxYs+3wfGToFwr2Kr4/aLS1Y0Hk7FtpOiFLLta6RIxe21Vrs=,iv:Upo6s3M652KrWe25zLsevJkNBR+xBkkyklamk0BVq58=,tag:GXoBy15/4vzczAyx/X+L4A==,type:str]",
3+
"sops": {
4+
"age": [
5+
{
6+
"recipient": "age17n64ahe3wesh8l8lj0zylf4nljdmqn28hvqns2g7hgm9mdkhlsvsjuvkxz",
7+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBReUFpWlY2aFhuSXo0V3pY\neE94S04xVjZabWxHRnMyZHlGNWl2cGxrdHdzClNqakNPbUJRWDFFK2hmRjl5NkdP\nQnVNamF1ODJEVllzd3dhWnVQMHI5Q1kKLS0tIFE5eHJ1Sjc0QUhPSHg5SjQrbnhs\nbFZSK3h0ZFFyVWc5c3dmMk9JYWdkZFEKvxEHeHmqUxRVzFdRBTnG9Ua89FfFIZNR\nrWWp/cnGu72RLP9TXLqRaf86XXF9AfR7ZiE/MmrtERp/jtvDoOfHCQ==\n-----END AGE ENCRYPTED FILE-----\n"
8+
},
9+
{
10+
"recipient": "age1hjm3aujg9e79f5yth8a2cejzdjg5n9vnu96l05p70uvfpeltnpms7yy3pp",
11+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjL1VHaG1lM1gzdE11WHpz\nMThQL05SMU5tL1hsWUtSTzR6bDJnYlZwc0JBCmhwQTA3T250YWRTbUNxVk9raHFJ\nSE9qZUV3RjdBNXM2OFFvcUYvZ1htTEkKLS0tIGROcGR5bUpHN251bkRrZVdQK0E2\nc3IvU2tqMDdYN251SG82NGJvMlIvNXcKMpge6JRlEKl7ZNay6fAGhtO9fCwfhULt\nEFd78tIUcANvpG6ltAqtKcT6kTLHZFjX646Fv7i+2IN98JySYaIvKA==\n-----END AGE ENCRYPTED FILE-----\n"
12+
},
13+
{
14+
"recipient": "age1nnm255ah9wa4gpsaq0v023a75lnmlcxszt9lc6az3mtwzxgrucfq45rp7h",
15+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhZXNIVDhaZTkySTFqNXlm\ndllDUzloeXErZ04xZFVmVm9ZZ05yM1ZySWhrClAwTTM4dnZjNFNIcmlrQzh6SmZp\nY1RVTnpYRVhXQVlJd005N0RaY1NHY2MKLS0tIGF6Q2dKSGx5UHJPcU5DbklCTjdn\nR1NObHNjV0lVaU81N2VRSUFSbGQyN3MK5ytoOYfw/SV7n6cuFKYqcfSGNhwh+r2Q\nKnU3Qib36H0LQyZQ/4TX4xEpmsnVsBZsR0yhHtzJVl6s0uMgzLthAw==\n-----END AGE ENCRYPTED FILE-----\n"
16+
}
17+
],
18+
"lastmodified": "2026-01-25T13:48:18Z",
19+
"mac": "ENC[AES256_GCM,data:iZzaBmrEKX9eivoOPjf4LTViclHAZA/qfg8WW/aC+trb04M0r2Qho2oNWLa+DAWrK9rzT4Qd39Iw6ZsSIq4AKrHnO4XDaHBjPp0v+Hi1VJuPYr39gqO7TbhvZJQq6Am9qVP+xkXH2MPb6U3+Xf3bPERyid+FfBQcFBv/5Gp9p88=,iv:5TIgqcuEsQEtd3z+mmAMCmqhuIiyvYVQ/XPldw712VU=,tag:d8tgaQSyZDq9JjKPN2uV8g==,type:str]",
20+
"version": "3.11.0"
21+
}
22+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../../sops/users/joerg
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../../sops/machines/eve
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"data": "ENC[AES256_GCM,data:S/OEZkYq+8mradRB3fcjKqWBD5hWdXSNz/V3XBVoTE/ojsl6o6OOvUCzvNQGdwfUGr/ooPkZmxqQXRY8qwqagUAbAQVKQZCcR8BzRFk9TmSs5OtckuFe7/CK0pnuMES46lqhLsKicUu9DQy0pfj1GBJF0P6sbC/BJ3Xp7Ih5oqBJwJEPBiwVnL9HsrmnJwoGmBNwco1iHIbpee7+EKe0PtXuGz7b1BqOyl0biLcQvpoGHKGJKziki5txuuBLkBMI4WjIJyaqBFpbX/UMkpjaxTh5kiUaWG3++gDMu58dB+wOTvNsMvPiMkElKHaHJYUWiWD/4E/ELO/+wb1pyp7UXCwH+cfvbreCGb//5w+eHwiji3sFHKmEi1c81uBwmT1yakgFgbDfb1/jUR8tRyA=,iv:hWtRVY9M/tXksrAveGT3oWQYn7Xiz/937M/gyERLvRo=,tag:45/YPpnz6M5hrDNblBkhjw==,type:str]",
3+
"sops": {
4+
"age": [
5+
{
6+
"recipient": "age17n64ahe3wesh8l8lj0zylf4nljdmqn28hvqns2g7hgm9mdkhlsvsjuvkxz",
7+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGeHo1QWgwNjltQ0FCL0RP\nS1B6dFI1M3RGZHZWbWtqNUE0ajdyTFdFM2tvClp1SlR4SklQOTM2MzV3bHYvdFBr\ncCszSUlwc2VYRU9kZVBhNDR4aEF6Q0kKLS0tIHVsVU1mSEluOHJpMHJZTmVEeVAy\nLzR2bWhGRHNRQzNub1p0VGlsOVY4bzgKFXC+UT6YeIVEj7sm9kz1FzeYRcA41MFK\nThPfnxKOiAW79RuRoXk0Spne8yPFe7XRUs+ZkBH8C06Am4N948BwCA==\n-----END AGE ENCRYPTED FILE-----\n"
8+
},
9+
{
10+
"recipient": "age1hjm3aujg9e79f5yth8a2cejzdjg5n9vnu96l05p70uvfpeltnpms7yy3pp",
11+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGUEVhcEhnSnJwbEVnaUZy\nT0NaS3JDSGpJZEpoTS9jSTdHQ0lHd0NOZFRJCjMyeEhZV0VHZDNYOTN6bGxRcXhT\nVlJMaFdBd0EyVkN4OTU2bzdTc1Z3OXcKLS0tIHRIR2Y4ekpqaWFHNmEwcngzSk54\nbnZKVks2a1FlalpIWWNJcXB2Y2NkZUEKqKCxy7LB8iLKwRqiSl68L1BiFnmZnPw1\nRLDxy6jfwMx5zeWfwM+iHsHMneO5IfI/9hu7JLB9i/EUx5oC2WCYmQ==\n-----END AGE ENCRYPTED FILE-----\n"
12+
},
13+
{
14+
"recipient": "age1nnm255ah9wa4gpsaq0v023a75lnmlcxszt9lc6az3mtwzxgrucfq45rp7h",
15+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEbjJoTHFDUSs5N1AySkZV\nRjNnNjlVQ3hNcitqdUR2bUttaGhvMDJJVlNNCjBOcEZ2MXBDekx6M3NQSXdiZFFG\nZjE3ZnVKczBLUTg4bXRDVzl5aURnTzgKLS0tIDNmYk9aeFNPN2w2bVRkSURzVFZa\nRS9iWXF3cHNOSG5QZFczTXZhVExKMWcKEyPjDAtq4pEJEhbba/cnpL4G0nMO6VBw\nxS+3KmtHUZYd7CkRJoiFRZqpQ9RPWSCfsEXnN8c7LZ+TTaJ/LCJGdA==\n-----END AGE ENCRYPTED FILE-----\n"
16+
}
17+
],
18+
"lastmodified": "2026-01-25T13:48:19Z",
19+
"mac": "ENC[AES256_GCM,data:dHqLqyvmXqHDDXbkfVc9ugxYTaU0gJa76QEm+XpF8sGD2T3cEPrhTJUqucjxYjFoVltsbAQ4CS8QCIIhI5ydZTOW5onKdlZzyilQsuNpw8gQUYxoLVGmS0fVT0k0INczCFr/t5nQs91vVohG0FJJhs1LnOGiDuEtsgKd3KcbuKI=,iv:81X1YwBfz+wh6BA1oboPMZd22rtAIRucYdrbVD/JD3Q=,tag:iCCI3d/slGhdRo0Kaosilg==,type:str]",
20+
"version": "3.11.0"
21+
}
22+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../../sops/users/joerg
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../../../sops/machines/eve
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"data": "ENC[AES256_GCM,data:GLpCJ38v4aeGaHt/HvUxuhc5vZ1wo67u0B+LyNYnPLTETfPcZQVwTXXdXAlXxgV0+aYfcxcFEPZlx3tFOO37zgYUuKSfUq+SFz8VWtXCG9iAw6R2DRmIR6yJ3gOZF12Y65zQ+gXnIdjGc/Q0kDN69cZxh8zuHPwOFMpMZOIOyabM/OVemXT48Pr5/2isRRdR0kHok+hre4Qkod8/Vbhsu70sWVJBXwPwXCtXlk4ZPI3QzrAxDvOo08ctE5byamsJuFYrjF4UtmXkvH/I0yU0DPgXA5/Cms3siS8D8e6owkBj+Ai/8H761o7pFHFVyKGiKivrZJehgGUYasVl7lV3ZBUJx4m0mpPah1RQMPF2dnkusyuG1rgflt0M/0D0EOziVr8d8qDx5aGtZWpzg7oI4UQZByUM3Dj+LiPuvGMgE5rlV22WP8uDPls53+DhF5WJysCjpoW2WtTeUOwqt1datm89ncr3agvuJNzlGE6PY/EJHLy8yvcQTGmsyD6Y84c3GqmhdLpgMnltm9GV4PXVyS8U2dHL6yYoGBK+3LGFTQ5GX5CTLrvq9+fdPSrJ68TS3BOOf+fKYHUaDKkEnmPkfCORxMiJmuJ8Gvuv3Pprv/ExaQU8BYA8IBjYlVuOvEdGNC6dhVJCpnewg8SbYbZB6Tpu2Iq9mMiSiowSKz3kPrWkgz4z3/vYmWbCIDLQqXORFnkQZmL/mjSyb1x86f9KKgHy5E/km46+atmHPUHrD5SB8sOrlacVx/t8Q4lvBw==,iv:XyKhUawB6oXDKdIS7dggjZa8YWvhwMDDauf1W1HncxU=,tag:R6eWoEt+OPn0XVZ/BlolwA==,type:str]",
3+
"sops": {
4+
"age": [
5+
{
6+
"recipient": "age17n64ahe3wesh8l8lj0zylf4nljdmqn28hvqns2g7hgm9mdkhlsvsjuvkxz",
7+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4blI2K3BaNGd2MG5hQ1Aw\nbWg2WWpKRm5aaG5VdUhseDB2NjJsd3p0Z1JBClEzWEswSHRYRUZJQ1l1NnhQTGMr\nTDdNbWRXblhjL2toMTNNODJBSkVyVDQKLS0tIDlMOUFaczl6VkdiVmg2SFF1ajI1\nVldnc2Q1WWUvdVhWZmh6NWZQdWhBYjAKPqL/Oswdf1iR6JWUllbxihm9dFefyx41\nFNh40Ie3WnXngPz5KRRccCO99psqy7qqLjrAqFOZg9m9JP25jYJPxQ==\n-----END AGE ENCRYPTED FILE-----\n"
8+
},
9+
{
10+
"recipient": "age1hjm3aujg9e79f5yth8a2cejzdjg5n9vnu96l05p70uvfpeltnpms7yy3pp",
11+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwWS8rU2lHTnRVNGdKVTlh\naG9BamlHVWlDM09HQWtUNnlqWVFJNGpWNVVvCnc0b1JHVXJXdlc3MEpJb3dZckFT\nMXA4SUtxNXlZbjBEWWZHa1ZLa3I3eUkKLS0tIHcrMzlBaG1BVy9LRGVzbURzSjh0\nK2Z3Y2J0VFhsWXRwWGlLQ05ldHc1dGsKOH5tkuhvzOMNuZwu1xabrRWroNZfFAi4\nvC4Zg715I5AjfJHd/QcYMxg1LacCRE+l9L4PCe1pEVxi4wjsGVZZFQ==\n-----END AGE ENCRYPTED FILE-----\n"
12+
},
13+
{
14+
"recipient": "age1nnm255ah9wa4gpsaq0v023a75lnmlcxszt9lc6az3mtwzxgrucfq45rp7h",
15+
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjUVhQN2dDeGNVSmhoK05u\nTTNsbVRmZjd5QUVlanpnV2UybFp3eVhRckdFClRxNm1YUFJ4NmFwSHI5THhvUGdt\ncFNaT3ZRZ0ppanBLb0g1WnVIanJMS1UKLS0tIC81bXRRTkJmZnJUL1hRQ0duNnVz\nM05nN1pGRFRQTG03czJOZ1FRNGw5OXcKrMkVJWBIzMvl2ZKzsWIdb5eDWyUCXfYs\nojpyqyKpKxDTvg3l1Drt9cEmVmBf8yDa0udBCBbkSTF2LE8C9CqDnA==\n-----END AGE ENCRYPTED FILE-----\n"
16+
}
17+
],
18+
"lastmodified": "2026-01-25T13:48:19Z",
19+
"mac": "ENC[AES256_GCM,data:pM1r5i1J6S5S+tUhxOdVhtZAcPPWAdi/cUrszNN9VHA79TMGLiJSkAY9mIrDT8f0fO8te8VNkd7rDGehO1G0BsKdDHnnkzTm66hd4WpJQmHE2GDQmkjBuizfNEItjOnZ6LawLEmTNGblMSUgQ/7ktNor3i54Lka+9S+NQt6+NQQ=,iv:kD/+zTZ7OS5zlcKdTbqKwttBb71HjCWjZNmMWZNdzz4=,tag:IRKkKkQIFofQjxJqLvvPww==,type:str]",
20+
"version": "3.11.0"
21+
}
22+
}

0 commit comments

Comments
 (0)