diff options
author | Christian Cleberg <hello@cleberg.net> | 2024-03-29 01:42:38 -0500 |
---|---|---|
committer | Christian Cleberg <hello@cleberg.net> | 2024-03-29 01:42:38 -0500 |
commit | 00b2726e0561f174393ae600f0f11adb8afebaab (patch) | |
tree | a4733d553ce68f64277ffa3a52f800dc58ff72de /content/blog/2024-03-15-self-hosting-ddns-updater.org | |
parent | 8ba3d90a0f3db7e5ed29e25ff6d0c1b557ed3ca0 (diff) | |
parent | 41bd0ad58e44244fe67cb36e066d4bb68738516f (diff) | |
download | cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.tar.gz cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.tar.bz2 cleberg.net-00b2726e0561f174393ae600f0f11adb8afebaab.zip |
merge org branch into main
Diffstat (limited to 'content/blog/2024-03-15-self-hosting-ddns-updater.org')
-rw-r--r-- | content/blog/2024-03-15-self-hosting-ddns-updater.org | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/content/blog/2024-03-15-self-hosting-ddns-updater.org b/content/blog/2024-03-15-self-hosting-ddns-updater.org new file mode 100644 index 0000000..0e70c58 --- /dev/null +++ b/content/blog/2024-03-15-self-hosting-ddns-updater.org @@ -0,0 +1,314 @@ +#+title: Self-Hosting DDNS Updater +#+date: <2024-03-15 Fri 14:49:59> +#+description: A guide to self-hosting the DDNS Updater container. + +#+caption: DDNS Updater Web View +[[https://img.cleberg.net/blog/20240315-ddns-updater/ddns.png]] + +[[https://github.com/qdm12/ddns-updater][DDNS Updater]] is a program to +keep DNS A and/or AAAA records updated for multiple DNS providers. + +If you've read any of my other posts, you'll notice that I have been +searching for and using a few different DDNS updating solutions for +years. You'll also notice that I love any projects that offer a Docker +Compose solution. + +Luckily, DDNS Upater fits both of these preferences. + +** Installation + +To get started, always make sure to review the project's +[[https://github.com/qdm12/ddns-updater/blob/master/README.md][README]]. +I'll be documenting my steps below, but they may have changed by the +time you read this. + +The first step is to set up the directories and files required for the +project. + +#+begin_src sh +mkdir ~/ddns-updater +mkdir ~/ddns-updater/data +touch ~/ddns-updater/data/config.json +#+end_src + +*** Configuration + +The main configuration you need to update is the =data/config.json= +file. There is a large list of supported providers in the README, but +I'm going to use Cloudflare in this example. + +#+begin_src sh +nano ~/ddns-updater/data/config.json +#+end_src + +When setting up the configuration for Cloudflare, you'll need the +following: + +- Required Parameters + - ="zone_identifier"= is the Zone ID of your site from the domain + overview page + - ="host"= is your host and can be ="@"=, a subdomain or the wildcard + ="*"=. See + [[https://github.com/qdm12/ddns-updater/issues/243#issuecomment-928313949][this + issue comment for context]]. + - ="ttl"= integer value for record TTL in seconds (specify 1 for + automatic) + - One of the following + ([[https://developers.cloudflare.com/fundamentals/api/get-started/][how + to find API keys]]): + - Email ="email"= and Global API Key ="key"= + - User service key ="user_service_key"= + - API Token ="token"=, configured with DNS edit permissions for your + DNS name's zone +- Optional Parameters + - ="proxied"= can be set to =true= to use the proxy services of + Cloudflare + - ="ip_version"= can be =ipv4= (A records), or =ipv6= (AAAA records) + or =ipv4 or ipv6= (update one of the two, depending on the public + ip found). It defaults to =ipv4 or ipv6=. + - ="ipv6_suffix"= is the IPv6 interface identifier suffix to use. It + can be for example =0:0:0:0:72ad:8fbb:a54e:bedd/64=. If left empty, + it defaults to no suffix and the raw public IPv6 address obtained is + used in the record updating. + +#+begin_src conf +{ + "settings": [ + { + "provider": "cloudflare", + "zone_identifier": "some id", + "domain": "domain.com", + "host": "@", + "ttl": 1, + "proxied": true, + "token": "yourtoken", + "ip_version": "ipv4", + "ipv6_suffix": "" + } + ] +} +#+end_src + +Once you have configured the provider of your choice, correct the file +and directory permissions and ownership. + +#+begin_src sh +cd ~/ddns_updater +# Owned by user ID of Docker container (1000) +chown -R 1000 data +# all access (for creating json database file data/updates.json) +chmod 700 data +# read access only +chmod 400 data/config.json +#+end_src + +*** Docker Compose + +After creating the project structure, let's create the +=docker-compose.yml= file. + +#+begin_src sh +nano ~/ddns_-pdater/docker-compose.yml +#+end_src + +#+begin_src config +version: "3.7" +services: + ddns-updater: + image: qmcgaw/ddns-updater + container_name: ddns-updater + network_mode: bridge + ports: + - 8097:8000/tcp # Change the 8097 value to whichever port you want to use + volumes: + - ./data:/updater/data + environment: + - CONFIG= + - PERIOD=5m + - UPDATE_COOLDOWN_PERIOD=5m + - PUBLICIP_FETCHERS=all + - PUBLICIP_HTTP_PROVIDERS=all + - PUBLICIPV4_HTTP_PROVIDERS=all + - PUBLICIPV6_HTTP_PROVIDERS=all + - PUBLICIP_DNS_PROVIDERS=all + - PUBLICIP_DNS_TIMEOUT=3s + - HTTP_TIMEOUT=10s + + # Web UI + - LISTENING_ADDRESS=:8000 + - ROOT_URL=/ + + # Backup + - BACKUP_PERIOD=0 # 0 to disable + - BACKUP_DIRECTORY=/updater/data + + # Other + - LOG_LEVEL=info + - LOG_CALLER=hidden + - SHOUTRRR_ADDRESSES= + restart: always +#+end_src + +After configuring your preferences in the =docker-compose.yml=, launch +the container. + +#+begin_src sh +cd ~/ddns-updater +sudo docker-compose up -d +#+end_src + +If you've launched this on your local machine, you can launch +=localhost:8097= in your browser to see the results. + +*** Nginx Reverse Proxy + +If you launched this service on a server, other machine, or just want to +access it remotely via a domain name, you can use Nginx as a reverse +proxy to expose the service publicly. + +Start by creating the Nginx configuration file. + +#+begin_src sh +sudo nano /etc/nginx/sites-available/ddns +#+end_src + +Here's a basic example that should work properly. + +#+begin_src conf +server { + # If using 443, remember to include your ssl_certificate + # and ssl_certificate_key + listen [::]:80; + listen 80; + server_name ddns.example.com; + + location / { + set $upstream_ao http://127.0.0.1:9380; + proxy_pass $upstream_ao; + + # May need some additional proxy_* parameters, + # see the full example below if necessary + } +} +#+end_src + +Here's a full example that uses my Authelia authentication service to +require authentication before someone can access the web page. + +#+begin_src conf +server { + if ($host ~ ^[^.]+\.example\.com$) { + return 301 https://$host$request_uri; + } + + listen [::]:80; + listen 80; + server_name ddns.example.com; + return 404; +} + +server { + listen [::]:443 ssl http2; + listen 443 ssl http2; + server_name ddns.example.com; + access_log /var/log/nginx/ddns.access.log; + error_log /var/log/nginx/ddns.error.log; + + add_header X-Content-Type-Options "nosniff"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Frame-Options "DENY"; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains"; + add_header Referrer-Policy "no-referrer"; + + ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + + location /authelia { + internal; + set $upstream_authelia http://127.0.0.1:9091/api/verify; #change the IP and Port to match the IP and Port of your Authelia container + proxy_pass_request_body off; + proxy_pass $upstream_authelia; + proxy_set_header Content-Length ""; + + # Timeout if the real server is dead + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; + client_body_buffer_size 128k; + proxy_set_header Host $host; + proxy_set_header X-Original-URL $scheme://$http_host$request_uri; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Uri $request_uri; + proxy_set_header X-Forwarded-Ssl on; + proxy_redirect http:// $scheme://; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_cache_bypass $cookie_session; + proxy_no_cache $cookie_session; + proxy_buffers 4 32k; + + send_timeout 5m; + proxy_read_timeout 240; + proxy_send_timeout 240; + proxy_connect_timeout 240; + } + + location / { + set $upstream_ddns http://127.0.0.1:8097; #change ddns to match your container name: $upstream_some-container-name or $upstream_somecontainername + proxy_pass $upstream_ddns; #change ddns to match your container name: $upstream_some-container-name or $upstream_somecontainername + + auth_request /authelia; + auth_request_set $target_url https://$http_host$request_uri; + auth_request_set $user $upstream_http_remote_user; + auth_request_set $email $upstream_http_remote_email; + auth_request_set $groups $upstream_http_remote_groups; + proxy_set_header Remote-User $user; + proxy_set_header Remote-Email $email; + proxy_set_header Remote-Groups $groups; + + error_page 401 =302 https://auth.example.com/?rd=$target_url; #change this to match your authentication domain/subdomain + + client_body_buffer_size 128k; + + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; + + send_timeout 5m; + proxy_read_timeout 360; + proxy_send_timeout 360; + proxy_connect_timeout 360; + + proxy_set_header Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection upgrade; + proxy_set_header Accept-Encoding gzip; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Uri $request_uri; + proxy_set_header X-Forwarded-Ssl on; + proxy_redirect http:// $scheme://; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_cache_bypass $cookie_session; + proxy_no_cache $cookie_session; + proxy_buffers 64 256k; + + # set_real_ip_from 192.168.1.0/16; #make sure this matches your network setup + # real_ip_header CF-Connecting-IP; + # real_ip_recursive on; + } +} +#+end_src + +When complete, simply link the file and restart the web server. + +#+begin_src sh +sudo ln -s /etc/nginx/sites-available/ddns /etc/nginx/sites-enabled/ddns +sudo systemctl restart nginx.service +#+end_src + +Your ddns-updater service will now be available via =ddns.example.com=! |