Feature request: PowerDNS-Admin #300

Open
opened 2025-11-20 04:22:28 -05:00 by saavagebueno · 5 comments
Owner

Originally created by @bohemtucsok on GitHub (Aug 12, 2023).

Hello

We really like this program, it makes our lives a lot easier :)

Thanks for :)

The question would be who could make up the current list of providers with PowerDNS-Admin as a whole.

Powerdns can be updated with a simple curl call

a simple working example:

curl -H 'Content-Type: application/json' -X PATCH --data '{"rrsets": [ {"name": "xxxx.DOMAIN.COM.", "type": "A", "ttl": 86400, "changetype": "REPLACE", "records": [ {"content": "1.1.1.1", "disabled": false, "name": "xxxx.DOMAIN.COM.", "ttl": 86400, "type": "A"}]}]}' -H 'X-API-Key: WDVaRHNxxxxxxxxx' https://POWERDNS-ADMIN-WEB.COM/api/v1/servers/localhost/zones/DOMAIN.COM | jq .

there could be a way for this to be included among the service providers.

I can help with testing

:)

Originally created by @bohemtucsok on GitHub (Aug 12, 2023). Hello We really like this program, it makes our lives a lot easier :) Thanks for :) The question would be who could make up the current list of providers with PowerDNS-Admin as a whole. Powerdns can be updated with a simple curl call a simple working example: ``` curl -H 'Content-Type: application/json' -X PATCH --data '{"rrsets": [ {"name": "xxxx.DOMAIN.COM.", "type": "A", "ttl": 86400, "changetype": "REPLACE", "records": [ {"content": "1.1.1.1", "disabled": false, "name": "xxxx.DOMAIN.COM.", "ttl": 86400, "type": "A"}]}]}' -H 'X-API-Key: WDVaRHNxxxxxxxxx' https://POWERDNS-ADMIN-WEB.COM/api/v1/servers/localhost/zones/DOMAIN.COM | jq . ``` there could be a way for this to be included among the service providers. I can help with testing :)
saavagebueno added the Category: New provider 🆕Category: Motivated! 🙌 labels 2025-11-20 04:22:28 -05:00
Author
Owner

@bohemtucsok commented on GitHub (Aug 13, 2023):

I have provided a code that can help you integrate pdns-admin

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strconv"
	"time"
)

func getPreviousIP() string {
	previousIP, err := ioutil.ReadFile("previous_ip.txt")
	if err != nil {
		return ""
	}
	return string(previousIP)
}

func saveCurrentIP(ip string) {
	err := ioutil.WriteFile("previous_ip.txt", []byte(ip), 0644)
	if err != nil {
		fmt.Println("Error saving current IP:", err)
	}
}

func getCurrentIP() (string, error) {
	resp, err := http.Get("https://api64.ipify.org?format=text")
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	ip, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	return string(ip), nil
}

func updateDNSRecord(newIP string) error {
	url := os.Getenv("POWERDNS_ADMIN_URL") + os.Getenv("DNS_DOMAIN")
	apiKey := os.Getenv("POWERDNS_API_KEY")

	payload := `{
		"rrsets": [
			{
				"name": "` + os.Getenv("DNS_RECORD_NAME") + `.` + os.Getenv("DNS_DOMAIN") + `.",
				"type": "` + os.Getenv("DNS_RECORD_TYPE") + `",
				"ttl": ` + os.Getenv("DNS_RECORD_TTL") + `,
				"changetype": "REPLACE",
				"records": [
					{
						"content": "` + newIP + `",
						"disabled": false,
						"name": "` + os.Getenv("DNS_RECORD_NAME") + `.` + os.Getenv("DNS_DOMAIN") + `.",
						"ttl": ` + os.Getenv("DNS_RECORD_TTL") + `,
						"type": "` + os.Getenv("DNS_RECORD_TYPE") + `"
					}
				]
			}
		]
	}`

	req, err := http.NewRequest("PATCH", url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-Key", apiKey)

	client := &http.Client{}
	req.Body = ioutil.NopCloser(strings.NewReader(payload))
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	fmt.Println(string(body))

	return nil
}

func main() {
	for {
		previousIP := getPreviousIP()
		currentIP, err := getCurrentIP()
		if err != nil {
			fmt.Println("Error getting current IP:", err)
			time.Sleep(60 * time.Second)
			continue
		}

		if currentIP != previousIP {
			fmt.Println("IP address has changed. Updating DNS record...")
			err := updateDNSRecord(currentIP)
			if err == nil {
				fmt.Println("DNS record update successful!")
				saveCurrentIP(currentIP)
			} else {
				fmt.Println("DNS record update failed:", err)
			}
		} else {
			fmt.Println("IP address has not changed.")
		}

		time.Sleep(time.Duration(CHECK_INTERVAL) * time.Second)
	}
}

@bohemtucsok commented on GitHub (Aug 13, 2023): I have provided a code that can help you integrate pdns-admin ```go package main import ( "fmt" "io/ioutil" "net/http" "os" "strconv" "time" ) func getPreviousIP() string { previousIP, err := ioutil.ReadFile("previous_ip.txt") if err != nil { return "" } return string(previousIP) } func saveCurrentIP(ip string) { err := ioutil.WriteFile("previous_ip.txt", []byte(ip), 0644) if err != nil { fmt.Println("Error saving current IP:", err) } } func getCurrentIP() (string, error) { resp, err := http.Get("https://api64.ipify.org?format=text") if err != nil { return "", err } defer resp.Body.Close() ip, err := ioutil.ReadAll(resp.Body) if err != nil { return "", err } return string(ip), nil } func updateDNSRecord(newIP string) error { url := os.Getenv("POWERDNS_ADMIN_URL") + os.Getenv("DNS_DOMAIN") apiKey := os.Getenv("POWERDNS_API_KEY") payload := `{ "rrsets": [ { "name": "` + os.Getenv("DNS_RECORD_NAME") + `.` + os.Getenv("DNS_DOMAIN") + `.", "type": "` + os.Getenv("DNS_RECORD_TYPE") + `", "ttl": ` + os.Getenv("DNS_RECORD_TTL") + `, "changetype": "REPLACE", "records": [ { "content": "` + newIP + `", "disabled": false, "name": "` + os.Getenv("DNS_RECORD_NAME") + `.` + os.Getenv("DNS_DOMAIN") + `.", "ttl": ` + os.Getenv("DNS_RECORD_TTL") + `, "type": "` + os.Getenv("DNS_RECORD_TYPE") + `" } ] } ] }` req, err := http.NewRequest("PATCH", url, nil) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("X-API-Key", apiKey) client := &http.Client{} req.Body = ioutil.NopCloser(strings.NewReader(payload)) resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } fmt.Println(string(body)) return nil } func main() { for { previousIP := getPreviousIP() currentIP, err := getCurrentIP() if err != nil { fmt.Println("Error getting current IP:", err) time.Sleep(60 * time.Second) continue } if currentIP != previousIP { fmt.Println("IP address has changed. Updating DNS record...") err := updateDNSRecord(currentIP) if err == nil { fmt.Println("DNS record update successful!") saveCurrentIP(currentIP) } else { fmt.Println("DNS record update failed:", err) } } else { fmt.Println("IP address has not changed.") } time.Sleep(time.Duration(CHECK_INTERVAL) * time.Second) } } ```
Author
Owner

@gitwittidbit commented on GitHub (Oct 31, 2023):

+1 for the ability to update PowerDNS records

@gitwittidbit commented on GitHub (Oct 31, 2023): +1 for the ability to update PowerDNS records
Author
Owner

@qdm12 commented on GitHub (Jan 19, 2024):

@bohemtucsok Thanks for the piece of code 💯 I'll get to this real soon after releasing 2.6. Regarding #299 should it be done before or is it unrelated? Thanks!!

@qdm12 commented on GitHub (Jan 19, 2024): @bohemtucsok Thanks for the piece of code 💯 I'll get to this real soon after releasing 2.6. Regarding #299 should it be done before or is it unrelated? Thanks!!
Author
Owner

@bohemtucsok commented on GitHub (Jan 20, 2024):

Hi, @qdm12 #299 is the same, the request was created twice and can be deleted, it would be great if it was included :) if you need help with testing, please let me know.

@bohemtucsok commented on GitHub (Jan 20, 2024): Hi, @qdm12 #299 is the same, the request was created twice and can be deleted, it would be great if it was included :) if you need help with testing, please let me know.
Author
Owner

@LeePorte commented on GitHub (Oct 23, 2024):

I'll add a +1 for this being added in

@LeePorte commented on GitHub (Oct 23, 2024): I'll add a +1 for this being added in
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/ddns-updater#300