release: v0.1.0
This commit is contained in:
292
README.md
292
README.md
@@ -1,74 +1,153 @@
|
||||
# ddns-updater
|
||||
# DDNS Updater
|
||||
|
||||
A small Go daemon that keeps Cloudflare A records in sync with your current public IPv4 address.
|
||||
It reads a YAML config, checks your IP periodically, compares it to existing DNS records, and only updates when needed.
|
||||
A lightweight dynamic DNS updater for Cloudflare written in Go. Automatically detects your public IP changes and updates specified DNS A records.
|
||||
|
||||
## Features
|
||||
|
||||
- Uses Cloudflare API token (modern auth)
|
||||
- Supports multiple subdomains in one zone
|
||||
- IPv4 only (A records)
|
||||
- User-defined check interval (minutes)
|
||||
- Retries on failure, then logs and skips
|
||||
- Structured JSON logging to file
|
||||
- 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)
|
||||
|
||||
## Requirements
|
||||
## Quick Start
|
||||
|
||||
- Go 1.21+ (tested with 1.23)
|
||||
- A Cloudflare account
|
||||
- API token with:
|
||||
- Zone:DNS:Edit
|
||||
- Zone:Zone:Read
|
||||
- Existing zone and A records for your subdomains
|
||||
|
||||
## Installation
|
||||
### 1. Generate configuration template
|
||||
|
||||
```bash
|
||||
# 1. Create project directory
|
||||
mkdir ddns-updater
|
||||
cd ddns-updater
|
||||
|
||||
# 2. Initialize module
|
||||
go mod init github.com/yourname/ddns-updater
|
||||
|
||||
# 3. Add files
|
||||
# - main.go
|
||||
# - config.yaml
|
||||
# - (this README.md)
|
||||
|
||||
# 4. Fetch dependencies
|
||||
go mod tidy
|
||||
|
||||
# 5. Build binary (current platform)
|
||||
go build -o ddns-updater
|
||||
|
||||
# 6. Build for Linux (LXC, etc.)
|
||||
GOOS=linux GOARCH=amd64 go build -o ddns-updater-linux
|
||||
make init-config
|
||||
```
|
||||
|
||||
Copy the resulting binary and `config.yaml` onto your target machine or LXC container, e.g. `/opt/ddns-updater`.
|
||||
This creates `config.yaml` with default settings.
|
||||
|
||||
## Configuration
|
||||
### 2. Get Cloudflare credentials
|
||||
|
||||
Create `config.yaml` in the same directory as the binary:
|
||||
#### 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
|
||||
check_interval: 5 # minutes (e.g. 5, 15, 30)
|
||||
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_CF_API_TOKEN"
|
||||
zone_id: "YOUR_ZONE_ID"
|
||||
api_token: "your-api-token"
|
||||
zone_id: "your-zone-id"
|
||||
zone_name: "example.com"
|
||||
subdomains:
|
||||
- name: "lc"
|
||||
proxied: false
|
||||
- name: "git"
|
||||
proxied: false
|
||||
- name: "mempool"
|
||||
proxied: false
|
||||
- name: "subdomain"
|
||||
proxied: false # true = route through Cloudflare proxy (orange cloud)
|
||||
|
||||
logging:
|
||||
file: "ddns-updater.log"
|
||||
level: "info" # debug, info, warn, error
|
||||
level: "info" # debug, info, warn, error
|
||||
|
||||
retry:
|
||||
max_attempts: 3
|
||||
@@ -76,78 +155,77 @@ retry:
|
||||
|
||||
webhook:
|
||||
enabled: false
|
||||
url: ""
|
||||
url: "" # Optional webhook for notifications
|
||||
```
|
||||
|
||||
- `check_interval`: how often to check your current IP (in minutes).
|
||||
- `subdomains`: just the left part of the name (e.g. `git` for `git.example.com`).
|
||||
- `proxied`: `true` for orange-cloud (proxied), `false` for DNS only.
|
||||
- `logging.file`: log file path, relative to the working directory.
|
||||
- `retry`: per-subdomain retry behavior when the Cloudflare API or network fails temporarily.
|
||||
|
||||
## Usage
|
||||
|
||||
### Direct run
|
||||
|
||||
From the directory containing the binary and `config.yaml`:
|
||||
## Building from Source
|
||||
|
||||
```bash
|
||||
./ddns-updater
|
||||
# Build for current platform
|
||||
make build
|
||||
|
||||
# Build for all platforms
|
||||
make build-all
|
||||
|
||||
# Clean build artifacts
|
||||
make clean
|
||||
```
|
||||
|
||||
The process will:
|
||||
Built binaries will be in `./bin/`
|
||||
|
||||
1. Load `config.yaml`.
|
||||
2. Detect current public IPv4 using external services.
|
||||
3. For each subdomain:
|
||||
- Fetch its current A record from Cloudflare.
|
||||
- If the IP differs, update the record.
|
||||
4. Sleep for `check_interval` minutes and repeat.
|
||||
5. Log events to `ddns-updater.log`.
|
||||
## Troubleshooting
|
||||
|
||||
### Run in background (simple)
|
||||
### 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
|
||||
nohup ./ddns-updater >/dev/null 2>&1 &
|
||||
sudo journalctl -u ddns-updater -n 50
|
||||
```
|
||||
|
||||
### Example systemd service (on Linux/LXC)
|
||||
|
||||
Create `/etc/systemd/system/ddns-updater.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Cloudflare DDNS Updater
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/ddns-updater
|
||||
ExecStart=/opt/ddns-updater/ddns-updater
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Then:
|
||||
**macOS:**
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable ddns-updater
|
||||
sudo systemctl start ddns-updater
|
||||
sudo systemctl status ddns-updater
|
||||
cat /usr/local/var/log/ddns-updater.err
|
||||
```
|
||||
|
||||
Logs will go to `ddns-updater.log` in `/opt/ddns-updater` plus systemd’s journal.
|
||||
### Docker deployment
|
||||
|
||||
## Updating
|
||||
|
||||
To update the binary:
|
||||
Build the image:
|
||||
|
||||
```bash
|
||||
git pull # if you put it in a repo
|
||||
go build -o ddns-updater
|
||||
sudo systemctl restart ddns-updater
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user