release: v0.1.0

This commit is contained in:
LC mac
2026-01-13 23:55:58 +08:00
parent d60c89201f
commit 9c252cf92c
6 changed files with 381 additions and 127 deletions

292
README.md
View File

@@ -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 systemds 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 Dockers restart policy.