232 lines
4.8 KiB
Markdown
232 lines
4.8 KiB
Markdown
# DDNS Updater
|
||
|
||
A lightweight dynamic DNS updater for Cloudflare written in Go. Automatically detects your public IP changes and updates specified DNS A records.
|
||
|
||
## Features
|
||
|
||
- Automatic public IP detection with fallback services
|
||
- Multiple subdomain support
|
||
- Cloudflare API v4 integration
|
||
- Configurable check intervals
|
||
- Retry logic with exponential backoff
|
||
- Structured JSON logging
|
||
- Graceful shutdown handling
|
||
- Cross-platform (Linux, macOS)
|
||
|
||
## Quick Start
|
||
|
||
### 1. Generate configuration template
|
||
|
||
```bash
|
||
make init-config
|
||
```
|
||
|
||
This creates `config.yaml` with default settings.
|
||
|
||
### 2. Get Cloudflare credentials
|
||
|
||
#### Generate API Token
|
||
|
||
1. Log in to [Cloudflare Dashboard](https://dash.cloudflare.com)
|
||
2. Go to **Profile** → **API Tokens**
|
||
3. Click **Create Token**
|
||
4. Use the **Edit zone DNS** template or create a custom token with:
|
||
- **Permissions**: Zone → DNS → Edit, Zone → Zone → Read
|
||
- **Zone Resources**: Include → Specific zone → (select your domain)
|
||
5. Copy the token (you'll only see it once)
|
||
|
||
#### Find Zone ID
|
||
|
||
1. In Cloudflare Dashboard, select your domain
|
||
2. Scroll down on the **Overview** page
|
||
3. Find **Zone ID** in the right sidebar under **API** section
|
||
4. Copy the Zone ID
|
||
|
||
### 3. Configure
|
||
|
||
Edit `config.yaml`:
|
||
|
||
```yaml
|
||
cloudflare:
|
||
api_token: "your-token-here" # From step 2
|
||
zone_id: "your-zone-id-here" # From step 2
|
||
zone_name: "example.com" # Your domain
|
||
subdomains:
|
||
- name: "home" # Updates home.example.com
|
||
proxied: false
|
||
- name: "vpn"
|
||
proxied: true # Route through Cloudflare proxy
|
||
```
|
||
|
||
### 4. Run locally (test)
|
||
|
||
```bash
|
||
make run
|
||
```
|
||
|
||
Logs will show IP detection and DNS updates in real-time.
|
||
|
||
## Production Deployment
|
||
|
||
### Linux (systemd)
|
||
|
||
#### Install and set up service
|
||
|
||
```bash
|
||
# Build and install binary
|
||
make install-linux
|
||
|
||
# Edit config with your credentials
|
||
sudo nano /etc/ddns-updater/config.yaml
|
||
|
||
# Create systemd service
|
||
make service-linux
|
||
|
||
# Enable and start
|
||
sudo systemctl daemon-reload
|
||
sudo systemctl enable ddns-updater
|
||
sudo systemctl start ddns-updater
|
||
|
||
# Check status
|
||
sudo systemctl status ddns-updater
|
||
|
||
# View logs
|
||
sudo journalctl -u ddns-updater -f
|
||
```
|
||
|
||
#### Service management
|
||
|
||
```bash
|
||
sudo systemctl stop ddns-updater # Stop service
|
||
sudo systemctl restart ddns-updater # Restart service
|
||
sudo systemctl disable ddns-updater # Disable auto-start
|
||
```
|
||
|
||
### macOS (launchd)
|
||
|
||
#### Install and set up service
|
||
|
||
```bash
|
||
# Build and install binary
|
||
make install-macos
|
||
|
||
# Edit config with your credentials
|
||
sudo nano /usr/local/etc/ddns-updater.yaml
|
||
|
||
# Create launchd service
|
||
make service-macos
|
||
|
||
# Load and start
|
||
launchctl load ~/Library/LaunchAgents/com.ddns-updater.plist
|
||
launchctl start com.ddns-updater
|
||
|
||
# View logs
|
||
tail -f /usr/local/var/log/ddns-updater.log
|
||
```
|
||
|
||
#### Service management
|
||
|
||
```bash
|
||
launchctl stop com.ddns-updater # Stop service
|
||
launchctl unload ~/Library/LaunchAgents/com.ddns-updater.plist # Unload service
|
||
```
|
||
|
||
## Configuration Reference
|
||
|
||
```yaml
|
||
# Check interval in minutes (how often to check for IP changes)
|
||
check_interval: 5
|
||
|
||
cloudflare:
|
||
api_token: "your-api-token"
|
||
zone_id: "your-zone-id"
|
||
zone_name: "example.com"
|
||
subdomains:
|
||
- name: "subdomain"
|
||
proxied: false # true = route through Cloudflare proxy (orange cloud)
|
||
|
||
logging:
|
||
file: "ddns-updater.log"
|
||
level: "info" # debug, info, warn, error
|
||
|
||
retry:
|
||
max_attempts: 3
|
||
delay_seconds: 5
|
||
|
||
webhook:
|
||
enabled: false
|
||
url: "" # Optional webhook for notifications
|
||
```
|
||
|
||
## Building from Source
|
||
|
||
```bash
|
||
# Build for current platform
|
||
make build
|
||
|
||
# Build for all platforms
|
||
make build-all
|
||
|
||
# Clean build artifacts
|
||
make clean
|
||
```
|
||
|
||
Built binaries will be in `./bin/`
|
||
|
||
## Troubleshooting
|
||
|
||
### Authentication errors
|
||
|
||
- Verify API token has correct permissions (Zone → DNS → Edit, Zone → Zone → Read)
|
||
- Confirm token is scoped to the correct zone
|
||
- Check token hasn't expired
|
||
|
||
### DNS record not found
|
||
|
||
- Ensure `zone_name` matches your Cloudflare domain exactly
|
||
- Verify subdomain exists in Cloudflare DNS settings
|
||
- Check subdomain name doesn't include the domain (use `home`, not `home.example.com`)
|
||
|
||
### Service won't start
|
||
|
||
**Linux:**
|
||
|
||
```bash
|
||
sudo journalctl -u ddns-updater -n 50
|
||
```
|
||
|
||
**macOS:**
|
||
|
||
```bash
|
||
cat /usr/local/var/log/ddns-updater.err
|
||
```
|
||
|
||
### Docker deployment
|
||
|
||
Build the image:
|
||
|
||
```bash
|
||
docker build -t yourname/ddns-updater:latest .
|
||
```
|
||
|
||
Run with a local config file:
|
||
|
||
```bash
|
||
cp config.yaml.example config.yaml # or make init-config
|
||
# edit config.yaml with your Cloudflare settings
|
||
|
||
docker run -d \
|
||
--name ddns-updater \
|
||
--restart unless-stopped \
|
||
-v $(pwd)/config.yaml:/config/config.yaml:ro \
|
||
yourname/ddns-updater:latest
|
||
```
|
||
|
||
Or with Docker Compose:
|
||
|
||
```bash
|
||
docker compose up -d
|
||
```
|
||
|
||
The container runs in the foreground inside Docker; restarts are handled by Docker’s restart policy.
|