```text ██████╗ ██████╗ ██████╗ ███╗ ██╗███████╗ ██╔════╝ ██╔═══██╗██╔══██╗████╗ ██║██╔════╝ ██║ ███╗██║ ██║██║ ██║██╔██╗ ██║███████╗ ██║ ██║██║ ██║██║ ██║██║╚██╗██║╚════██║ ╚██████╔╝╚██████╔╝██████╔╝██║ ╚████║███████║ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ``` [![Apache licensed][9]][10] [![Docker][3]][4] [![Go Report Card][11]][12] [![GoDoc][13]][14] [![Homebrew][15]][16] [3]: https://img.shields.io/docker/image-size/timothyye/godns/latest [4]: https://hub.docker.com/r/timothyye/godns [9]: https://img.shields.io/badge/license-Apache-blue.svg [10]: LICENSE [11]: https://goreportcard.com/badge/github.com/timothyye/godns [12]: https://goreportcard.com/report/github.com/timothyye/godns [13]: https://godoc.org/github.com/TimothyYe/godns?status.svg [14]: https://godoc.org/github.com/TimothyYe/godns [15]: https://img.shields.io/homebrew/v/godns [16]: https://formulae.brew.sh/formula/godns [GoDNS](https://github.com/TimothyYe/godns) is a self-hosted dynamic DNS (DDNS) client with multi-provider support and a built-in web panel. It is a rewrite in [Go](https://golang.org) of my early [DynDNS](https://github.com/TimothyYe/DynDNS) open-source project. [查看中文帮助文档](README_CN.md) ## Hosted version If you want a managed DDNS service instead of self-hosting GoDNS yourself, try [godns.app](https://godns.app). It is a hosted option for users who want DDNS without running their own server, managing DNS manually, or even owning a domain in advance. Below is the built-in web panel of the open-source GoDNS project: - [Supported DNS Providers](#supported-dns-providers) - [Quick Start](#quick-start) - [Supported Platforms](#supported-platforms) - [Self-hosting Pre-conditions](#self-hosting-pre-conditions) - [Installation](#installation) - [Configuration](#configuration) - [Web Panel](#web-panel) - [Running GoDNS](#running-godns) - [Contributing](#contributing) --- ## Supported DNS Providers | Provider | IPv4 support | IPv6 support | Root Domain | Subdomains | | ------------------------------------- | :----------------: | :----------------: | :----------------: | :----------------: | | [Cloudflare][cloudflare] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [DigitalOcean][digitalocean] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [Google Domains][google.domains] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [DNSPod][dnspod] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [Dynv6][dynv6] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [HE.net (Hurricane Electric)][he.net] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [AliDNS][alidns] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [DuckDNS][duckdns] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [Dreamhost][dreamhost] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [No-IP][no-ip] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [Scaleway][scaleway] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [Linode][linode] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [Strato][strato] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [LoopiaSE][loopiase] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [Infomaniak][infomaniak] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [Hetzner][hetzner] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [OVH][ovh] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [Porkbun][porkbun] | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | | [Dynu][dynu] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [IONOS][ionos] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | | [TransIP][transip] | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | [cloudflare]: https://cloudflare.com [digitalocean]: https://digitalocean.com [google.domains]: https://domains.google [dnspod]: https://www.dnspod.cn [dynv6]: https://dynv6.com [he.net]: https://dns.he.net [alidns]: https://help.aliyun.com/product/29697.html [duckdns]: https://www.duckdns.org [dreamhost]: https://www.dreamhost.com [no-ip]: https://www.noip.com [scaleway]: https://www.scaleway.com/ [linode]: https://www.linode.com [strato]: https://strato.de [loopiase]: https://www.loopia.se/ [infomaniak]: https://www.infomaniak.com/ [hetzner]: https://hetzner.com/ [ovh]: https://www.ovh.com [porkbun]: https://porkbun.com/ [dynu]: https://www.dynu.com/ [ionos]: https://www.ionos.com/ [transip]: https://www.transip.net/ Tip: You can follow this [issue](https://github.com/TimothyYe/godns/issues/76) to view the current status of DDNS for root domains. ## Quick Start Choose the path that fits you best: - Want a managed service with no self-hosting: use [godns.app](https://godns.app). - Want the fastest self-hosted setup: download a binary from [releases](https://github.com/TimothyYe/godns/releases). - Want to run it in a container: jump to [As a Docker container](#as-a-docker-container). - Want to build from source: see [Installation](#installation). ## Supported Platforms - Linux - MacOS - ARM Linux (Raspberry Pi, etc.) - Windows - MIPS32 platform To compile binaries for MIPS (mips or mipsle), run: ```bash GOOS=linux GOARCH=mips/mipsle GOMIPS=softfloat go build -a ``` The binary can run on routers as well. ## Self-hosting Pre-conditions To self-host GoDNS, it is assumed: - You registered (now own) a domain - Domain was delegated to a supported [DNS provider](#supported-dns-providers) (i.e. it has nameserver `NS` records pointing at a supported provider) Alternatively, you can sign in to [DuckDNS](https://www.duckdns.org) (with a social account) and get a subdomain on the duckdns.org domain for free. ## Installation Choose one of the following installation methods: - Install with [Homebrew](https://brew.sh) (macOS / Linux): ```bash brew install godns ``` - Download a compiled binary from [releases](https://github.com/TimothyYe/godns/releases). - Use the Docker image described in [As a Docker container](#as-a-docker-container). - Build from source: ```bash cd cmd/godns # go to the GoDNS directory go mod download # get dependencies go build # build ``` ## Usage Print usage/help by running: ```bash $ ./godns -h Usage of ./godns: -c string Specify a config file (default "./config.json") -h Show help ``` ## Configuration ### Overview - Make a copy of [config_sample.json](configs/config_sample.json) and name it as `config.json`, or make a copy of [config_sample.yaml](configs/config_sample.yaml) and name it as `config.yaml`. - Configure your provider, domain/subdomain info, credentials, etc. - Configure a notification medium (e.g. SMTP to receive emails) to get notified when your IP address changes - Place the file in the same directory of GoDNS or use the `-c=path/to/your/file.json` option ### Multi-Provider Support 🆕 **GoDNS now supports multiple DNS providers simultaneously!** You can now configure domains from different DNS providers in a single configuration file, allowing you to: - Manage domains across multiple DNS services (Cloudflare, DNSPod, DigitalOcean, etc.) - Use provider-specific credentials for each service - Maintain full backward compatibility with existing single-provider configurations 📖 **[View the complete Multi-Provider Configuration Guide](MULTI_PROVIDER.md)** for detailed setup instructions and examples. ### Configuration file format GoDNS supports 2 different configuration file formats: - JSON - YAML By default, GoDNS uses `JSON` config file. However, you can specify to use the `YAML` format via: `./godns -c /path/to/config.yaml` ### Dynamic loading of configuration GoDNS supports dynamic loading of configuration. If you modify the configuration file, GoDNS will automatically reload the configuration and apply the changes. ### Configuration properties - `provider` — One of the [supported provider to use](#supported-dns-providers): `Cloudflare`, `Google`, `DNSPod`, `AliDNS`, `HE`, `DuckDNS` or `Dreamhost`. - `email` — Email or account name of the DNS provider. - `password` — Password of the DNS provider. - `login_token` — API token of the DNS provider. - `domains` — Domains list, with your subdomains. - `ip_urls` — A URL array for fetching one's public IPv4 address. - `ipv6_urls` — A URL array for fetching one's public IPv6 address. - `ip_type` — Switch deciding if IPv4 or IPv6 should be used (when [supported](#supported-dns-providers)). Available values: `IPv4` or `IPv6`. - `interval` — How often (in seconds) the public IP should be updated. - `socks5_proxy` — Socks5 proxy server. - `resolver` — Address of a public DNS server to use. For instance to use [Google's public DNS](https://developers.google.com/speed/public-dns/docs/using), you can set `8.8.8.8` when using GoDNS in IPv4 mode or `2001:4860:4860::8888` in IPv6 mode. - `skip_ssl_verify` - Skip verification of SSL certificates for https requests. ### Update root domain By simply putting `@` into `sub_domains`, for example: ```json "domains": [{ "domain_name": "example.com", "sub_domains": ["@"] }] ``` ### Configuration examples #### Cloudflare For Cloudflare, you need to provide the email & Global API Key as a password (or to use the API token) and configure all the domains & subdomains. By setting the option `proxied = true`, the record receives the performance and security benefits of Cloudflare. This option is only available for Cloudflare.
Using email & Global API Key ```json { "provider": "Cloudflare", "email": "you@example.com", "password": "Global API Key", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "", "proxied": false } ```
Using the API Token ```json { "provider": "Cloudflare", "login_token": "API Token", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### DNSPod For DNSPod, you need to provide your API Token(you can create it [here](https://www.dnspod.cn/console/user/security)), and config all the domains & subdomains.
Example ```json { "provider": "DNSPod", "login_token": "your_id,your_token", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### DigitalOcean For DigitalOcean, you need to provide an API Token with the `domain` scopes (you can create it [here](https://cloud.digitalocean.com/account/api/tokens/new)), and config all the domains & subdomains.
Example ```json { "provider": "DigitalOcean", "login_token": "dop_v1_00112233445566778899aabbccddeeff", "domains": [ { "domain_name": "example.com", "sub_domains": ["@", "www"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300 } ```
#### Dreamhost For Dreamhost, you need to provide your API Token(you can create it [here](https://panel.dreamhost.com/?tree=home.api)), and config all the domains & subdomains.
Example ```json { "provider": "Dreamhost", "login_token": "your_api_key", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "resolver": "ns1.dreamhost.com", "socks5_proxy": "" } ```
#### Dynv6 For Dynv6, only need to provide the `token`, config 1 default domain & subdomains.
Example ```json { "provider": "Dynv6", "password": "", "login_token": "1234567ABCDEFGabcdefg123456789", "domains": [ { "domain_name": "dynv6.net", "sub_domains": ["myname"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### Google Domains For Google Domains, you need to provide email & password, and config all the domains & subdomains.
Example ```json { "provider": "Google", "email": "Your_Username", "password": "Your_Password", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### AliDNS For AliDNS, you need to provide `AccessKeyID` & `AccessKeySecret` as `email` & `password`, and config all the domains & subdomains.
Example ```json { "provider": "AliDNS", "email": "AccessKeyID", "password": "AccessKeySecret", "login_token": "", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### DuckDNS For DuckDNS, the only thing needed is to provide the `token`, config 1 default domain & subdomains.
Example ```json { "provider": "DuckDNS", "password": "", "login_token": "3aaaaaaaa-f411-4198-a5dc-8381cac61b87", "domains": [ { "domain_name": "www.duckdns.org", "sub_domains": ["myname"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### No-IP
Example ```json { "provider": "NoIP", "email": "mail@example.com", "password": "YourPassword", "domains": [ { "domain_name": "ddns.net", "sub_domains": ["timothyye6"] } ], "ip_type": "IPv4", "ip_urls": ["https://api.ip.sb/ip"], "resolver": "8.8.8.8", "interval": 300, "socks5_proxy": "" } ```
#### HE.net For HE, email is not needed, just fill in the DDNS key as a password, and configure all the domains & subdomains.
Example ```json { "provider": "HE", "password": "Your DDNS Key", "login_token": "", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
Provider configuration Add a new "A record" and make sure that "Enable entry for dynamic dns" is checked: Fill in your own DDNS key or generate a random DDNS key for this newly created "A record": Remember the DDNS key and set it in the `password` property in the configuration file. **NOTICE**: If you have multiple domains or subdomains, make sure their DDNS key are the same.
#### Scaleway For Scaleway, you need to provide an API Secret Key as the `login_token` ([How to generate an API key](https://www.scaleway.com/en/docs/generate-api-keys/)), and configure the domains and subdomains. `domain_name` should equal a DNS zone, or the root domain in Scaleway. TTL for the DNS records will be set to the `interval` value. Make sure `A` or `AAAA` records exist for the relevant sub domains, these can be set up in the [Scaleway console](https://www.scaleway.com/en/docs/scaleway-dns/#-Managing-Records).
Example ```json { "provider": "Scaleway", "login_token": "API Secret Key", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "@"] }, { "domain_name": "samplednszone.example.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300 } ```
#### Linode To authenticate with the Linode API you will need to provide a Personal Access Token with "Read/Write" access on the "Domain" scope. Linode has [a help page about creating access tokens](https://www.linode.com/docs/guides/getting-started-with-the-linode-api/). Pass this token into the `login_token` field of the config file. The `domain_name` field of the config file must be the name of an existing Domain managed by Linode. Linode has [a help page about adding domains](https://www.linode.com/docs/guides/dns-manager/). The GoDNS Linode handler will not create domains automatically but will create subdomains automatically. The GoDNS Linode handler currently uses a fixed TTL of 30 seconds for Linode DNS records.
Example ```json { "provider": "Linode", "login_token": ${PERSONAL_ACCESS_TOKEN}, "domains": [{ "domain_name": "example.com", "sub_domains": ["www","@"] },{ "domain_name": "samplednszone.example.com", "sub_domains": ["www","test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300 } ```
#### Strato For Strato, you need to provide email & password and configure all the domains & subdomains. More Info: [German](https://www.strato.de/faq/hosting/so-einfach-richten-sie-dyndns-fuer-ihre-domains-ein/) [English](https://www.strato-hosting.co.uk/faq/hosting/this-is-how-easy-it-is-to-set-up-dyndns-for-your-domains/)
Example ```json { "provider": "strato", "password": "Your_Password", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### LoopiaSE For LoopiaSE, you need to provide a username & password and configure all the domains & subdomains. More info: [Swedish](https://support.loopia.se/wiki/om-dyndns-stodet/)
Example ```json { "provider": "LoopiaSE", "email": "Your_Username", "password": "Your_Password", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### Infomaniak For Infomaniak, you need to provide a username & password and configure all the domains & subdomains. More info: [English](https://faq.infomaniak.com/2376)
Example ```json { "provider": "Infomaniak", "email": "Your_Username", "password": "Your_Password", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### Hetzner For Hetzner, you have to create an access token. This can be done in the DNS-Console. (Person Icon in the top left corner --> API Tokens) Notice: If a domain has multiple Records **only the first** Record will be updated. Make sure there is just one record.
Example ```json { "provider": "hetzner", "login_token": "", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4" } ```
#### OVH For OVH, you need to provide a Consumerkey, an Appsecret, and an Appkey and configure all the domains & subdomains. The needed values can be obtained by visiting [this site](https://www.ovh.com/auth/api/createToken) Rights should be '\*' on GET, POST and PUT More info: [help.ovhcloud.com](https://help.ovhcloud.com/csm/en-gb-api-getting-started-ovhcloud-api?id=kb_article_view&sysparm_article=KB0042784)
Example ```json { "provider": "OVH", "consumer_key": "e389ac80cc8da9c7451bc7b8f171bf4f", "app_secret": "d1ffee354d3643d70deaab48a09131fd", "app_key": "cd338839d6472064", "domains": [ { "domain_name": "example.com", "sub_domains": ["www", "test"] }, { "domain_name": "example2.com", "sub_domains": ["www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### Porkbun For Porkbun, you need to provide your API key as `login_token` and secret key as `password`. Get your API credentials from [Porkbun API Management](https://porkbun.com/account/api).
Example ```json { "provider": "Porkbun", "login_token": "pk1_your_api_key", "password": "sk1_your_secret_key", "domains": [ { "domain_name": "example.com", "sub_domains": ["@", "www", "test"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ipify.org"], "ip_type": "IPv4", "interval": 300 } ```
#### Dynu For Dynu, you need to configure the `password`, config 1 default domain & subdomain.
Example ```json { "provider": "Dynu", "password": "Your_Password", "domains": [ { "domain_name": "your_domain.com", "sub_domains": ["your_subdomain"] } ], "resolver": "8.8.8.8", "ip_urls": ["https://api.ip.sb/ip"], "ip_type": "IPv4", "interval": 300, "socks5_proxy": "" } ```
#### IONOS This is for IONOS Hosting Services, **not** IONOS Cloud. You'll need to [sign up for API Access to Hosting Services](https://my.ionos.com/shop/product/ionos-api), then create an [API Key](https://developer.hosting.ionos.com/keys). You can find a full guide in the [IONOS API Documentation](https://developer.hosting.ionos.com/docs/getstarted). **Note**: The API-Key used by GoDNS must follow the form `publicprefix.secret` as described in the aforementioned documentation.
Example ```yaml provider: IONOS login_token: publicprefix.secret domains: - domain_name: example.com sub_domains: - somesubdomain - anothersubdomain resolver: 1.1.1.1 ip_urls: - https://api.ipify.org ip_type: IPv4 interval: 300 socks5_proxy: "" ```
#### TransIP For TransIP, you need to provide your api private key as `login_token` and username as `email`, and configure all the domains & subdomains.
Example ```yaml provider: TransIP email: account_name login_token: api_key domains: - domain_name: example.com sub_domains: - "@" - somesubdomain - anothersubdomain resolver: 1.1.1.1 ip_urls: - https://api.ipify.org ip_type: IPv4 interval: 300 socks5_proxy: "" ```
### Notifications GoDNS can send a notification each time the IP changes. #### Email Emails are sent over [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol). Update your configuration with the following snippet: ```json "notify": { "mail": { "enabled": true, "smtp_server": "smtp.example.com", "smtp_username": "user", "smtp_password": "password", "smtp_port": 25, "send_from": "my_mail@example.com" "send_to": "my_mail@example.com" } } ``` Each time the IP changes, you will receive an email like this: #### Telegram To receive a [Telegram](https://telegram.org/) message each time the IP changes, update your configuration with the following snippet: ```json "notify": { "telegram": { "enabled": true, "bot_api_key": "11111:aaaa-bbbb", "chat_id": "-123456", "message_template": "Domain *{{ .Domain }}* updated to %0A{{ .CurrentIP }}", "use_proxy": false }, } ``` The `message_template` property supports [markdown](https://www.markdownguide.org). New lines need to be escaped with `%0A`. #### Slack To receive a [Slack](https://slack.com) message each time the IP changes, update your configuration with the following snippet: ```json "notify": { "slack": { "enabled": true, "bot_api_token": "xoxb-xxx", "channel": "your_channel", "message_template": "Domain *{{ .Domain }}* updated to \n{{ .CurrentIP }}", "use_proxy": false }, } ``` The `message_template` property supports [markdown](https://www.markdownguide.org). New lines needs to be escaped with `\n`. #### Discord To receive a [Discord](https://discord.gg) message each time the IP changes, update your configuration with the following snippit: ```json "notify": { "discord": { "enabled": true, "bot_api_token": "discord_bot_token", "channel": "your_channel", "message_template": "(Optional) Domain *{{ .Domain }}* updated to \n{{ .CurrentIP }}", } } ``` #### Pushover To receive a [Pushover](https://pushover.net/) message each time the IP changes, update your configuration with the following snippet: ```json "notify": { "pushover": { "enabled": true, "token": "abcdefghijklmnopqrstuvwxyz1234", "user": "abcdefghijklmnopqrstuvwxyz1234", "message_template": "", "device": "", "title": "", "priority": 0, "html": 1 } } ``` The `message_template` property supports [html](https://pushover.net/api#html) if the `html` parameter is `1`. If it is left empty a default message will be used. If the `device` and `title` parameters are left empty, Pushover will choose defaults [see](https://pushover.net/api#messages). More details on the priority parameter can be found on the Pushover [API description](https://pushover.net/api#priority). #### Bark To receive a [Bark](https://bark.day.app/) message each time the IP changes, update your configuration with the following snippet: ```json "notify": { "bark": { "enabled": true, "server": "https://api.day.app", "device_keys": "", "params": "{ \"isArchive\": 1, \"action\": \"none\" }" } } ``` `server` Bark server address. You can use the default official server `https://api.day.app` or set it to a self-hosted server address. `device_keys` device key, supports multiple keys (comma-separated) for batch push. `params` Bark request parameters, please refer to [Bark API](https://bark.day.app/#/en-us/tutorial?id=request-parameters) `user` Basic auth username of the self-hosted server, same with server side environment variable `BARK_SERVER_BASIC_AUTH_USER`. `password` Basic auth password of the self-hosted server, same with server side environment variable `BARK_SERVER_BASIC_AUTH_PASSWORD`. For more information, please refer to the [Bark official documentation](https://bark.day.app/) #### Ntfy To receive an [ntfy](https://ntfy.sh/) notification each time the IP changes, update your configuration with the following snippet: ```json "notify": { "ntfy": { "enabled": true, "topic": "godns", "server": "https://ntfy.sh", "token": "", "user": "", "password": "", "priority": "default", "tags": "rotating_light", "icon": "", "message_template": "" } } ``` `topic` The ntfy topic to publish to (required). The topic is essentially a channel name — pick something not easily guessable. `server` The ntfy server URL. Defaults to `https://ntfy.sh`. Set to your self-hosted server address if applicable. `token` Access token for authentication (optional). Only needed for self-hosted servers with access control. `user` Username for basic authentication (optional). Used with `password` for self-hosted servers. `password` Password for basic authentication (optional). Used with `user` for self-hosted servers. `priority` Message priority: `min`, `low`, `default`, `high`, or `max` (optional). `tags` Comma-separated list of tags or [emoji short codes](https://docs.ntfy.sh/emojis/) (optional). `icon` URL to an icon to display in the notification (optional). `message_template` Custom message template (optional). If empty, defaults to `IP address of {{ .Domain }} updated to {{ .CurrentIP }}`. For more information, please refer to the [ntfy documentation](https://docs.ntfy.sh/publish/) ### Webhook Webhook is another feature that GoDNS provides to deliver notifications to other applications while the IP is changed. GoDNS delivers a notification to the target URL via an HTTP `GET` or `POST` request. The configuration section `webhook` is used for customizing the webhook request. In general, there are 2 fields used for the webhook request: > - `url`: The target URL for sending webhook requests. > - `request_body`: The content for sending a `POST` request, if this field is empty, an HTTP GET request will be sent instead of the HTTP POST request. Available variables: > - `Domain`: The current domain. > - `IP`: The new IP address. > - `IPType`: The type of the IP: `IPV4` or `IPV6`. #### Webhook with HTTP GET request ```json "webhook": { "enabled": true, "url": "http://localhost:5000/api/v1/send?domain={{.Domain}}&ip={{.CurrentIP}}&ip_type={{.IPType}}", "request_body": "" } ``` For this example, a webhook with query string parameters will be sent to the target URL: ``` http://localhost:5000/api/v1/send?domain=ddns.example.com&ip=192.168.1.1&ip_type=IPV4 ``` #### Webhook with HTTP POST request ```json "webhook": { "enabled": true, "url": "http://localhost:5000/api/v1/send", "request_body": "{ \"domain\": \"{{.Domain}}\", \"ip\": \"{{.CurrentIP}}\", \"ip_type\": \"{{.IPType}}\" }" } ``` For this example, a webhook will be triggered when the IP changes, and the target URL `http://localhost:5000/api/v1/send` will receive an `HTTP POST` request with the request body: ```json { "domain": "ddns.example.com", "ip": "192.168.1.1", "ip_type": "IPV4" } ``` ### Miscellaneous topics #### IPv6 support Most of the [providers](#supported-dns-providers) support IPv6. To enable the `IPv6` support of GoDNS, there are two solutions to choose from: 1. Use an online service to lookup the external IPv6 For that: - Set the `ip_type` as `IPv6`, and make sure the `ipv6_urls` is configured - Create an `AAAA` record instead of an `A` record in your DNS provider
Configuration example ```json { "domains": [ { "domain_name": "example.com", "sub_domains": ["ipv6"] } ], "resolver": "2001:4860:4860::8888", "ipv6_urls": ["https://api-ipv6.ip.sb/ip"], "ip_type": "IPv6" } ```
2. Let GoDNS find the IPv6 of the network interface of the machine it is running on (more on that [later](#network-interface-ip-address)). For this to happen, just leave `ip_urls` and `ipv6_urls` empty. Note that the network interface must be configured with an IPv6 for this to work. #### Network interface IP address For some reasons, if you want to get the IP address associated with a network interface (instead of performing an online lookup), you can specify it in the configuration file this way: ```json "ip_urls": [""], "ip_interface": "interface-name", ``` With `interface-name` replaced by the name of the network interface, e.g. `eth0` on Linux or `Local Area Connection` on Windows. Note: If `ip_urls` is also specified, it will be used to perform an online lookup first and the network interface IP will be used as a fallback in case of failure. #### SOCKS5 proxy support You can make all remote calls go through a [SOCKS5 proxy](https://en.wikipedia.org/wiki/SOCKS#SOCKS5) by specifying it in the configuration file this way: ```json "socks5_proxy": "127.0.0.1:7070" "use_proxy": true ``` #### Obtain IP from Router OS If you want to get the public IP from a Mikrotik RouterOS device, you can use the following configuration: ```json "mikrotik": { "enabled": false, "server": "http://192.168.88.1", "username": "admin", "password": "password", "interface": "pppoe-out" } ``` #### Display debug info To display debug info, set `debug_info` as `true` to enable this feature. By default, the debug info is disabled. ```json "debug_info": true, ``` #### Multiple API URLs GoDNS supports fetching the public IP from multiple URLs via a simple round-robin algorithm. If the first URL fails, it will try the next one until it succeeds. Here is an example of the configuration: ```json "ip_urls": [ "https://api.ipify.org", "https://myip.biturl.top", "https://api-ipv4.ip.sb/ip" ], ``` #### Recommended APIs - - - - ## Web Panel Starting from version 3.1.0, GoDNS provides a web panel to manage the configuration and monitor the status of the domains. The web UI is disabled by default. To enable it, just enable the `web_panel` in the configuration file. ```json "web_panel": { "enabled": true, "addr": "0.0.0.0:9000", "username": "admin", "password": "123456" } ``` After enabling the web panel, you can visit `http://localhost:9000` to manage the configuration and monitor the status of the domains. ## Running GoDNS There are a few ways to run GoDNS. ### Manually Note: make sure to set the `run_once` parameter in your config file so the program will quit after the first run (the default is `false`). It can be added to `cron` or attached to other events on your system. ```json { "...": "...", "run_once": true } ``` Then run ```bash ./godns ``` ### As a manual daemon ```bash nohup ./godns & ``` Note: when the program stops, it will not be restarted. ### As a managed daemon (with upstart) 1. Install `upstart` first (if not available already) 2. Copy `./config/upstart/godns.conf` to `/etc/init` (and tweak it to your needs) 3. Start the service: ```bash sudo start godns ``` ### As a managed daemon (with systemd) 1. Install `systemd` first (it not available already) 2. Copy `./config/systemd/godns.service` to `/lib/systemd/system` (and tweak it to your needs) 3. Start the service: ```bash sudo systemctl enable godns sudo systemctl start godns ``` ### As a managed daemon (with procd) `procd` is the init system on OpenWRT. If you want to use godns as a service with OpenWRT and procd: 1. Copy `./config/procd/godns` to `/etc/init.d` (and tweak it to your needs) 2. Start the service (with root privilege): ```bash service godns enable service godns start ``` ### As a Docker container Available docker registries: - - Visit to fetch the latest docker image. The `-p 9000:9000` option exposes the web panel. With `/path/to/config.json` as your local configuration file, run: ```bash docker run \ -d --name godns --restart=always \ -v /path/to/config.json:/config.json \ -p 9000:9000 \ timothyye/godns:latest ``` To run it with a `YAML` config file: ```bash docker run \ -d --name godns \ -e CONFIG=/config.yaml \ --restart=always \ -v /path/to/config.yaml:/config.yaml \ -p 9000:9000 \ timothyye/godns:latest ``` ### As a Windows service 1. Download the latest version of [NSSM](https://nssm.cc/download) 2. In an administrative prompt, from the folder where NSSM was downloaded, e.g. `C:\Downloads\nssm\` **win64**, run: ``` nssm install YOURSERVICENAME ``` 3. Follow the interface to configure the service. In the "Application" tab just indicate where the `godns.exe` file is. Optionally you can also define a description on the "Details" tab and define a log file on the "I/O" tab. Finish by clicking on the "Install service" button. 4. The service will now start along Windows. Note: you can uninstall the service by running: ``` nssm remove YOURSERVICENAME ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. ### Setup the frontend development environment Requirements: - Bun `1.3.11` or higher - Go `1.17` or higher The frontend project is built with [Next.js](https://nextjs.org/) and [daisyUI](https://daisyui.com/). To start the development environment, run: ```bash cd web bun install bun run dev ``` ### Build the frontend To build the frontend, run: ```bash cd web bun run build ``` ### Run the frontend To run the frontend, run: ```bash cd web bun run start ``` ## Star History [![Star History Chart](https://api.star-history.com/chart?repos=timothyye/godns&type=date&legend=top-left&sealed_token=_J0qwcFvEXQOQ_qAZLm797oWRL6RSJyyZmiybWfH6Rv5P50a7Bl0WQmufET40oCB7OqnkYblx-pmX17fO8j9rb0KK8jbldaz_C0efBkREtkNrIMl3yNxFQ)](https://www.star-history.com/?repos=timothyye%2Fgodns&type=date&legend=top-left)