██████╗ ██████╗ ██████╗ ███╗ ██╗███████╗
██╔════╝ ██╔═══██╗██╔══██╗████╗ ██║██╔════╝
██║ ███╗██║ ██║██║ ██║██╔██╗ ██║███████╗
██║ ██║██║ ██║██║ ██║██║╚██╗██║╚════██║
╚██████╔╝╚██████╔╝██████╔╝██║ ╚████║███████║
╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
GoDNS is a dynamic DNS (DDNS) client tool. It is a rewrite in Go of my early DynDNS open-source project.

- Supported DNS Providers
- Supported Platforms
- Pre-conditions
- Installation
- Usage
- Configuration
- Web Panel
- Running GoDNS
- Contributing
- Special Thanks
Supported DNS Providers
| Provider | IPv4 support | IPv6 support | Root Domain | Subdomains |
|---|---|---|---|---|
| Cloudflare | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| DigitalOcean | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Google Domains | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| DNSPod | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Dynv6 | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| HE.net (Hurricane Electric) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| AliDNS | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| DuckDNS | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Dreamhost | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| No-IP | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Scaleway | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Linode | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Strato | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| LoopiaSE | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Infomaniak | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Hetzner | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| OVH | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| Porkbun | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Dynu | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| IONOS | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| TransIP | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
Tip: You can follow this issue to view the current status of DDNS for root domains.
Supported Platforms
- Linux
- MacOS
- ARM Linux (Raspberry Pi, etc.)
- Windows
-
MIPS32 platform
To compile binaries for MIPS (mips or mipsle), run:
GOOS=linux GOARCH=mips/mipsle GOMIPS=softfloat go build -aThe binary can run on routers as well.
Pre-conditions
To use GoDNS, it is assumed:
- You registered (now own) a domain
- Domain was delegated to a supported DNS provider (i.e. it has nameserver
NSrecords pointing at a supported provider)
Alternatively, you can sign in to DuckDNS (with a social account) and get a subdomain on the duckdns.org domain for free.
Installation
Build GoDNS by running (from the root of the repository):
cd cmd/godns # go to the GoDNS directory
go mod download # get dependencies
go build # build
You can also download a compiled binary from the releases.
Usage
Print usage/help by running:
$ ./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 and name it as
config.json, or make a copy of config_sample.yaml and name it asconfig.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.jsonoption
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 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:Cloudflare,Google,DNSPod,AliDNS,HE,DuckDNSorDreamhost.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). Available values:IPv4orIPv6.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, you can set8.8.8.8when using GoDNS in IPv4 mode or2001:4860:4860::8888in IPv6 mode.skip_ssl_verify- Skip verification of SSL certificates for https requests.
Update root domain
By simply putting @ into sub_domains, for example:
"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), 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), 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), 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), 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.
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. 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. 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 English
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
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
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": "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": "" } ```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 } ```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": "" } ```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: "" ```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: "" ```
#### 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 ** updated to %0A",
"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 ** updated to \n",
"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 ** updated to \n",
}
}
```
#### 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/)
### 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=&ip=&ip_type=",
"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\": \"\", \"ip\": \"\", \"ip_type\": \"\" }"
}
```
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" } ```
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:
- <https://hub.docker.com/r/timothyye/godns>
- <https://github.com/TimothyYe/godns/pkgs/container/godns>
Visit <https://hub.docker.com/r/timothyye/godns> 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:
- Node.js `18.19.0` 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
npm ci
npm run dev
```
### Build the frontend
To build the frontend, run:
```bash
cd web
npm run build
```
### Run the frontend
To run the frontend, run:
```bash
cd web
npm run start
```
## Special Thanks
Thanks JetBrains for sponsoring this project with [free open source license](https://www.jetbrains.com/community/opensource/).
> I like GoLand, it is an amazing and productive tool.