diff --git a/roles/dns-registrierung/defaults/main.yml b/roles/dns-registrierung/defaults/main.yml new file mode 100644 index 0000000..91b9afa --- /dev/null +++ b/roles/dns-registrierung/defaults/main.yml @@ -0,0 +1,21 @@ +# Standardwerte für die DNS-Registrierung + +# Modus: "install" oder "remove" +# Wird in Semaphore als Variable übergeben (z. B. -e dns_registrierung_modus=install) +dns_registrierung_modus: "install" + +# Technitium DNS-Server (IP oder Hostname) +dns_server: "192.168.0.51" + +# DNS-Zone, in der der Host eingetragen wird +dns_zone: "proxmox.homelab" + +# API-Token für die Technitium-DNS-API +# Wird in Semaphore als Secret übergeben (z. B. -e api_token=$API_TOKEN) +api_token: "CHANGEME" + +# Name des systemd Service/Timers +service_name: "update-dns" + +# Pfad, unter dem das Update-Skript installiert wird +script_path: "/usr/local/bin/update-dns.sh" \ No newline at end of file diff --git a/roles/dns-registrierung/tasks/install.yml b/roles/dns-registrierung/tasks/install.yml new file mode 100644 index 0000000..795e978 --- /dev/null +++ b/roles/dns-registrierung/tasks/install.yml @@ -0,0 +1,69 @@ +- name: curl installieren (falls nicht vorhanden) + ansible.builtin.package: + name: curl + state: present + +- name: Verzeichnis für Skript sicherstellen + ansible.builtin.file: + path: "{{ script_path | dirname }}" + state: directory + owner: root + group: root + mode: '0755' + +- name: Skript installieren + ansible.builtin.template: + src: update-dns.sh.j2 + dest: "{{ script_path }}" + owner: root + group: root + mode: '0755' + +- name: systemd Service-Datei erstellen + ansible.builtin.copy: + dest: "/etc/systemd/system/{{ service_name }}.service" + content: | + [Unit] + Description=Update DNS after boot + + [Service] + ExecStart={{ script_path }} + Type=oneshot + owner: root + group: root + mode: "0644" + +- name: systemd Timer-Datei erstellen + ansible.builtin.copy: + dest: "/etc/systemd/system/{{ service_name }}.timer" + content: | + [Unit] + Description=Run DNS update 10 seconds after boot + + [Timer] + OnBootSec=10s + AccuracySec=1s + Unit={{ service_name }}.service + + [Install] + WantedBy=timers.target + owner: root + group: root + mode: "0644" + +- name: systemd Timer aktivieren und starten + ansible.builtin.systemd: + name: "{{ service_name }}.timer" + enabled: true + state: started + daemon_reload: true + +- name: Skript sofort ausführen (einmalig beim Installieren) + ansible.builtin.shell: "{{ script_path }}" + register: dns_script_output + failed_when: "'Fehler' in dns_script_output.stdout or dns_script_output.rc != 0" + +- name: Ausgabe des DNS-Update-Skripts anzeigen + ansible.builtin.debug: + var: dns_script_output.stdout_lines + when: dns_script_output is defined \ No newline at end of file diff --git a/roles/dns-registrierung/tasks/main.yml b/roles/dns-registrierung/tasks/main.yml new file mode 100644 index 0000000..744eafe --- /dev/null +++ b/roles/dns-registrierung/tasks/main.yml @@ -0,0 +1,11 @@ +- name: DNS-Modus anzeigen + ansible.builtin.debug: + msg: "DNS-Modus ist '{{ dns_registrierung_modus }}'" + +- name: Installation ausführen + ansible.builtin.include_tasks: install.yml + when: dns_registrierung_modus | lower == "install" + +- name: Entfernung ausführen + ansible.builtin.include_tasks: remove.yml + when: dns_registrierung_modus | lower == "remove" \ No newline at end of file diff --git a/roles/dns-registrierung/tasks/remove.yml b/roles/dns-registrierung/tasks/remove.yml new file mode 100644 index 0000000..f88504e --- /dev/null +++ b/roles/dns-registrierung/tasks/remove.yml @@ -0,0 +1,51 @@ +- name: Hostname ermitteln + command: hostname + register: hostname_result + +- name: IP-Adresse ermitteln + command: hostname -I + register: ip_result + +- name: DNS-Eintrag beim Technitium-DNS entfernen + uri: + url: "http://{{ dns_server }}:5380/api/zones/records/delete?domain={{ hostname_result.stdout }}.{{ dns_zone }}&zone={{ dns_zone }}&type=A&token={{ api_token }}" + method: GET + return_content: true + register: delete_dns_response + +- name: Rückmeldung zur DNS-Löschung anzeigen + debug: + var: delete_dns_response.content + +- name: systemd Timer stoppen und deaktivieren + systemd: + name: "{{ service_name }}.timer" + enabled: false + state: stopped + daemon_reload: true + +- name: systemd Service stoppen und deaktivieren + systemd: + name: "{{ service_name }}.service" + enabled: false + state: stopped + daemon_reload: true + +- name: systemd Timer-Datei löschen + file: + path: "/etc/systemd/system/{{ service_name }}.timer" + state: absent + +- name: systemd Service-Datei löschen + file: + path: "/etc/systemd/system/{{ service_name }}.service" + state: absent + +- name: systemd Daemon neu laden + systemd: + daemon_reload: true + +- name: Bashskript löschen + file: + path: "{{ script_path }}" + state: absent \ No newline at end of file diff --git a/roles/dns-registrierung/templates/update-dns.sh.j2 b/roles/dns-registrierung/templates/update-dns.sh.j2 new file mode 100644 index 0000000..30e38a1 --- /dev/null +++ b/roles/dns-registrierung/templates/update-dns.sh.j2 @@ -0,0 +1,96 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset + +DNS_SERVER="{{ dns_server }}" +DNS_ZONE="{{ dns_zone }}" +API_TOKEN="{{ api_token }}" + +HOSTNAME=$(hostname) +IP_ADDRESS=$(hostname -I | awk '{print $1}') +DOMAIN="$HOSTNAME.$DNS_ZONE" + +LOGFILE="/var/log/update-dns.log" +DEBUG=true # bei Bedarf auf false setzen + +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S') | $1" | tee -a "$LOGFILE" +} + +debug() { + if [ "$DEBUG" = true ]; then + log "DEBUG: $1" + fi +} + +log "🔄 Starte DNS-Update für $DOMAIN ($IP_ADDRESS)" + +# --- CURL REQUEST ------------------------------------------------------------- + +API_URL="http://$DNS_SERVER:5380/api/zones/records/add" +QUERY="domain=$DOMAIN&zone=$DNS_ZONE&type=A&overwrite=true&IPAddress=$IP_ADDRESS&token=$API_TOKEN" + +debug "API-URL: $API_URL?$QUERY" + +response=$(curl \ + --silent \ + --show-error \ + --write-out "%{http_code}" \ + --output /tmp/dns_api_response.txt \ + --max-time 10 \ + "$API_URL?$QUERY" 2>/tmp/dns_api_error.txt || true) + +curl_exit=$? + +debug "Curl Exit-Code: $curl_exit" +debug "HTTP-Code: $response" +debug "Curl stderr: $(cat /tmp/dns_api_error.txt || true)" + +if [ "$curl_exit" -ne 0 ]; then + log "❌ Curl-Fehler beim DNS-Update (Exit-Code $curl_exit)" + log " → $(cat /tmp/dns_api_error.txt || echo 'kein Fehlertext')" + exit 10 +fi + +if [ "$response" -ne 200 ]; then + log "❌ DNS-Server antwortete mit HTTP $response" + log " API Response: $(cat /tmp/dns_api_response.txt || echo 'keine Antwort')" + exit 11 +fi + +log "✅ DNS-Eintrag erfolgreich gesetzt." + +# --- DNS CHECK --------------------------------------------------------------- + +log "🔍 Prüfe DNS-Eintrag mit dig..." + +max_retries=5 +retry_delay=2 +success=false + +for i in $(seq 1 "$max_retries"); do + dns_check=$(dig +time=2 +tries=1 +short "$DOMAIN" 2>/tmp/dns_dig_error.txt || true) + + if [ -s /tmp/dns_dig_error.txt ]; then + debug "dig error: $(cat /tmp/dns_dig_error.txt)" + fi + + if [ -n "$dns_check" ]; then + log "🟢 DNS-Eintrag gefunden: $dns_check" + success=true + break + else + log "🔁 Versuch $i/$max_retries: DNS-Eintrag noch nicht sichtbar" + sleep "$retry_delay" + fi +done + +if [ "$success" = false ]; then + log "🔴 Kein DNS-Eintrag gefunden nach $max_retries Versuchen." + exit 12 +fi + +log "🎉 DNS-Update abgeschlossen." +exit 0 \ No newline at end of file