This video demonstrates turning a Raspberry Pi into a private, secure home server using Docker, Portainer, TailScale, and DNS tricks.
Main Points
Use Raspberry Pi OS Lite to save space and avoid desktop overhead.
Enable SSH during setup and SSH into Pi remotely.
Avoid bare-metal apps; use Docker to isolate services.
Portainer provides a GUI to manage Docker containers easily.
Create a dedicated Portainer volume and run Portainer in Docker.
Docker Compose/Stacks help organize multi-service deployments.
TailScale creates a secure, encrypted mesh for remote access.
TailScale avoids opening inbound ports and public internet exposure.
Optional Mulvad VPN and magic DNS enhance security and usability.
Access containers by hostname via magic DNS, even on mobile.
Takeaways
Centralize apps in Docker/Portainer for portability and isolation.
Use TailScale for zero-trust remote access, not public ports.
Enable magic DNS to reference devices by hostname, not IPs.
Maintain the system with a container-focused approach to reduce maintenance.
Consider Mulvad as an optional exit-node for extra privacy.
SUMMARY
This tutorial walks you through turning a Raspberry Pi into a secure, remotely accessible home server by running services as Docker containers and managing them with Portainer. The main problem it addresses is keeping a home lab clean and maintainable (no dependency mess on “bare metal”), while still enabling safe remote access without opening router ports. The primary tools are Docker (container runtime), Portainer CE (container management UI), and Tailscale (encrypted mesh VPN with optional MagicDNS). (Docker Documentation)
DETAILED STEP-BY-STEP BREAKDOWN
Prerequisites (hardware/software)
Hardware
Raspberry Pi (model not specified; ensure it’s compatible with your chosen OS and Docker).
microSD card for OS installation.
Software
Raspberry Pi OS Lite (recommended in the transcript for smaller footprint).
Tailscale installed on the Pi (not inside Docker). (Tailscale)
Step 1 — Install Raspberry Pi OS Lite and enable SSH
Flash Raspberry Pi OS to the SD card.
During first-boot setup:
Enable SSH
Set a username/password
Common mistakes
Forgetting to enable SSH → you can’t manage the Pi headlessly.
Choosing the desktop image when you won’t use GUI → wastes storage and RAM.
(For OS choice: “Lite” is a practical default for servers; Docker doesn’t require a desktop.)
Step 2 — Find the Pi’s IP address and SSH in
Determine the Pi’s IP address on your LAN.
From another machine, SSH into it:
ssh <username>@<pi-ip-address>
Transcript notes
They mention using ifconfig on the Pi to see the IP.
They also use an SSH hostname alias like ssh pihub.
Common mistakes
Wrong IP (DHCP changed it) → consider DHCP reservation on your router.
SSH blocked by firewall/router rules on your LAN.
Step 3 — Install Docker Engine on Raspberry Pi OS
The transcript uses the convenience script approach (“curl … | sh”). The official Docker docs also provide supported install paths and OS requirements. (Docker Documentation)
Installing an unsupported combination (32-bit vs 64-bit, older Pi CPU, etc.). The Docker docs list supported Raspberry Pi OS versions and warn about 32-bit support changes. (Docker Documentation)
Confusing “Docker installed” with “Docker usable by my user” (next step).
Step 4 — Add your user to the docker group (avoid sudo for every command)
Add the current user to the docker group (transcript describes this step):
sudo usermod -aG docker <username>
Then log out and back in (or reboot) so group membership applies:
exit
# SSH back in
groups
You should see docker in the output.
Common mistakes
Forgetting to re-login → group change doesn’t apply.
Typo in username → user isn’t actually added.
Step 5 — Install Portainer CE (Docker management dashboard)
Portainer runs as a container and manages your other containers. Official install docs show the standard pattern: pull the image, create a volume, and run the container with ports. (Portainer Documentation)
Typical flow
Pull Portainer:
docker pull portainer/portainer-ce:latest
Create a persistent volume:
docker volume create portainer_data
Run Portainer (Portainer’s docs provide the authoritative command and port mapping for your desired setup): (Portainer Documentation)
Access Portainer UI
In the transcript, Portainer is hosted on port 9443 (HTTPS UI).
Open in a browser:
https://<pi-ip>:9443
Common mistakes
Forgetting the volume → Portainer config resets on container recreation.
Port collision (9443 already in use) → choose another host port.
Step 6 — Deploy your services as containers (via Portainer “Stacks”)
The transcript shows these apps running as containers managed in Portainer:
Plex
Pi-hole
Heimdall
Caddy
Portainer itself
Practical approach (recommended)
Use Docker Compose in Portainer Stacks so configuration is reproducible.
Confirm containers are running:
docker ps
Common mistakes
Incorrect volume paths → data doesn’t persist (Plex libraries/config, etc.).
Bad port mappings → UI unreachable from LAN.
Permissions issues on mounted directories.
Step 7 — Install Tailscale on the Pi (NOT in Docker)
The transcript explicitly warns: install Tailscale on the host OS (“bare metal”), not in a container.
Official Raspberry Pi OS install instructions: (Tailscale)
Bring the Pi onto your tailnet
sudo tailscale up
This command authenticates and connects the device. (Tailscale)
Common mistakes
Installing Tailscale inside Docker → makes networking and device identity messier than needed.
Forgetting to authenticate in the browser → device won’t join tailnet.
Step 8 — Enable MagicDNS (optional, makes hostnames work)
MagicDNS lets you use device names (like pihub) instead of IP addresses. (Tailscale)
Where
Tailscale admin console → DNS → enable MagicDNS. (Tailscale)
Common mistakes
Assuming MagicDNS automatically creates nice subdomains for each container. It mainly maps devices; containers still need ports or a reverse proxy.
Prefer Raspberry Pi OS Lite for a headless server: fewer packages, less disk/RAM overhead.
Use Portainer Stacks (Compose) for every service so rebuilds/migrations are copy-paste reproducible.
Add your user to the docker group and re-login; it prevents constant sudo friction.
Turn on MagicDNS so you can use pihub instead of IPs across devices. (Tailscale)
Put Caddy (or another reverse proxy) in front of web apps to reduce “remember ports” fatigue and standardize TLS internally.
POTENTIAL LIMITATIONS / WARNINGS
Raspberry Pi compatibility: Not every Pi + OS + Docker combination is equally supported; Docker’s docs call out OS versions and architecture caveats. (Docker Documentation)
Storage wear: Running multiple containers on an SD card can accelerate wear; consider SSD boot/storage for heavier services (especially Plex).
Remote access assumptions: Tailscale secures access, but you still must manage:
Tailscale device approvals
Account security (2FA)
Which services you expose on which ports
Portainer isn’t a security boundary: It’s a management UI—protect it (strong password, restrict who can reach it, keep it updated). (Portainer Documentation)
Container networking pitfalls: Misconfigured port mappings or volumes are the #1 cause of “it works locally but not remotely.”
RECOMMENDED FOLLOW-UP RESOURCES
Docker Engine on Raspberry Pi OS (official install + requirements): (Docker Documentation)
Tailscale DNS settings overview (official): (Tailscale)
If you want, I can produce a clean “starter stack” Compose bundle (Portainer + Heimdall + Caddy) and a validation checklist (ports, volumes, backups, update routine).