feat: add Docker image build target and deployment docs
This commit is contained in:
29
Makefile
29
Makefile
@@ -1,15 +1,20 @@
|
||||
APP_NAME = ddns-updater
|
||||
BIN_DIR = bin
|
||||
VERSION = 1.0.0
|
||||
BIN_DIR = bin
|
||||
VERSION = 1.0.0
|
||||
|
||||
# Go parameters
|
||||
GOCMD = go
|
||||
GOCMD = go
|
||||
GOBUILD = $(GOCMD) build
|
||||
GOCLEAN = $(GOCMD) clean
|
||||
GORUN = $(GOCMD) run
|
||||
GORUN = $(GOCMD) run
|
||||
|
||||
# Docker image (override: make build-dockerimg IMAGE=kccleoc/ddns-updater:latest)
|
||||
IMAGE ?= kccleoc/ddns-updater:latest
|
||||
|
||||
# Build targets
|
||||
.PHONY: all build clean run init-config install install-linux install-macos service-linux service-macos
|
||||
.PHONY: all build build-all clean run init-config install \
|
||||
install-linux install-macos service-linux service-macos \
|
||||
build-dockerimg push-dockerimg
|
||||
|
||||
all: build
|
||||
|
||||
@@ -22,8 +27,8 @@ build:
|
||||
# Build for multiple platforms
|
||||
build-all:
|
||||
mkdir -p $(BIN_DIR)
|
||||
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-linux-amd64 main.go
|
||||
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-linux-arm64 main.go
|
||||
GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-linux-amd64 main.go
|
||||
GOOS=linux GOARCH=arm64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-linux-arm64 main.go
|
||||
GOOS=darwin GOARCH=amd64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-darwin-amd64 main.go
|
||||
GOOS=darwin GOARCH=arm64 $(GOBUILD) -o $(BIN_DIR)/$(APP_NAME)-darwin-arm64 main.go
|
||||
@echo "Built all platform binaries in $(BIN_DIR)/"
|
||||
@@ -90,3 +95,13 @@ service-macos:
|
||||
@echo " launchctl start com.ddns-updater"
|
||||
@echo "\nView logs with:"
|
||||
@echo " tail -f /usr/local/var/log/ddns-updater.log"
|
||||
|
||||
# Build Docker image (parameterized)
|
||||
# Usage: make build-dockerimg IMAGE=kccleoc/ddns-updater:latest
|
||||
build-dockerimg:
|
||||
docker build -t $(IMAGE) .
|
||||
|
||||
# Push Docker image
|
||||
# Usage: make push-dockerimg IMAGE=kccleoc/ddns-updater:latest
|
||||
push-dockerimg:
|
||||
docker push $(IMAGE)
|
||||
|
||||
284
README.md
284
README.md
@@ -13,219 +13,161 @@ A lightweight dynamic DNS updater for Cloudflare written in Go. Automatically de
|
||||
- Graceful shutdown handling
|
||||
- Cross-platform (Linux, macOS)
|
||||
|
||||
## Quick Start
|
||||
## Building and running
|
||||
|
||||
### 1. Generate configuration template
|
||||
### 1. Generate config
|
||||
|
||||
```bash
|
||||
make init-config
|
||||
go run main.go -init-config > config.yaml
|
||||
# edit config.yaml with your Cloudflare token, zone_id, zone_name, and subdomains
|
||||
```
|
||||
|
||||
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`:
|
||||
Key fields:
|
||||
|
||||
```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"
|
||||
api_token: "your-token"
|
||||
zone_id: "your-zone-id"
|
||||
zone_name: "example.com"
|
||||
subdomains:
|
||||
- name: "subdomain"
|
||||
proxied: false # true = route through Cloudflare proxy (orange cloud)
|
||||
|
||||
- name: "lc"
|
||||
proxied: false
|
||||
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
|
||||
file: "/config/logs/ddns-updater.log"
|
||||
```
|
||||
|
||||
## Building from Source
|
||||
### 2. Local binary (Linux/macOS)
|
||||
|
||||
```bash
|
||||
# Build for current platform
|
||||
make build
|
||||
|
||||
# Build for all platforms
|
||||
make build-all
|
||||
|
||||
# Clean build artifacts
|
||||
make clean
|
||||
./bin/ddns-updater -config config.yaml
|
||||
```
|
||||
|
||||
Built binaries will be in `./bin/`
|
||||
***
|
||||
|
||||
## Troubleshooting
|
||||
## Production: Linux (systemd)
|
||||
|
||||
### 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:**
|
||||
1. Install:
|
||||
|
||||
```bash
|
||||
sudo journalctl -u ddns-updater -n 50
|
||||
sudo make install
|
||||
sudo mkdir -p /etc/ddns-updater
|
||||
sudo cp config.yaml /etc/ddns-updater/config.yaml
|
||||
sudo chmod 600 /etc/ddns-updater/config.yaml
|
||||
```
|
||||
|
||||
**macOS:**
|
||||
2. Create `/etc/systemd/system/ddns-updater.service`:
|
||||
|
||||
```bash
|
||||
cat /usr/local/var/log/ddns-updater.err
|
||||
```ini
|
||||
[Unit]
|
||||
Description=DDNS Updater
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/ddns-updater -config /etc/ddns-updater/config.yaml
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
### Docker deployment
|
||||
|
||||
Build the image:
|
||||
3. Enable:
|
||||
|
||||
```bash
|
||||
docker build -t yourname/ddns-updater:latest .
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now ddns-updater
|
||||
sudo systemctl status ddns-updater
|
||||
```
|
||||
|
||||
Run with a local config file:
|
||||
***
|
||||
|
||||
## Production: macOS (launchd)
|
||||
|
||||
1. Install:
|
||||
|
||||
```bash
|
||||
cp config.yaml.example config.yaml # or make init-config
|
||||
# edit config.yaml with your Cloudflare settings
|
||||
sudo make install
|
||||
sudo mkdir -p /usr/local/etc /usr/local/var/log
|
||||
sudo cp config.yaml /usr/local/etc/ddns-updater.yaml
|
||||
sudo chmod 600 /usr/local/etc/ddns-updater.yaml
|
||||
```
|
||||
|
||||
2. Create `~/Library/LaunchAgents/com.ddns-updater.plist` pointing at:
|
||||
|
||||
```xml
|
||||
<array>
|
||||
<string>/usr/local/bin/ddns-updater</string>
|
||||
<string>-config</string>
|
||||
<string>/usr/local/etc/ddns-updater.yaml</string>
|
||||
</array>
|
||||
```
|
||||
|
||||
3. Load:
|
||||
|
||||
```bash
|
||||
launchctl load ~/Library/LaunchAgents/com.ddns-updater.plist
|
||||
launchctl start com.ddns-updater
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Docker usage
|
||||
|
||||
### 1. Prepare appdata on host (e.g. Unraid)
|
||||
|
||||
```bash
|
||||
mkdir -p /mnt/user/appdata/ddns-updater/logs
|
||||
cp config.yaml /mnt/user/appdata/ddns-updater/config.yaml
|
||||
chmod -R 775 /mnt/user/appdata/ddns-updater
|
||||
```
|
||||
|
||||
Ensure `logging.file` in `/mnt/user/appdata/ddns-updater/config.yaml` is:
|
||||
|
||||
```yaml
|
||||
logging:
|
||||
file: "/config/logs/ddns-updater.log"
|
||||
```
|
||||
|
||||
### 2. Dockerfile (multi-stage)
|
||||
|
||||
Already in repo, using `/config/config.yaml` inside the container and writing logs to `/config/logs`.
|
||||
|
||||
### 3. Run with docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name ddns-updater \
|
||||
--restart unless-stopped \
|
||||
-v $(pwd)/config.yaml:/config/config.yaml:ro \
|
||||
yourname/ddns-updater:latest
|
||||
-v /mnt/user/appdata/ddns-updater:/config \
|
||||
kccleoc/ddns-updater:latest
|
||||
```
|
||||
|
||||
Or with Docker Compose:
|
||||
### 4. Docker Compose (Unraid 7 friendly)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
ddns-updater:
|
||||
image: kccleoc/ddns-updater:latest
|
||||
container_name: ddns-updater
|
||||
restart: unless-stopped
|
||||
user: "0:0"
|
||||
volumes:
|
||||
- /mnt/user/appdata/ddns-updater:/config
|
||||
```
|
||||
|
||||
Bring it up from the Compose UI (or CLI):
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
The container runs in the foreground inside Docker; restarts are handled by Docker’s restart policy.
|
||||
## Makefile (Docker image build)
|
||||
|
||||
Usage examples:
|
||||
|
||||
```bash
|
||||
make build-dockerimg IMAGE=kccleoc/ddns-updater:latest
|
||||
make push-dockerimg IMAGE=kccleoc/ddns-updater:latest
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user