From f69caa09349de9f3f17f93835080bdeddfb6404e Mon Sep 17 00:00:00 2001 From: Andrew Trieu Date: Tue, 9 Dec 2025 19:36:19 +0200 Subject: [PATCH] feat: Migrate from DuckDNS to Porkbun and add Wg-easy --- README.md | 42 ++++++++++++++++++----------------------- duckdns/duck.log | 5 ----- duckdns/duck.sh | 19 ------------------- homelab/.env.example | 9 +++++---- homelab/Caddyfile | 35 ++++++++++++++++++++++------------ homelab/Dockerfile | 4 ++-- homelab/compose.yml | 39 ++++++++++++++++++++++++++++++++++++-- porkbun/porkbun_ddns.sh | 27 ++++++++++++++++++++++++++ 8 files changed, 112 insertions(+), 68 deletions(-) delete mode 100644 duckdns/duck.log delete mode 100755 duckdns/duck.sh create mode 100755 porkbun/porkbun_ddns.sh diff --git a/README.md b/README.md index cbcc2f4..80bf6eb 100644 --- a/README.md +++ b/README.md @@ -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` | | **2FAuth** | Self-hosted two-factor authentication manager | `https://auth.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://:9443` | | **Uptime Kuma** | Monitors homelab/domain uptime | `http://:3001` | | **Dozzle** | Displays logs super easily (real-time Docker logs) | `http://:9999` | | **Netdata** | Beautiful system and container monitoring | `http://: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. @@ -20,51 +20,43 @@ The setup is built with Docker Compose and is designed to be simple, secure, and ```bash . -├── duckdns -│ ├── duck.log # Log file for DuckDNS updates -│ └── duck.sh # DuckDNS update script (runs via cron) +├── porkbun +│ └── porkbun_ddns.sh # Porkbun DDNS update script (runs via cron) └── homelab - ├── Caddyfile # Reverse proxy configuration for Caddy - └── compose.yml # Docker Compose stack for all services + ├── Caddyfile # Reverse proxy configuration for Caddy + └── compose.yml # Docker Compose stack for all services ``` ## 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 -- `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 / Let’s Encrypt and 2FAuth) -- `TOKEN` → your DuckDNS token -- `SomeRandomStringOf32CharsExactly` → a **32-character** random string for `APP_KEY` +## Porkbun Dynamic DNS Updater -## DuckDNS Dynamic DNS Updater - -The `duckdns/duck.sh` script updates all DuckDNS domains used by the homelab. It always logs to `duckdns/duck.log`. +The script updates all Porkbun domains used by the homelab. ### Run manually ```bash -cd duckdns -./duck.sh +cd porkbun +./porkbun_ddns.sh ``` ### Cron to run periodically (recommended) ```bash -cd duckdns -chmod 700 duck.sh +cd porkbun +chmod 700 porkbun_ddns.sh crontab -e ``` Add: ```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) @@ -75,6 +67,7 @@ The **homelab/** folder contains: - `https://` → Vaultwarden - `https://` → 2FAuth - `https://` → Filebrowser + - `https://` → Wireguard ### Start the stack @@ -91,7 +84,8 @@ mkdir -p services/vaultwarden \ services/netdata/cache \ services/filebrowser/srv \ services/filebrowser/database \ - services/filebrowser/config + services/filebrowser/config \ + services/wg-easy/data ex``` ### Stop the stack diff --git a/duckdns/duck.log b/duckdns/duck.log deleted file mode 100644 index 870fdb9..0000000 --- a/duckdns/duck.log +++ /dev/null @@ -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 diff --git a/duckdns/duck.sh b/duckdns/duck.sh deleted file mode 100755 index 70bc50c..0000000 --- a/duckdns/duck.sh +++ /dev/null @@ -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" diff --git a/homelab/.env.example b/homelab/.env.example index ee45bf7..21a6dec 100644 --- a/homelab/.env.example +++ b/homelab/.env.example @@ -1,8 +1,9 @@ VAULT_DOMAIN=vault.example.com AUTH_DOMAIN=auth.example.com STORAGE_DOMAIN=storage.example.com +VPN_DOMAIN=vpn.example.com EMAIL=mail@example.com -APP_KEY=32characterslongrandomstring! -NC_ADMIN_USER=admin -NC_ADMIN_PASS=changeme -DUCKDNS_TOKEN=TOKEN \ No newline at end of file +TWOFAUTH_APP_KEY=32characterslongrandomstring! +WG_EASY_PASSWORD_HASH=your_bcrypt_hashed_password +PORKBUN_API_KEY=your_porkbun_api_key +PORKBUN_API_SECRET=your_porkbun_api_secret \ No newline at end of file diff --git a/homelab/Caddyfile b/homelab/Caddyfile index fb4f9ba..cb17e36 100644 --- a/homelab/Caddyfile +++ b/homelab/Caddyfile @@ -1,9 +1,12 @@ # =========================== -# DuckDNS +# Porkbun # =========================== -(dns_duck) { +(dns_porkbun) { tls { - dns duckdns {env.DUCKDNS_TOKEN} + dns porkbun { + api_key {env.PORKBUN_API_KEY} + api_secret_key {env.PORKBUN_API_SECRET} + } } log { output file {env.LOG_FILE} @@ -15,10 +18,9 @@ # Vaultwarden # =========================== {env.VAULT_DOMAIN} { - import dns_duck - - encode zstd gzip + import dns_porkbun + encode gzip reverse_proxy vaultwarden:80 } @@ -26,10 +28,9 @@ # 2FAuth # =========================== {env.AUTH_DOMAIN} { - import dns_duck - - encode zstd gzip + import dns_porkbun + encode gzip reverse_proxy 2fauth:8000 } @@ -37,10 +38,20 @@ # Filebrowser # =========================== {env.STORAGE_DOMAIN} { - import dns_duck - - encode zstd gzip + import dns_porkbun + encode gzip reverse_proxy filebrowser:80 } +# =========================== +# WireGuard VPN +# =========================== +{env.VPN_DOMAIN} { + import dns_porkbun + + encode gzip + tls internal + reverse_proxy wg-easy:51821 +} + diff --git a/homelab/Dockerfile b/homelab/Dockerfile index 7e0b8df..8659b54 100644 --- a/homelab/Dockerfile +++ b/homelab/Dockerfile @@ -1,8 +1,8 @@ -# Build Caddy with DuckDNS DNS provider +# Build Caddy with Porkbun DNS provider FROM caddy:latest-builder AS builder RUN xcaddy build \ - --with github.com/caddy-dns/duckdns + --with github.com/caddy-dns/porkbun FROM caddy:latest diff --git a/homelab/compose.yml b/homelab/compose.yml index a01fd54..a70565a 100644 --- a/homelab/compose.yml +++ b/homelab/compose.yml @@ -10,6 +10,8 @@ services: - ./services/vaultwarden:/data environment: DOMAIN: "https://${VAULT_DOMAIN}" + networks: + - proxy # ========================== # 2FAuth (2FA manager) @@ -26,12 +28,14 @@ services: APP_DEBUG: false APP_TIMEZONE: UTC SITE_OWNER: ${EMAIL} - APP_KEY: ${APP_KEY} + APP_KEY: ${TWOFAUTH_APP_KEY} APP_URL: "https://${AUTH_DOMAIN}" ASSET_URL: "https://${AUTH_DOMAIN}" TRUSTED_PROXIES: '*' LOG_CHANNEL: daily LOG_LEVEL: notice + networks: + - proxy # ========================== # Filebrowser (Cloud file manager) @@ -45,6 +49,33 @@ services: - ./services/filebrowser/database:/database - ./services/filebrowser/config:/config 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) @@ -68,9 +99,13 @@ services: VAULT_DOMAIN: ${VAULT_DOMAIN} AUTH_DOMAIN: ${AUTH_DOMAIN} STORAGE_DOMAIN: ${STORAGE_DOMAIN} + VPN_DOMAIN: ${VPN_DOMAIN} EMAIL: ${EMAIL} - DUCKDNS_TOKEN: ${DUCKDNS_TOKEN} + PORKBUN_API_KEY: ${PORKBUN_API_KEY} + PORKBUN_API_SECRET: ${PORKBUN_API_SECRET} LOG_FILE: /data/access.log + networks: + - proxy # ========================== # Portainer (Docker manager) diff --git a/porkbun/porkbun_ddns.sh b/porkbun/porkbun_ddns.sh new file mode 100755 index 0000000..da60757 --- /dev/null +++ b/porkbun/porkbun_ddns.sh @@ -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