mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 11:02:47 +00:00
Hotfix/duckdns token (#8)
* fix: source DuckDNS token from Vault * chore: rotate DuckDNS Vault token
This commit is contained in:
committed by
GitHub
parent
54e2917062
commit
24268938bd
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# DuckDNS runtime files contain a rendered Vault token and must stay on the host.
|
||||||
|
/dotfiles/server/duckdns/
|
||||||
@@ -53,6 +53,7 @@ Ansible-driven personal infrastructure repo for Fedora and Void desktops, Fedora
|
|||||||
- AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff`
|
- AI coding agents: `ansible-playbook ansible/site.yml --limit <host> --tags ai_agents --check --diff`
|
||||||
- Mail bootstrap: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh`
|
- Mail bootstrap: `sh -n scripts/bootstrap_mail.sh` and `shellcheck scripts/bootstrap_mail.sh`
|
||||||
- Server compose render: `docker compose -f /opt/docker/server/docker-compose.yml config`
|
- Server compose render: `docker compose -f /opt/docker/server/docker-compose.yml config`
|
||||||
|
- DuckDNS config only: `ansible-playbook ansible/site.yml --limit prometheus --tags duckdns --check --diff`
|
||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
- Use FQCN Ansible modules.
|
- Use FQCN Ansible modules.
|
||||||
@@ -96,6 +97,10 @@ The dotfile vars follow the same split: `desktop_common_dotfiles` carries mode-i
|
|||||||
- Windows applications are installed manually and are not managed from the WSL profile.
|
- Windows applications are installed manually and are not managed from the WSL profile.
|
||||||
|
|
||||||
## Rocky Server Notes
|
## Rocky Server Notes
|
||||||
|
- DuckDNS is rendered by `profile_server` from host-local `server_duckdns_domain` and
|
||||||
|
`vault_duckdns_token`. Keep the rotated token in encrypted Vault or untracked local vars, never in
|
||||||
|
dotfiles. The private `~/duckdns/duck.sh` keeps the existing entrypoint; rendering uses `no_log`
|
||||||
|
and disables diffs. Provisioning does not execute the updater or change its external schedule.
|
||||||
- `rocky_server` is a child of both `platform_rocky` and `server`; `prometheus` is its active target.
|
- `rocky_server` is a child of both `platform_rocky` and `server`; `prometheus` is its active target.
|
||||||
- The target must already provide `server_username` with local sudo access before the profile runs.
|
- The target must already provide `server_username` with local sudo access before the profile runs.
|
||||||
- The Rocky profile installs Docker CE, uses firewalld, preserves SELinux enforcement, and renders the
|
- The Rocky profile installs Docker CE, uses firewalld, preserves SELinux enforcement, and renders the
|
||||||
|
|||||||
19
README.it.md
19
README.it.md
@@ -184,6 +184,25 @@ Lo stato attuale del profilo server include:
|
|||||||
- attivazione di firewalld con servizio SSH esplicitamente abilitato
|
- attivazione di firewalld con servizio SSH esplicitamente abilitato
|
||||||
- Syncthing escluso dal profilo server Rocky
|
- Syncthing escluso dal profilo server Rocky
|
||||||
|
|
||||||
|
### DuckDNS
|
||||||
|
|
||||||
|
`profile_server` genera `~/duckdns/duck.sh` con permessi `0700`, mantenendo il percorso dello
|
||||||
|
script e `duck.log`. Definire `server_duckdns_domain` negli host vars del server e salvare il
|
||||||
|
**nuovo token rigenerato** in `vault_duckdns_token`, nel Vault cifrato `secrets/vault.yml`
|
||||||
|
(`ansible-vault edit secrets/vault.yml`) oppure negli override non versionati `secrets/vault.local.yml`.
|
||||||
|
Non committare lo script generato e non passare il token sulla riga di comando. Il rendering
|
||||||
|
nasconde output e diff sensibili; lo script verifica TLS e passa il token a curl tramite stdin.
|
||||||
|
Il playbook non esegue lo script e non modifica la sua schedulazione esterna.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook ansible/site.yml --limit prometheus --tags duckdns --check --diff
|
||||||
|
ansible-playbook ansible/site.yml --limit prometheus --tags duckdns
|
||||||
|
```
|
||||||
|
|
||||||
|
La cancellazione dalla cronologia non revoca il token: rigenerarlo sul pannello DuckDNS.
|
||||||
|
Dopo la bonifica, riclonare gli altri checkout senza unire nuovamente la vecchia storia;
|
||||||
|
salvare separatamente eventuali modifiche non committate senza copiare segreti.
|
||||||
|
|
||||||
### Migrazione dati
|
### Migrazione dati
|
||||||
|
|
||||||
Dopo il provisioning Rocky, eseguire `scripts/migrate_prometheus_data.sh` **sul server Ubuntu
|
Dopo il provisioning Rocky, eseguire `scripts/migrate_prometheus_data.sh` **sul server Ubuntu
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -120,6 +120,24 @@ ansible-playbook ansible/site.yml --limit prometheus \
|
|||||||
|
|
||||||
The target must already provide `server_username` with local sudo access.
|
The target must already provide `server_username` with local sudo access.
|
||||||
|
|
||||||
|
### DuckDNS
|
||||||
|
|
||||||
|
`profile_server` renders `~/duckdns/duck.sh` with mode `0700`, keeping the existing updater path
|
||||||
|
and `duck.log`. Set `server_duckdns_domain` in the server's host vars and store the **rotated**
|
||||||
|
`vault_duckdns_token` in encrypted `secrets/vault.yml` (using `ansible-vault edit secrets/vault.yml`)
|
||||||
|
or untracked `secrets/vault.local.yml`. Never commit the rendered script or put the token on a
|
||||||
|
command line. Rendering hides secret output/diffs; the updater verifies TLS and passes the token
|
||||||
|
to curl through stdin. The playbook neither runs the updater nor changes its external schedule.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible-playbook ansible/site.yml --limit prometheus --tags duckdns --check --diff
|
||||||
|
ansible-playbook ansible/site.yml --limit prometheus --tags duckdns
|
||||||
|
```
|
||||||
|
|
||||||
|
An exposed token must be revoked/regenerated on DuckDNS: deleting it from Git history does not
|
||||||
|
revoke it. After a history cleanup, re-clone other checkouts rather than merging the old history
|
||||||
|
back in; preserve any uncommitted work separately without copying secrets.
|
||||||
|
|
||||||
### Data migration
|
### Data migration
|
||||||
|
|
||||||
Provision Rocky first, then run the migration script **on the retired Ubuntu source host**. It is
|
Provision Rocky first, then run the migration script **on the retired Ubuntu source host**. It is
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ server_dotfiles:
|
|||||||
- src: .themes.gitignore
|
- src: .themes.gitignore
|
||||||
dest: .themes.gitignore
|
dest: .themes.gitignore
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
- src: duckdns/
|
|
||||||
dest: duckdns/
|
|
||||||
mode: preserve
|
|
||||||
|
|
||||||
server_templates:
|
server_templates:
|
||||||
- src: server/.gitconfig.j2
|
- src: server/.gitconfig.j2
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ ansible_port: 22
|
|||||||
ansible_ssh_private_key_file: /home/fscotto/.ssh/id_ed25519
|
ansible_ssh_private_key_file: /home/fscotto/.ssh/id_ed25519
|
||||||
|
|
||||||
server_username: rocky
|
server_username: rocky
|
||||||
|
server_duckdns_domain: fscotto
|
||||||
|
|||||||
33
ansible/roles/profile_server/tasks/duckdns.yml
Normal file
33
ansible/roles/profile_server/tasks/duckdns.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
- name: Require DuckDNS domain and Vault token before deployment
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- >-
|
||||||
|
server_duckdns_domain | default('') is
|
||||||
|
regex('[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?', match_type='fullmatch')
|
||||||
|
- >-
|
||||||
|
vault_duckdns_token | default('') is
|
||||||
|
regex('[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', match_type='fullmatch')
|
||||||
|
fail_msg: >-
|
||||||
|
Define server_duckdns_domain in host_vars and the rotated vault_duckdns_token
|
||||||
|
in encrypted Vault or an untracked local vars file before deploying DuckDNS.
|
||||||
|
no_log: true
|
||||||
|
|
||||||
|
- name: Ensure private DuckDNS directory exists
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ server_user_home }}/duckdns"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ server_username }}"
|
||||||
|
group: "{{ server_user_group }}"
|
||||||
|
mode: "0700"
|
||||||
|
|
||||||
|
- name: Render DuckDNS updater with the Vault token
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: duck.sh.j2
|
||||||
|
dest: "{{ server_user_home }}/duckdns/duck.sh"
|
||||||
|
owner: "{{ server_username }}"
|
||||||
|
group: "{{ server_user_group }}"
|
||||||
|
mode: "0700"
|
||||||
|
validate: /bin/sh -n %s
|
||||||
|
no_log: true
|
||||||
|
diff: false
|
||||||
@@ -18,6 +18,10 @@
|
|||||||
Server container secrets are missing. Define vault_navidrome_db_password and
|
Server container secrets are missing. Define vault_navidrome_db_password and
|
||||||
vault_postgres_root_password in secrets/vault.yml or another vars source.
|
vault_postgres_root_password in secrets/vault.yml or another vars source.
|
||||||
|
|
||||||
|
- name: Configure DuckDNS updater
|
||||||
|
tags: [dotfiles, dotfiles:server, duckdns]
|
||||||
|
ansible.builtin.import_tasks: duckdns.yml
|
||||||
|
|
||||||
- name: Ensure server directories exist
|
- name: Ensure server directories exist
|
||||||
tags: [dotfiles, services]
|
tags: [dotfiles, services]
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
|
|||||||
24
ansible/roles/profile_server/templates/duck.sh.j2
Normal file
24
ansible/roles/profile_server/templates/duck.sh.j2
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Managed by Ansible. Contains a Vault token; never copy this file into Git.
|
||||||
|
set -eu
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
log_file={{ (server_user_home ~ '/duckdns/duck.log') | quote }}
|
||||||
|
|
||||||
|
# Keep the token out of process arguments and verify the HTTPS certificate.
|
||||||
|
if ! response=$(curl --fail --silent --show-error --connect-timeout 10 --max-time 30 --config - <<'DUCKDNS_CONFIG'
|
||||||
|
url = "https://www.duckdns.org/update?domains={{ server_duckdns_domain }}&token={{ vault_duckdns_token }}&ip="
|
||||||
|
DUCKDNS_CONFIG
|
||||||
|
); then
|
||||||
|
printf 'ERROR\n' > "$log_file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$response" in
|
||||||
|
OK) printf 'OK\n' > "$log_file" ;;
|
||||||
|
*)
|
||||||
|
printf 'KO\n' > "$log_file"
|
||||||
|
printf 'DuckDNS update failed.\n' >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
tags: [always]
|
tags: [always]
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
file: "{{ playbook_dir }}/../secrets/vault.yml"
|
file: "{{ playbook_dir }}/../secrets/vault.yml"
|
||||||
|
no_log: true
|
||||||
when: >-
|
when: >-
|
||||||
lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.yml',
|
lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.yml',
|
||||||
errors='ignore', wantlist=True) | length > 0
|
errors='ignore', wantlist=True) | length > 0
|
||||||
@@ -15,6 +16,7 @@
|
|||||||
tags: [always]
|
tags: [always]
|
||||||
ansible.builtin.include_vars:
|
ansible.builtin.include_vars:
|
||||||
file: "{{ playbook_dir }}/../secrets/vault.local.yml"
|
file: "{{ playbook_dir }}/../secrets/vault.local.yml"
|
||||||
|
no_log: true
|
||||||
when: >-
|
when: >-
|
||||||
lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.local.yml',
|
lookup('ansible.builtin.fileglob', playbook_dir + '/../secrets/vault.local.yml',
|
||||||
errors='ignore', wantlist=True) | length > 0
|
errors='ignore', wantlist=True) | length > 0
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
OK
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
echo url="https://www.duckdns.org/update?domains=fscotto&token=d173a037-8a10-4e40-8d9d-bebedbdde086&ip=" | curl -k -o ~/duckdns/duck.log -K -
|
|
||||||
@@ -1,40 +1,45 @@
|
|||||||
$ANSIBLE_VAULT;1.1;AES256
|
$ANSIBLE_VAULT;1.1;AES256
|
||||||
65623833316230316230376465656261383230643661393032396462643232383334383236653134
|
62633966363435396136666635303362663932366464323231363563373462383134326361346533
|
||||||
3964353234623165633736303035623132643565393461660a323930623462323635613361373836
|
3465353461326565356435633866393230383838356235340a333036383038653134323066663031
|
||||||
37613164656538353734333932326136303532346161663238613466616236636432346534626331
|
37373135643331356366373831343163363835656462343962636538623937356231376337616330
|
||||||
3434663266366637650a336235363033333562626135333962626265666332386261643666306638
|
3831626261343761310a306133633264613430613165343265303664383439333230663665333231
|
||||||
64343262353661346435326662633833656533643464653665356233316466333432303536356539
|
30393934323438333066383737663665316634613932353232343334626261636661393434646163
|
||||||
32623430303663616261386636613534326231613366636536303761646335396132623231336361
|
63316537383866353338353261373161623562343037383032633932383630666339633234326639
|
||||||
61656337313766353533643266396230626439353033373630666336616230316362616135323462
|
64303735663532376433393464616230616236353134383734623132333061356664613039323265
|
||||||
30306633373234386639633932393437323931613739383135353835393630623937636639343338
|
35373434336261313438633866643765323330623336343732346465613264613666616631303633
|
||||||
35636530643330376538393262383738333735656230363633383463386366343065633961663562
|
31333437623437626135623032306434306538323461623161336431353630336539646531313365
|
||||||
37653264326565376166666262643136616333656233386564333030663532353836306131316530
|
30356330356438353037663262643463363636386162393764323133373261376263663338636333
|
||||||
62633738306434303236623239646638613230323434393761656265393064373235333435393264
|
33336537383061643234356365653137333639623863303530666665373663376166316533623737
|
||||||
36363936336330636433643133346164643733356239616530653831626165316238643834356236
|
31616262363132326133666230396636663035343432633830323430336332326261613932633837
|
||||||
36333262313764653137633930663131306132306434376433306230306564366633363738313634
|
62303232306331663936366435666164383335313335326662663363643563643938623739386663
|
||||||
35316230623134623932396132316530366662643366643439643334366233646334633764346266
|
65356431353362623634333437346566363166366161313132653131613861386437306562633934
|
||||||
35373764633138343235323931346134613265356238616138323134326338633335336339313862
|
38306135636161366530303461636665386639396639356265323361623639616265323462333534
|
||||||
61653939366263386431636334333661306538643166353661336561396365366434353830643465
|
61626439616631356532353437653539333631636265346238653439313130326239633035613130
|
||||||
31626136626336633363653531363064643534396336623331363130313966653966373636663232
|
65366161356231356638313633393735356465393339343034356138316366656431336435386437
|
||||||
65653132363139653239383636333861323435613362666637366162323062376139633033373563
|
36366339366463396638303062366263356436666232393437613766623631313264646565316534
|
||||||
66656134313931313965303134613836383534636438363936353836326639346565653031363839
|
32373534366363373737616563616161346265323936336665653934656365323731633637376331
|
||||||
63623738366261363734376536646532396231616233303061363364383238616434333366613933
|
31336262356632313533393366346565373434373134653630303431643037363561613830663339
|
||||||
63616539613336393863633361303466353738313666393164343638373530376666663666666235
|
39313837356362643164386432653030306132643234303162363463376130666239653461623736
|
||||||
33666234353736633335343639623664326566333162333539636235346663663737366432366665
|
65333734303532356462636538326430353831336562666563336333323764346234643037373064
|
||||||
66373831303666666533343234373466333132343135326261663532663062313939623963383437
|
63343533386564356232633661346232666135393365323133323365663637373261396264333432
|
||||||
34653732653830313638343631313437623931623531323566306232373165636662316633333438
|
64616463643931653162373666323731653635616633386231653863623830666637623638353062
|
||||||
66666537623966623932323463323330316337613637383339613637653637333832623965636434
|
61363339613364343239363336626266386561343032333262396436663736353835303863643865
|
||||||
34653330336663323263353636353139323337646166623862343565646637616136646232373633
|
35616136363830326661383066316537633537616565343361633036373163316566653638343638
|
||||||
33356134373464646664303865353763323531383661323930353038646333386366353665396431
|
33323162376537353961383965666165663631396663356533643432356630396435356636366636
|
||||||
64303739643735376235626134663566343165646433393966373961393738323036353437346436
|
32363264303633656335333335356166323164386338363437663435336635643334646532616539
|
||||||
66656166306561353637623462303039393465363261343164393062643130383736623261383232
|
66646336393834613337336661336638613463626230336132386265396165656461623533333738
|
||||||
38623036626464613138363635646233323737653137633830316138663835656633336663626338
|
33353063306336623463396130386335383338383861376330616566643638333230303862356462
|
||||||
33386232633862616432396662343738343462623263303337393533313264396637356134373739
|
63356464313263666538306230636363643665643933323236363864303634343539326239363134
|
||||||
61323266623665353631316461633462646536386266343934356235363065653162363566623661
|
65376231623836363730376631303032393330326362383438373434383633656134373539653461
|
||||||
35643332303333306362303538333034316461326363653632313765396664643533373862333533
|
38306632636463346365396131316234623736626335633361663861316437326635633237346262
|
||||||
37306536356465393933366238663031653630386239383839316365323761316236326330306637
|
38643730666130656335663232366362333164353433613731363131366138633766623433363031
|
||||||
36373434643864343064646437323736393330326361663231373933613864303339653661616139
|
37613337383961386661393733623238393062663065663931313231366366626261666336656134
|
||||||
36356134636136333830663031656132656237383331663362313238653133366538323462376632
|
63646237643864643462653337306462646631663433663461343764306163646466326334323335
|
||||||
63373766383939656265313934636462626633376162623931333363393837303336363036303439
|
61396162353032633937333066313438333461376161666166336337356430373737313266363238
|
||||||
32643730383735383535633439326564376261343937343934366366373039653761383934316162
|
63633365613331636234333765633536653639343234396262653438353132623239303431316134
|
||||||
383035326562353431616536646238323164
|
35663930323535373830313766353630636237343330346232316637336531336466326564306630
|
||||||
|
62356639356330396465353432333135313130653366303931616165663638633461613961643766
|
||||||
|
62633564666566616665366336396436386330323536356633323965343566396232303434666534
|
||||||
|
33333636313136326535303136643265393834613733343362346333336339636437353236326161
|
||||||
|
65633230656531633238623830343432663365313532343435623133636239333763633930316666
|
||||||
|
34363535313731666432
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
vault_duckdns_token: "CHANGEME"
|
||||||
vault_personal_full_name: "REPLACE_ME"
|
vault_personal_full_name: "REPLACE_ME"
|
||||||
vault_git_email: "REPLACE_ME"
|
vault_git_email: "REPLACE_ME"
|
||||||
vault_git_signing_key: "REPLACE_ME"
|
vault_git_signing_key: "REPLACE_ME"
|
||||||
|
|||||||
Reference in New Issue
Block a user