Loading
October 26, 2026

AmirHesamTech

Raspberry Pi, homelab, Linux and automation — projects and practical guides

Secure Local Server: DuckDNS, Nginx Proxy Manager and free HTTPS for a home server

You have something running at home — a media server, a photo backup, a dashboard. It works perfectly on your own Wi-Fi, and the moment you leave the house it’s unreachable.

Getting to it from outside normally needs three things that stop most people: a domain name, a way to keep that name pointed at a home connection whose IP address keeps changing, and a certificate so browsers don’t throw a security warning. This guide does all three for free. It’s the written version of my DuckDNS and Nginx Proxy Manager guide on GitHub, with a couple of traps I’ve added notes for.

By the end you’ll have an address like yourname.duckdns.org, an HTTPS certificate that renews itself, and several services behind one entrance, each on its own subdomain.

Advertisement

The pieces and what each one does

Piece Job Cost
DuckDNS Gives you a name and keeps it pointed at your home IP as it changes Free
Nginx Proxy Manager Sits at the front door and sends each subdomain to the right service Free, runs in Docker
Let’s Encrypt Issues the HTTPS certificate, from a button inside Nginx Proxy Manager Free
CasaOS (optional) A web dashboard and app store for the server, so you’re not managing everything over SSH Free

Before you start: this opens a door from the internet into your home network. Change every default password, forward only ports 80 and 443, and read the security checklist near the end before you leave it running.

What you need

  • A computer or Raspberry Pi to act as the server, running Linux.
  • Access to your router’s settings, for port forwarding.
  • About an hour.

Step 1: Create your DuckDNS name

  1. Go to duckdns.org and sign in with GitHub, Google or another account.
  2. Type the name you want, for example myserver, and click add domain. Your address is now myserver.duckdns.org.
  3. Copy the token shown at the top of the page and keep it somewhere safe. Treat it like a password: anyone who has it can point your name somewhere else.

The single most common confusion: the token is not entered in Nginx Proxy Manager. It’s only used by a small script on your server that tells DuckDNS your current IP address.

Step 2: Keep the name pointed at your home

Most home connections get a new IP address from time to time. This script reports the current one to DuckDNS, and cron runs it every five minutes.

mkdir -p ~/duckdns
echo '#!/bin/bash' > ~/duckdns/duck.sh
echo "echo url="https://www.duckdns.org/update?domains=YOURDOMAIN&token=YOURTOKEN&ip=" | curl -k -o ~/duckdns/duck.log -K -" >> ~/duckdns/duck.sh
chmod 700 ~/duckdns/duck.sh      # the token is inside, so only you can read it
~/duckdns/duck.sh
cat ~/duckdns/duck.log           # should say OK

Replace YOURDOMAIN with just the name (myserver, not the full address) and YOURTOKEN with your token. Then schedule it:

(crontab -l 2>/dev/null; echo "*/5 * * * * ~/duckdns/duck.sh") | crontab -
crontab -l

Step 3: If you’ll run CasaOS too, move it off port 80 first

This is the trap. Nginx Proxy Manager needs ports 80 and 443 on the server, and CasaOS’s dashboard also uses port 80 by default. If both run on the same machine, one of them can’t start. The fix is to give CasaOS a different port before you start the proxy: edit /etc/casaos/gateway.ini, change port=80 under [gateway] to something free such as port=8080, then restart it:

sudo nano /etc/casaos/gateway.ini
sudo systemctl restart casaos-gateway

CasaOS is now at http://YOUR_SERVER_IP:8080. If you haven’t installed CasaOS yet, see my guide to turning a spare computer into a home server, or skip this step.

Step 4: Install Nginx Proxy Manager

Install Docker, then create a folder and a Compose file for the proxy:

sudo apt update
sudo apt install docker.io docker-compose -y
mkdir -p ~/nginx-proxy-manager && cd ~/nginx-proxy-manager
nano docker-compose.yml
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'    # web traffic
      - '443:443'  # HTTPS traffic
      - '81:81'    # the admin panel - never forward this one on your router
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
docker-compose up -d     # on newer Docker installs: docker compose up -d

Open http://YOUR_SERVER_IP:81 from a computer on your network and sign in. The default login has long been [email protected] with the password changeme; newer versions may ask you to create the first account instead. Either way, set your own email and a strong password straight away.

Step 5: Forward ports 80 and 443 on your router

In your router’s admin page (often 192.168.1.1 or 192.168.0.1), find Port forwarding — sometimes under Advanced or NAT — and create two rules: external port 80 to your server’s IP on port 80, and external 443 to your server’s IP on 443. Give the server a fixed local IP first (a DHCP reservation in the router), or the rules will break when its address changes.

Step 6: Add a proxy host and a free certificate

  1. In Nginx Proxy Manager open Hosts → Proxy Hosts → Add Proxy Host.
  2. Domain Names: myserver.duckdns.org. Scheme: http. Forward Hostname/IP: your server’s local IP. Forward Port: the port of the service you want to reach.
  3. On the SSL tab choose Request a new SSL Certificate, enter your email, accept the terms, tick Force SSL, and save.
  4. Visit https://myserver.duckdns.org — you should see the padlock.

Step 7: One subdomain per service

DuckDNS answers for every name under yours as well, so casaos.myserver.duckdns.org or photos.myserver.duckdns.org work without any extra DNS setup. Add one proxy host per service — for CasaOS: domain casaos.myserver.duckdns.org, forward port 8080 (from step 3) — and request a certificate for each one.

How a request travels once it’s all running: DuckDNS turns the name into your home IP → your router forwards ports 80/443 to the server → Nginx Proxy Manager reads the subdomain and passes the request to the right service → the certificate keeps it encrypted end to end.

Troubleshooting

  • Works at home, not outside. Test from your phone on mobile data, not Wi-Fi. Check cat ~/duckdns/duck.log says OK, check both port-forwarding rules, and check whether your internet provider blocks port 80 or 443 — some do.
  • The certificate request fails. Let’s Encrypt has to reach your server on port 80 from the internet to prove you own the name. Make sure port 80 is forwarded and that the name already points at your current IP.
  • Is the proxy even running? In the ~/nginx-proxy-manager folder run docker-compose ps, and docker-compose logs app for its log. (Compose names the container after the folder and service, so a plain docker logs nginx-proxy-manager won’t find it.)
  • Something else is using the ports. sudo ss -tulpn | grep -E ':80 |:443 |:81 ' shows what’s listening — often CasaOS, see step 3.
  • DuckDNS stopped updating. Check the token in the script, that the script is executable, and that the cron line exists with crontab -l.

Security checklist before you walk away

  • Every default password changed — Nginx Proxy Manager, CasaOS and each app.
  • Only 80 and 443 forwarded. Port 81 (the proxy’s admin panel) and SSH stay private.
  • Only publish services that need to be reachable. An Access List in Nginx Proxy Manager can put a password in front of anything sensitive.
  • Keep the server and the containers updated, and keep backups.

Port forwarding or a tunnel?

This website doesn’t use any of the above. It reaches the internet through a Cloudflare Tunnel instead, which I explain in how I run this website on a Raspberry Pi 4. Both approaches are valid:

DuckDNS + port forwarding Cloudflare Tunnel
Router changes Forward ports 80 and 443 None — the server connects out
Your own domain needed No — a free duckdns.org name Yes, managed in Cloudflare
Home IP visible Yes No
Works when the ISP blocks ports No Yes
Who sits in the middle Nobody — traffic comes straight to you Cloudflare

Frequently asked questions

Is DuckDNS really free?

Yes. It’s a free dynamic DNS service; you sign in with an existing account and get your subdomains.

Do I need a static IP from my internet provider?

No — that’s exactly what the update script in step 2 is for. It keeps your name pointed at whatever IP you have today.

Do I put the DuckDNS token in Nginx Proxy Manager?

No. The token only goes in the update script. Nginx Proxy Manager only needs the domain name.

Can I run all of this on a Raspberry Pi?

Yes. Docker, Nginx Proxy Manager and CasaOS all run on a 64-bit Raspberry Pi OS.

The full guide, with every command in one place, is on GitHub. If it saves you time, a star there helps other people find it.

Advertisement

65 Posts

SDET and QA engineer. I build Raspberry Pi servers, a Proxmox homelab and automations, and share how on TikTok and Instagram (@techwithamirh3sam).

View All Posts

You Missed

REWARDS 🔰 LV1 0🪙 ❯
🔰
Recruit
Guest Operative
Level1
XP0 / 100
💬 Need help?
coins0
Streak0 days · best 0
📋 Daily missions
↻ Resets daily at midnight
Rank ladder
How to earn
✓ Welcome bonus for joining — +200 🪙 & +100 XP (one-time)
✓ Daily check-in (streak bonus) — +20 XP & +12–24 🪙 (more 🪙 the longer your streak)
✓ Spin the daily wheel — +10 to +150 🪙 (free, once a day)
✓ Daily missions — check-in +15 🪙/+10 XP · daily spin +15 🪙/+10 XP
✓ Finish ALL daily missions — +30 🪙 & +20 XP bonus
✓ Level up — +25 🪙 every new level
✓ Achievements — first sign-in +50 🪙 · Lv5 +75 · Lv10 +150 · Lv25 +300 · 7-day streak +100 · 30-day +250 · collector +100 · subscriber +50
✓ Complete your profile (name, bio, photo) — up to +55 XP (one-time)
✓ Subscribe to the newsletter — +250 🪙 (one-time)
Coins and XP are just for fun: they have no cash value and can't be exchanged for money or prizes. You never earn them for viewing or clicking ads, or for how many pages or articles you open.
🛒 Token Shop0 🪙
🛍️ Shop0items
🎒 Inventory0items

🎡 Daily Spin

One free spin every day — pure bonus coins!
🪙
💬Need help?