feat: Migrate from DuckDNS to Porkbun and add Wg-easy

This commit is contained in:
2025-12-09 19:36:19 +02:00
parent cab5220930
commit f69caa0934
8 changed files with 112 additions and 68 deletions

View File

@@ -7,12 +7,12 @@ This repository contains the configuration for my personal homelab stack, includ
| **Vaultwarden** | Self-hosted password manager (Bitwarden-compatible) | `https://vault.example.com` | | **Vaultwarden** | Self-hosted password manager (Bitwarden-compatible) | `https://vault.example.com` |
| **2FAuth** | Self-hosted two-factor authentication manager | `https://auth.example.com` | | **2FAuth** | Self-hosted two-factor authentication manager | `https://auth.example.com` |
| **Filebrowser** | Self-hosted file hosting service | `https://storage.example.com` | | **Filebrowser** | Self-hosted file hosting service | `https://storage.example.com` |
| **Caddy** | Reverse proxy with automatic HTTPS via DuckDNS (DNS-01) | *No direct UI* | | **Wg-easy** | Wireguard VPN with management console | `https://vpn.example.com` |
| **Caddy** | Reverse proxy with automatic HTTPS | *No direct UI* |
| **Portainer** | Makes Docker life 100x easier (visual container manager) | `https://<SERVER_IP>:9443` | | **Portainer** | Makes Docker life 100x easier (visual container manager) | `https://<SERVER_IP>:9443` |
| **Uptime Kuma** | Monitors homelab/domain uptime | `http://<SERVER_IP>:3001` | | **Uptime Kuma** | Monitors homelab/domain uptime | `http://<SERVER_IP>:3001` |
| **Dozzle** | Displays logs super easily (real-time Docker logs) | `http://<SERVER_IP>:9999` | | **Dozzle** | Displays logs super easily (real-time Docker logs) | `http://<SERVER_IP>:9999` |
| **Netdata** | Beautiful system and container monitoring | `http://<SERVER_IP>:19999` | | **Netdata** | Beautiful system and container monitoring | `http://<SERVER_IP>:19999` |
| **DuckDNS Updater** | Updates current dynamic IP address automatically | Runs from `./duckdns/duck.sh` |
The setup is built with Docker Compose and is designed to be simple, secure, and easy to maintain. The setup is built with Docker Compose and is designed to be simple, secure, and easy to maintain.
@@ -20,9 +20,8 @@ The setup is built with Docker Compose and is designed to be simple, secure, and
```bash ```bash
. .
├── duckdns ├── porkbun
── duck.log # Log file for DuckDNS updates ── porkbun_ddns.sh # Porkbun DDNS update script (runs via cron)
│ └── duck.sh # DuckDNS update script (runs via cron)
└── homelab └── homelab
├── Caddyfile # Reverse proxy configuration for Caddy ├── Caddyfile # Reverse proxy configuration for Caddy
└── compose.yml # Docker Compose stack for all services └── compose.yml # Docker Compose stack for all services
@@ -30,41 +29,34 @@ The setup is built with Docker Compose and is designed to be simple, secure, and
## Secrets and Environment Variables ## Secrets and Environment Variables
Before deploying, you **must** replace all placeholder values in the config files. Before deploying, you **must** replace all placeholder values in the config files. See `.env.example`.
- `https://vault.example.com` and `vault.example.com` → your Vaultwarden domain ## Porkbun Dynamic DNS Updater
- `https://auth.example.com` and `auth.example.com` → your 2FAuth domain
- `https://storage.example.com` and `storage.example.com` → your Filebrowser domain
- `admin@example.com` → your email address (used by Caddy / Lets Encrypt and 2FAuth)
- `TOKEN` → your DuckDNS token
- `SomeRandomStringOf32CharsExactly` → a **32-character** random string for `APP_KEY`
## DuckDNS Dynamic DNS Updater The script updates all Porkbun domains used by the homelab.
The `duckdns/duck.sh` script updates all DuckDNS domains used by the homelab. It always logs to `duckdns/duck.log`.
### Run manually ### Run manually
```bash ```bash
cd duckdns cd porkbun
./duck.sh ./porkbun_ddns.sh
``` ```
### Cron to run periodically (recommended) ### Cron to run periodically (recommended)
```bash ```bash
cd duckdns cd porkbun
chmod 700 duck.sh chmod 700 porkbun_ddns.sh
crontab -e crontab -e
``` ```
Add: Add:
```bash ```bash
*/5 * * * * /path/to/duckdns/duck.sh >/dev/null 2>&1 */5 * * * * /path/to/porkbun/porkbun_ddns.sh >/dev/null 2>&1
``` ```
This ensures your DuckDNS domains always point to your current IP. This ensures your Porkbun domains always point to your current IP.
## Homelab Stack (Docker Compose) ## Homelab Stack (Docker Compose)
@@ -75,6 +67,7 @@ The **homelab/** folder contains:
- `https://<vault-domain>` → Vaultwarden - `https://<vault-domain>` → Vaultwarden
- `https://<auth-domain>` → 2FAuth - `https://<auth-domain>` → 2FAuth
- `https://<storage-domain>` → Filebrowser - `https://<storage-domain>` → Filebrowser
- `https://<vpn-domain>` → Wireguard
### Start the stack ### Start the stack
@@ -91,7 +84,8 @@ mkdir -p services/vaultwarden \
services/netdata/cache \ services/netdata/cache \
services/filebrowser/srv \ services/filebrowser/srv \
services/filebrowser/database \ services/filebrowser/database \
services/filebrowser/config services/filebrowser/config \
services/wg-easy/data
ex``` ex```
### Stop the stack ### Stop the stack

View File

@@ -1,5 +0,0 @@
OKUpdating DuckDNS domain andy-auth:
OK
Updating DuckDNS domain andy-vault:
OK
DuckDNS update completed at Sat Nov 15 02:05:38 PM EET 2025

View File

@@ -1,19 +0,0 @@
#!/bin/bash
# === CONFIGURATION ===
TOKEN="TOKEN"
DOMAINS=("auth" "vault" "storage")
LOG_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="$LOG_DIR/duck.log"
# === SETUP ===
mkdir -p "$LOG_DIR"
# === UPDATE ALL DOMAINS ===
for domain in "${DOMAINS[@]}"; do
echo "Updating DuckDNS domain $domain:" >> "$LOG_FILE"
curl -ks "https://www.duckdns.org/update?domains=${domain}&token=${TOKEN}&ip=" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
done
echo "DuckDNS update completed at $(date)" >> "$LOG_FILE"

View File

@@ -1,8 +1,9 @@
VAULT_DOMAIN=vault.example.com VAULT_DOMAIN=vault.example.com
AUTH_DOMAIN=auth.example.com AUTH_DOMAIN=auth.example.com
STORAGE_DOMAIN=storage.example.com STORAGE_DOMAIN=storage.example.com
VPN_DOMAIN=vpn.example.com
EMAIL=mail@example.com EMAIL=mail@example.com
APP_KEY=32characterslongrandomstring! TWOFAUTH_APP_KEY=32characterslongrandomstring!
NC_ADMIN_USER=admin WG_EASY_PASSWORD_HASH=your_bcrypt_hashed_password
NC_ADMIN_PASS=changeme PORKBUN_API_KEY=your_porkbun_api_key
DUCKDNS_TOKEN=TOKEN PORKBUN_API_SECRET=your_porkbun_api_secret

View File

@@ -1,9 +1,12 @@
# =========================== # ===========================
# DuckDNS # Porkbun
# =========================== # ===========================
(dns_duck) { (dns_porkbun) {
tls { tls {
dns duckdns {env.DUCKDNS_TOKEN} dns porkbun {
api_key {env.PORKBUN_API_KEY}
api_secret_key {env.PORKBUN_API_SECRET}
}
} }
log { log {
output file {env.LOG_FILE} output file {env.LOG_FILE}
@@ -15,10 +18,9 @@
# Vaultwarden # Vaultwarden
# =========================== # ===========================
{env.VAULT_DOMAIN} { {env.VAULT_DOMAIN} {
import dns_duck import dns_porkbun
encode zstd gzip
encode gzip
reverse_proxy vaultwarden:80 reverse_proxy vaultwarden:80
} }
@@ -26,10 +28,9 @@
# 2FAuth # 2FAuth
# =========================== # ===========================
{env.AUTH_DOMAIN} { {env.AUTH_DOMAIN} {
import dns_duck import dns_porkbun
encode zstd gzip
encode gzip
reverse_proxy 2fauth:8000 reverse_proxy 2fauth:8000
} }
@@ -37,10 +38,20 @@
# Filebrowser # Filebrowser
# =========================== # ===========================
{env.STORAGE_DOMAIN} { {env.STORAGE_DOMAIN} {
import dns_duck import dns_porkbun
encode zstd gzip
encode gzip
reverse_proxy filebrowser:80 reverse_proxy filebrowser:80
} }
# ===========================
# WireGuard VPN
# ===========================
{env.VPN_DOMAIN} {
import dns_porkbun
encode gzip
tls internal
reverse_proxy wg-easy:51821
}

View File

@@ -1,8 +1,8 @@
# Build Caddy with DuckDNS DNS provider # Build Caddy with Porkbun DNS provider
FROM caddy:latest-builder AS builder FROM caddy:latest-builder AS builder
RUN xcaddy build \ RUN xcaddy build \
--with github.com/caddy-dns/duckdns --with github.com/caddy-dns/porkbun
FROM caddy:latest FROM caddy:latest

View File

@@ -10,6 +10,8 @@ services:
- ./services/vaultwarden:/data - ./services/vaultwarden:/data
environment: environment:
DOMAIN: "https://${VAULT_DOMAIN}" DOMAIN: "https://${VAULT_DOMAIN}"
networks:
- proxy
# ========================== # ==========================
# 2FAuth (2FA manager) # 2FAuth (2FA manager)
@@ -26,12 +28,14 @@ services:
APP_DEBUG: false APP_DEBUG: false
APP_TIMEZONE: UTC APP_TIMEZONE: UTC
SITE_OWNER: ${EMAIL} SITE_OWNER: ${EMAIL}
APP_KEY: ${APP_KEY} APP_KEY: ${TWOFAUTH_APP_KEY}
APP_URL: "https://${AUTH_DOMAIN}" APP_URL: "https://${AUTH_DOMAIN}"
ASSET_URL: "https://${AUTH_DOMAIN}" ASSET_URL: "https://${AUTH_DOMAIN}"
TRUSTED_PROXIES: '*' TRUSTED_PROXIES: '*'
LOG_CHANNEL: daily LOG_CHANNEL: daily
LOG_LEVEL: notice LOG_LEVEL: notice
networks:
- proxy
# ========================== # ==========================
# Filebrowser (Cloud file manager) # Filebrowser (Cloud file manager)
@@ -45,6 +49,33 @@ services:
- ./services/filebrowser/database:/database - ./services/filebrowser/database:/database
- ./services/filebrowser/config:/config - ./services/filebrowser/config:/config
user: "1000:1000" user: "1000:1000"
networks:
- proxy
# ==========================
# WG-Easy (WireGuard VPN)
# ==========================
wg-easy:
image: ghcr.io/wg-easy/wg-easy:latest
container_name: wg-easy
restart: always
environment:
WG_HOST: ${VPN_DOMAIN}
PASSWORD_HASH: ${WG_EASY_PASSWORD_HASH}
volumes:
- ./services/wg-easy/data:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
networks:
- proxy
# ========================== # ==========================
# Caddy (Reverse proxy) # Caddy (Reverse proxy)
@@ -68,9 +99,13 @@ services:
VAULT_DOMAIN: ${VAULT_DOMAIN} VAULT_DOMAIN: ${VAULT_DOMAIN}
AUTH_DOMAIN: ${AUTH_DOMAIN} AUTH_DOMAIN: ${AUTH_DOMAIN}
STORAGE_DOMAIN: ${STORAGE_DOMAIN} STORAGE_DOMAIN: ${STORAGE_DOMAIN}
VPN_DOMAIN: ${VPN_DOMAIN}
EMAIL: ${EMAIL} EMAIL: ${EMAIL}
DUCKDNS_TOKEN: ${DUCKDNS_TOKEN} PORKBUN_API_KEY: ${PORKBUN_API_KEY}
PORKBUN_API_SECRET: ${PORKBUN_API_SECRET}
LOG_FILE: /data/access.log LOG_FILE: /data/access.log
networks:
- proxy
# ========================== # ==========================
# Portainer (Docker manager) # Portainer (Docker manager)

27
porkbun/porkbun_ddns.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
API_KEY="pk1_someapikeyvalue1234567890abcdef"
API_SECRET="sk1_somesecretapikeyvalueabcdef1234567890"
DOMAIN="example.com"
SUBDOMAINS=(
"vault"
"auth"
"cloud"
"vpn"
)
TTL="600"
# =================
IP="$(curl -fs https://api.ipify.org)"
for SUBDOMAIN in "${SUBDOMAINS[@]}"; do
curl -fs "https://api.porkbun.com/api/json/v3/dns/editByNameType/${DOMAIN}/A/${SUBDOMAIN}" \
-H "Content-Type: application/json" \
-d "{
\"apikey\": \"${API_KEY}\",
\"secretapikey\": \"${API_SECRET}\",
\"content\": \"${IP}\",
\"ttl\": \"${TTL}\"
}"
done