116 lines
2.7 KiB
Markdown
116 lines
2.7 KiB
Markdown
# Hostinger DNS Sync
|
|
|
|
A lightweight Docker container that watches **Traefik router labels** on your Docker host and automatically creates/updates **Hostinger DNS records** to point your subdomains at your server's public IP.
|
|
|
|
## How it works
|
|
|
|
```
|
|
Docker event (container start/stop)
|
|
│
|
|
▼
|
|
Scan all containers for Traefik labels
|
|
e.g. traefik.http.routers.myapp.rule=Host(`app.example.com`)
|
|
│
|
|
▼
|
|
Extract hostnames → filter by your DOMAIN
|
|
│
|
|
▼
|
|
Call Hostinger DNS API → upsert A records
|
|
```
|
|
|
|
On startup it does a full sync, then it listens to Docker events in real-time and re-syncs whenever a container starts or stops.
|
|
|
|
---
|
|
|
|
## Prerequisites
|
|
|
|
- Docker + Docker Compose
|
|
- A domain on Hostinger with API access enabled
|
|
- Your server's public IP reachable from the internet
|
|
|
|
---
|
|
|
|
## Setup
|
|
|
|
### 1. Get your Hostinger API key
|
|
|
|
1. Log in to [hPanel](https://hpanel.hostinger.com)
|
|
2. Go to **Profile → API Tokens**
|
|
3. Create a new token with DNS read/write permissions
|
|
|
|
### 2. Clone & configure
|
|
|
|
```bash
|
|
git clone <this-repo>
|
|
cd hostinger-dns-sync
|
|
cp .env.example .env
|
|
nano .env # fill in HOSTINGER_API_KEY and DOMAIN
|
|
```
|
|
|
|
### 3. Deploy
|
|
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
|
|
Check logs:
|
|
```bash
|
|
docker compose logs -f hostinger-dns-sync
|
|
```
|
|
|
|
---
|
|
|
|
## Environment variables
|
|
|
|
| Variable | Required | Default | Description |
|
|
|---|---|---|---|
|
|
| `HOSTINGER_API_KEY` | ✅ | — | API token from hPanel |
|
|
| `DOMAIN` | ✅ | — | Root domain, e.g. `example.com` |
|
|
| `PUBLIC_IP` | ❌ | auto-detected | Override server IP |
|
|
| `RECORD_TYPE` | ❌ | `A` | `A` (IPv4) or `AAAA` (IPv6) |
|
|
| `TTL` | ❌ | `3600` | DNS TTL in seconds |
|
|
| `DELETE_ORPHANS` | ❌ | `false` | Delete DNS records no longer in Traefik |
|
|
| `DRY_RUN` | ❌ | `false` | Preview changes without applying |
|
|
|
|
---
|
|
|
|
## Traefik label format
|
|
|
|
The service reads **all** containers with a label matching:
|
|
|
|
```
|
|
traefik.http.routers.<name>.rule=Host(`subdomain.example.com`)
|
|
```
|
|
|
|
Multi-host rules are supported:
|
|
|
|
```
|
|
traefik.http.routers.<name>.rule=Host(`a.example.com`) || Host(`b.example.com`)
|
|
```
|
|
|
|
---
|
|
|
|
## Orphan cleanup
|
|
|
|
By default, the service only **adds/updates** records and never deletes them.
|
|
Set `DELETE_ORPHANS=true` to automatically remove DNS records for subdomains
|
|
that are no longer referenced by any Traefik router.
|
|
|
|
⚠️ Use with care if you manage other records manually on the same domain.
|
|
|
|
---
|
|
|
|
## Test without making changes
|
|
|
|
```bash
|
|
DRY_RUN=true docker compose up hostinger-dns-sync
|
|
```
|
|
|
|
---
|
|
|
|
## Security notes
|
|
|
|
- The Docker socket is mounted **read-only** (`:ro`) — the container cannot start/stop containers.
|
|
- The API key is passed via environment variable, never baked into the image.
|
|
- Add `.env` to your `.gitignore`.
|