# DDNS Updater (Go)

Small, reliable DDNS updater written in Go.
It periodically checks your public IP (via a configurable IP service) and calls your provider's DDNS update URL **only when the IP changes.** Designed to run continuously and easily be installed as a Windows service (we recommend using [nssm](https://nssm.cc/)).

# Features

- Poll public IP at configurable intervals (seconds).

- Call DDNS update URL only when IP changes.

- Simple JSON config (`config.json`).

- Console output + optional file logging.

- Runs perfectly under a service wrapper (e.g., [nssm](https://nssm.cc/)) or Task Scheduler.

- Works with any DDNS endpoint (cPanel, DuckDNS, No-IP, etc.).

# Requirements

- Go 1.20+ to build (or download prebuilt .exe).

- Windows for service operation (works anywhere Go runs if you run it directly).

- If running as a Windows service, we recommend using nssm to wrap the executable.

- Internet access to the configured IP check endpoint (default `https://api.ipify.org`) and your DDNS update URL.

# Example config (`config.json`)
```json
{
  "update_url": "https://triztech.pro/cpanelwebcall/TOKEN",
  "check_interval_seconds": 30,
  "ip_check_url": "https://api.ipify.org",
  "log_file": "ddns.log"
}
```

`update_url` — full DDNS update URL (including token).

`check_interval_seconds` — how often to check public IP (seconds).

`ip_check_url` — a simple service returning your public IP (plain text).

`log_file` — optional path for logfile (relative to program CWD).

# Build
```bash
go build -o DDNSUpdater.exe ./path/to/ddns_updater.go
```
Place `DDNSUpdater.exe` and `config.json` in the same folder for easy management.

# Run manually (for testing)
```PowerShell
.\DDNSUpdater.exe
# or double-click in Explorer
```

It will print status lines to stdout and update the DDNS only when the IP changes.

# Running as a Windows service (recommended)

Use [nssm](https://nssm.cc/) to wrap the executable — it handles start/stop correctly, captures stdout/stderr to files, and restarts on crash.

# Install script (example)

Drop `DDNSUpdater.exe`, `config.json`, `nssm.exe`, and the script into the same folder. Run as Administrator.

`install_ddns_service.bat`
```bat
@echo off
SET SCRIPT_DIR=%~dp0
SET EXE=%SCRIPT_DIR%DDNSUpdater.exe
SET NSSM=%SCRIPT_DIR%nssm.exe

IF NOT EXIST "%EXE%" (
  echo DDNSUpdater.exe not found
  pause
  exit /b 1
)
IF NOT EXIST "%NSSM%" (
  echo nssm.exe not found
  pause
  exit /b 1
)

REM remove old service if exists
"%NSSM%" remove DDNSUpdaterService confirm

REM install service
"%NSSM%" install DDNSUpdaterService "%EXE%"
"%NSSM%" set DDNSUpdaterService AppDirectory "%SCRIPT_DIR%"
"%NSSM%" set DDNSUpdaterService Start SERVICE_AUTO_START

REM optional: stdout / stderr logs
"%NSSM%" set DDNSUpdaterService AppStdout "%SCRIPT_DIR%ddns_stdout.log"
"%NSSM%" set DDNSUpdaterService AppStderr "%SCRIPT_DIR%ddns_stderr.log"

"%NSSM%" start DDNSUpdaterService
echo Installed and started DDNSUpdaterService
pause
```
# Uninstall script

`uninstall_ddns_service.bat`
```bat
@echo off
SET SCRIPT_DIR=%~dp0
SET NSSM=%SCRIPT_DIR%nssm.exe

IF NOT EXIST "%NSSM%" (
  echo nssm.exe not found
  pause
  exit /b 1
)

"%NSSM%" stop DDNSUpdaterService
"%NSSM%" remove DDNSUpdaterService confirm

echo DDNSUpdaterService removed
pause
```

> Run these scripts as Administrator.

# Tips & Best Practices

Use `log_file` to capture activity when running as a service. NSSM can also capture stdout/stderr for you.

If you run behind a reverse proxy (e.g., Caddy), keep the updater independent — it only updates DNS, it does not interact with the proxy.

# Troubleshooting

**No updates happening**: check `config.json` for correct `update_url` and `ip_check_url`. Run the updater manually and inspect logs.

**Service installs but stops immediately**: ensure the binary runs continuously (it should sleep/poll in a loop). When running via NSSM, the process must not exit.

**Permission issues installing service**: run the install script as Administrator.

**IP check returns unexpected data**: try curl `https://api.ipify.org` and make sure the endpoint returns a plain IPv4/IPv6 string.

# Example behavior (log lines)
```log
2026-03-17T12:00:00Z Starting DDNSUpdater
2026-03-17T12:00:00Z Current IP: 154.241.114.93 (no previous value)
2026-03-17T12:00:00Z Updating DDNS at https://triztech.pro/cpanelwebcall/TOKEN -> OK
2026-03-17T12:00:30Z IP unchanged: 154.241.114.93
```