Exposing a Dockerized Python App on a Raspberry Pi Using Tailscale Funnel
Learn how to securely expose a Dockerized Python app running on a Raspberry Pi using Tailscale Funnel, without port forwarding or dynamic DNS.
π Exposing a Dockerized Python App on a Raspberry Pi Using Tailscale Funnel
As a developer hosting lightweight services on a Raspberry Pi, exposing them securely to the public internet can be tricky. Tools like ngrok or port forwarding either expire quickly, require fiddly router setup, or open up security holes.
Thatβs where Tailscale comes in. Recently, I stumbled across it while looking for a simple, secure way to expose a Python app running in Docker on my Raspberry Pi and I was seriously impressed.
In this guide, Iβll walk you through how I used Tailscale Funnel to host a Dockerized Python app at https://mypiapp.example.com.
Table of contents
π§ Why Tailscale?
Tailscale creates a peer-to-peer mesh VPN using WireGuard under the hood. But it doesnβt stop at private networking. With the release of Tailscale Funnel, you can securely expose services to the public internet without any port forwarding or dynamic DNS.
Benefits:
-
π End-to-end encryption
-
π No port forwarding needed
-
π Free tier supports Funnel
-
π οΈ Custom domain support
ποΈ Our Setup
Weβll expose a Flask-based Python app running inside a Docker container on a Raspberry Pi.
Requirements:
-
Raspberry Pi (or any Linux device) with Docker installed
-
Tailscale account (Free works fine)
-
A custom domain (e.g. example.com)
-
Access to DNS settings (e.g., Cloudflare, Namecheap)
-
Python Flask app (or similar)
π³ Step 1: Dockerize the Python App
Letβs start with a simple Flask app.
app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello from Raspberry Pi!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY app.py .
RUN pip install flask
CMD ["python", "app.py"]
docker-compose.yml (Optional)
version: '3'
services:
piapp:
build: .
ports:
- '5000:5000'
restart: always
Then build and run:
docker compose up -d --build
Visit http://
To verify Tailscale is running, you can check the status:
tailscale status --json
To get your Tailscale IP address, run:
tailscale ip -4
π Step 2: Install & Authenticate Tailscale
Install Tailscale on the Pi:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
Open the URL printed in the terminal and authenticate your device.
π Step 3: Enable Tailscale Funnel
Enable Funnel (public internet access) for this node:
sudo tailscale funnel enable
Then route public traffic to port 5000:
sudo tailscale serve tcp 443 http://localhost:5000
Boom! Your app is now live on:
https://<your-tailscale-username>.ts.net/
Test it from your phone or another device. It should show your Flask app.
π Step 4: Connect a Custom Domain (mypiapp.example.com)
Now the fun part using your own domain.
- Add a CNAME DNS Record Go to your domain registrar and add a CNAME:
Type: CNAME
Host: mypiapp
Value: <your-tailscale-username>.ts.net
TTL: Auto or 5 min
If your DNS provider doesnβt support CNAME at the root domain, you can use a subdomain like mypiapp.example.com.
- Configure HTTPS Tailscale will automatically provision a Letβs Encrypt certificate for your .ts.net domain, but your custom domain still points there via CNAME so youβre covered.
To verify:
curl -v https://mypiapp.example.com
π Optional: Make Tailscale Serve Permanent
By default, tailscale serve is ephemeral. To persist it:
Create a tailscale serve config file using [tailscale up --advertise-exit-node + ACLs], or
Use [tailscale serve --bg] with systemd or a startup script.
A simple systemd service might look like:
[Unit]
Description=Tailscale Funnel for Pi App
After=network.target
[Service]
ExecStart=/usr/bin/tailscale serve tcp 443 http://localhost:5000
Restart=always
[Install]
WantedBy=multi-user.target
Save this as /etc/systemd/system/tailscale-funnel.service, then:
sudo systemctl enable --now tailscale-funnel
π Done! Youβre Live. Youβve now got:
β A Dockerized Python app β Hosted on your Raspberry Pi β Exposed via HTTPS using Tailscale β Accessible from https://mypiapp.example.com without opening any ports
π§ Final Thoughts
Tailscale Funnel is an absolute game-changer for developers running services on edge devices like Raspberry Pi. Itβs dead simple, secure, and domain-friendly all without poking holes in your firewall.
If youβre tired of fragile port forwarding, try this setup. It just works.