dyndns-docker/CLAUDE.md

148 lines
3.7 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
This is a Docker-based Dynamic DNS client for the Hetzner DNS Console. It automatically detects IP changes and updates DNS records via the Hetzner DNS API.
**Core Components:**
- `dyndns.py`: Main Python application that handles IP detection and DNS updates
- `Dockerfile`: Container configuration for the application
- `docker-compose.yml`: Docker Compose setup for easy deployment
## Development Commands
### Docker Operations
**Build the container:**
```bash
docker-compose build
```
**Start the service:**
```bash
docker-compose up -d
```
**View logs:**
```bash
docker-compose logs -f
```
**Restart service:**
```bash
docker-compose restart
```
**Stop service:**
```bash
docker-compose down
```
**Rebuild after code changes:**
```bash
docker-compose up -d --build
```
### Local Development
**Run Python script directly (requires Python 3.11+):**
```bash
# Install dependencies
pip install -r requirements.txt
# Set environment variables or use .env file
export HETZNER_API_TOKEN="your_token"
export DOMAIN="example.com"
export RECORD_NAME="@"
# Run script
python dyndns.py
```
**Test IP detection without updating DNS:**
```python
from dyndns import HetznerDynDNS
client = HetznerDynDNS(api_token, domain, record_name)
current_ip = client.get_current_ip()
print(f"Current IP: {current_ip}")
```
## Architecture
### Application Flow
1. **Initialization**: Load configuration from environment variables
2. **Zone Lookup**: Auto-detect Hetzner DNS Zone ID if not provided
3. **Main Loop**:
- Get current public IP (via api.ipify.org)
- Fetch existing DNS record from Hetzner API
- Compare IPs and update if changed
- Wait for configured interval (default: 5 minutes)
- Repeat
### Hetzner DNS API Integration
The application uses Hetzner's DNS API v1 (https://dns.hetzner.com/api/v1):
- **Authentication**: Via `Auth-API-Token` header
- **GET /zones**: Find zone ID for domain
- **GET /records**: List DNS records for zone
- **POST /records**: Create new DNS record
- **PUT /records/{id}**: Update existing DNS record
### Configuration
All configuration is via environment variables (see `.env.example`):
- **Required**: `HETZNER_API_TOKEN`, `DOMAIN`
- **Optional**: `RECORD_NAME` (default: @), `RECORD_TYPE` (default: A), `CHECK_INTERVAL` (default: 300), `LOG_LEVEL` (default: INFO)
## Versioning Strategy
This project uses a simplified versioning scheme:
- **0.1**: Large changes (new features, breaking changes)
- **0.0.1**: Small changes (bugfixes, minor improvements)
- **1.x**: Major releases (only by explicit instruction)
**When making changes:**
1. Update `CHANGELOG.md` with the change description
2. Increment version according to change size
3. Work in feature branches, merge to main when ready
## Key Files
- `dyndns.py`: Core application logic (250+ lines)
- `requirements.txt`: Python dependencies
- `Dockerfile`: Multi-stage build with non-root user
- `docker-compose.yml`: Service configuration with restart policy
- `.env.example`: Configuration template
- `CHANGELOG.md`: Version history
## Security Notes
- API token is sensitive - never commit `.env` file
- Container runs as non-root user (UID 1000)
- Minimal Python slim image for reduced attack surface
- API token should have minimal required permissions (DNS read/write only)
## Troubleshooting
**Check if container is running:**
```bash
docker-compose ps
```
**View recent logs:**
```bash
docker-compose logs --tail=50
```
**Test API connectivity:**
```bash
# From host
curl -H "Auth-API-Token: YOUR_TOKEN" https://dns.hetzner.com/api/v1/zones
```
**Debug mode:**
Set `LOG_LEVEL=DEBUG` in `.env` and restart container.