railbird-sf: add DuckDNS dynamic-DNS updater
Keep rocket-sense.duckdns.org pointed at this node's current public IP via a systemd oneshot + 5min timer that hits the DuckDNS update API with the source IP auto-detected. The residential WAN IP changes after ISP failover, which otherwise leaves the public hostname stale. Adds the agenix-encrypted duckdns-token secret and its key grant. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,11 @@
|
||||
file = ../secrets/org-api-ssh-key.age;
|
||||
mode = "0400"; # Restrictive permissions for SSH key
|
||||
};
|
||||
# DuckDNS token for the rocket-sense.duckdns.org dynamic-DNS updater below.
|
||||
age.secrets.duckdns-token = {
|
||||
file = ../secrets/duckdns-token.railbird-sf.age;
|
||||
mode = "0400";
|
||||
};
|
||||
|
||||
services.org-agenda-api-host = {
|
||||
enable = true;
|
||||
@@ -121,6 +126,40 @@
|
||||
|
||||
security.acme.certs."rocket-sense.duckdns.org".extraDomainNames = ["rbsf.tplinkdns.com"];
|
||||
|
||||
# Dynamic-DNS updater: keep rocket-sense.duckdns.org pointed at this node's
|
||||
# current public IP. The residential WAN IP changes (e.g. after an ISP
|
||||
# outage/failover), and without this the public hostname goes stale and the
|
||||
# site becomes unreachable until manually re-pointed. Leaving ip= blank tells
|
||||
# DuckDNS to detect the source IP of this request, so it always reflects
|
||||
# whatever connection the node is currently egressing through.
|
||||
systemd.services.duckdns = {
|
||||
description = "DuckDNS updater for rocket-sense.duckdns.org";
|
||||
after = ["network-online.target"];
|
||||
wants = ["network-online.target"];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
DynamicUser = true;
|
||||
LoadCredential = ["token:${config.age.secrets.duckdns-token.path}"];
|
||||
};
|
||||
script = ''
|
||||
token="$(cat "$CREDENTIALS_DIRECTORY/token")"
|
||||
resp="$(${pkgs.curl}/bin/curl -fsS --retry 3 --max-time 30 \
|
||||
"https://www.duckdns.org/update?domains=rocket-sense&token=$token&ip=")"
|
||||
echo "DuckDNS response: $resp"
|
||||
[ "$resp" = "OK" ] || { echo "DuckDNS update failed"; exit 1; }
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.timers.duckdns = {
|
||||
description = "Periodic DuckDNS update for rocket-sense.duckdns.org";
|
||||
wantedBy = ["timers.target"];
|
||||
timerConfig = {
|
||||
OnBootSec = "1min";
|
||||
OnUnitActiveSec = "5min";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
# Open the standard Syncthing sync/discovery ports on the host firewall.
|
||||
# Note: you may still need router/NAT port-forwards for inbound access from the internet.
|
||||
services.syncthing.openDefaultPorts = true;
|
||||
|
||||
58
nixos/secrets/duckdns-token.railbird-sf.age
Normal file
58
nixos/secrets/duckdns-token.railbird-sf.age
Normal file
@@ -0,0 +1,58 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 ZgrTqA dbWFiSzLK7bR7hT7GwIMNNvD8WnZreFfDrtcA+LY/BE
|
||||
OzTFip9dHKtI7EKWa/ati8LwVJJbSE6G3t6QFg4G6KQ
|
||||
-> ssh-ed25519 ZaBdSg VkV8WJLCadquI8PH6mlEhFyXnBBQLtBAyixQJqaOT2w
|
||||
xhyXTY215Vd8rWzkq8qD4rcHu3JjJh4wRG2+NGoYLnQ
|
||||
-> ssh-ed25519 MHZylw Mjfvi/elwLcWlNhCBfYulnV6DkYdM2en0uhJUXctfQk
|
||||
EspZ5/1PRZAEatU/Jh/s77aizKfQSpQ9ulipwCZS0tk
|
||||
-> ssh-ed25519 sIUg6g gMwhuJAx5lURu7nD3TeWw8v7n9Kmn8Na83J6iNye1U4
|
||||
FYtpIENIwosPhD4fOd8hjvbAYIhbJM+y+XiSeBjGIIM
|
||||
-> ssh-ed25519 TnanwQ ihbJQDgyaoiSq30PktEjTlcQlzrXNKVVVVAT29eSI2g
|
||||
ap3GKydDNX4nZC6mBaGC0BGFN0TveqcFOu91bbFJ2rs
|
||||
-> ssh-ed25519 cH4aug YUs7dBlvrWhWU3WYPvkN30ozOgqvoMGOz1R9TDiVJVg
|
||||
cuA4RDIc9m4og0zm+dd+3zO7OnbnI4Iisc/HCWEgQts
|
||||
-> ssh-ed25519 ggrAFQ o2eVPsHgVCD+3EnYTzjziiYeqViVTFlmTtpe0oGulgU
|
||||
+C2Yd50lkcXhQRnIu12EyY6U3Mjf8hAZZ33saicTWBo
|
||||
-> ssh-rsa gwJx0Q
|
||||
xaIephd6lidO23X/owa9Xn2SBqJxjjiaMoot/gn9gygTl9/TwvQ6g/XBXbuDjLkn
|
||||
LjSJ9cRoyYMbzv8z21rmtuNRibNCoMR75+zff4BMf6tPpzdrtVAw05edwYp5hxtg
|
||||
G9kv70WiLLah11Nn8ebluH1tMjbO4LKhy5chomielQ8yk27XBzRZS8M3Plmy2+za
|
||||
AlUeUOsk5ExYl4jjbkz6RsHSryThbQjrcEBBYT3MVFzE4btiNsdCVsW5qfugZLnh
|
||||
c9MSPzeDk5IrfNOZ35ZeFVUDkyrNuHno4VZKLp07I9mRPqLvvkOaAtIEcBag8agd
|
||||
W/D5O3idVNc64/tp4icckw
|
||||
-> ssh-ed25519 YFIoHA 7SE4NKISDqbR1aJmfLy3hXkPg12kUbiMShQ3hx+zOUw
|
||||
SGQOn5t7dtt3e3+s4cvnoDGRjViQmDccFJWMF4HGsY8
|
||||
-> ssh-ed25519 KQfiow LwUOPqeamtQ1i1RcxWEAtQDhHUny8kph4wmiRuPUnHs
|
||||
q7VAs48mMeonKEn8IdX97CgxOHjRbY0nIYUbOmmysII
|
||||
-> ssh-ed25519 kScIxg 4bEfbh/SnGsW8Kblr6Pzap1oobu+V+UsTeLHl4UAURs
|
||||
7/t8Mo1jpr8650s3w/4L9FEfHLR/sH90xsBWKVzI2As
|
||||
-> ssh-ed25519 HzX1zw qhd1iJVv4s7TbLAfVTqUTxxBaDsccDM/ypApAZcY5mE
|
||||
oanEYt0MN3pcemOUMX+8sE7XxHW8h/IZ4dxaBJXh8Pk
|
||||
-> ssh-ed25519 KQfiow IBfrzlbi++0rIa3A33S4gaFpBSOGAszqxeeFKLWpBjo
|
||||
yBB/8ZnsIe4lPIR0vRLDpuFFLFgSxcryV1KCON257fw
|
||||
-> ssh-ed25519 1o2X0w xUUvBiLbre/LWzHzMBbfE5unuO3UhGa7OcDi6rPy2Q8
|
||||
KEuttdevVM3gPbea8xwq375qwf8TtrBPt3DeUUNH3EY
|
||||
-> ssh-ed25519 KQ5iUA +h6kpwlMYc/Q4NbKpEsRCA6RjPpN5D1aV7eZeDFBDkk
|
||||
Frm74ENiTFXBu/CjGYT0jRuPVO9qgHw5zoV/TbIOjUo
|
||||
-> ssh-ed25519 AKGkDw aE1oI3u8LrY3XMymyoQUU5r5MyGDSpSMbcHtEZShwiU
|
||||
gY9V3AbkonUl4sLcdfwaUFe0xKQIRxsFv2fq8VG+U0M
|
||||
-> ssh-ed25519 0eS5+A zdhSEeS0/gD5WGTCmPK3jVraO/jzgRhwD0/qOHpz8GQ
|
||||
QldMBke5zXTlVodSeKF0B8MTzxYipQ9cX6/VoaEZVp4
|
||||
-> ssh-ed25519 9/4Prw JgMakHMTZyE7BNepkgTOGeMxkKcWEmUcq1CRm+IscyI
|
||||
A/0EJhNWgofrESAaH3x12QpQujJ/bIIm9iGdGb9KQGg
|
||||
-> ssh-ed25519 gAk3+Q EEorMwdbnlr3BsEdu9gg7jzivtnqzEPgGwZokSxGG2g
|
||||
d9pq1Rbz685QKjcEF0KH3mIKwIzwZIVFkl+ujtT20rU
|
||||
-> ssh-ed25519 X6eGtQ 7fWfLj6hTNYj1BxGPHlrcV9LdV75hYAAr+HXRT2GwWU
|
||||
PjfOl8mGOhxWRfIGSiZ0l8Z/MXO8P1iBQnBUF+bLLl0
|
||||
-> ssh-ed25519 0ma8Cw /FJJIBd2qfD2eNrXfDvd6cXxGeXbbYwSQktjyL1THQE
|
||||
Q/wv7dasqq5yXe6RQdlsfgqW4ibxPHoreee1xBHi5Gs
|
||||
-> ssh-ed25519 Tp0Z1Q fxdPsJ9c73yp6cU9UdAHX9YfF29U//wUCAucCBE44V4
|
||||
lfTkurTHTanPAO3VbYoGRYHoWZ+BlwIoHE8lhVeRqXk
|
||||
-> ssh-ed25519 ePNWZQ Qmc1C1keGmWgob+Xjh4kaVPAtDk6rG8PEvtdWFlbuxU
|
||||
vKVO5t6TK4aWvMPw3O8ALq2glenVHEGFEGtYgsGf0k8
|
||||
-> ssh-ed25519 hILzzA DgZif0MMn8xBc9b8qi0IrjsUAFrZW79Rx5aRIRQNXn4
|
||||
ULkpXlqF0/zEl/8urDRipv9ErbRhxXE1ipojjuu6+sI
|
||||
-> ssh-ed25519 qQi7yA EfyNuGZmnrRF+ikVpmaeyLRkiUzYsjNfovMlq1acTj0
|
||||
0LuL347kis91fjiCOFpViIoO92cp5dFXJ22CL1GMJes
|
||||
--- TwXaFhbbk8goUF8gbDnISLXupN+vmC9PgXoadMcVDaY
|
||||
<EFBFBD><EFBFBD>ϙCI<EFBFBD><EFBFBD>I<EFBFBD><EFBFBD><EFBFBD>kQ<EFBFBD>w<EFBFBD><EFBFBD>BU'<27><><EFBFBD>5<EFBFBD><35><EFBFBD><EFBFBD>CTX<54><58><EFBFBD>GU><1A>i<EFBFBD>8}<7D>;<3B><><EFBFBD>[%d<>;#<23>)<29>)<29>.$<24>[F
|
||||
@@ -18,6 +18,7 @@ in {
|
||||
"1896Folsom-k3s-token.age".publicKeys = keys.agenixKeys ++ keys.railbird-sf;
|
||||
"api_service_account_key.json.age".publicKeys = keys.agenixKeys;
|
||||
"k3s-registry.yaml.age".publicKeys = keys.agenixKeys ++ keys.railbird-sf;
|
||||
"duckdns-token.railbird-sf.age".publicKeys = keys.agenixKeys ++ keys.railbird-sf;
|
||||
"discourse-admin-password.age".publicKeys = keys.hostKeys;
|
||||
"discourse-secret-key-base.age".publicKeys = keys.hostKeys;
|
||||
"vaultwarden-environment-file.age".publicKeys = keys.hostKeys;
|
||||
|
||||
Reference in New Issue
Block a user