Skip to the content.

GitHub Repo stars Project Type Platform OS Tool Category Scope Interface Audience Status Built With Last Updated

Tailscale on Raspberry Pi

🧠 This guide was featured by Tailscale in their newsletter and on Twitter/X.

🪄 Ready to dive in? Jump straight to the Tailscale setup guide ↓

🔒 A beginner-friendly walkthrough for setting up a Raspberry Pi as a secure, self-hosted VPN exit node using Tailscale — with clear command-line steps and privacy-focused configuration.

💡 You’re viewing the full online version of this guide, hosted via GitHub Pages. Follow along step-by-step or jump to a specific section using the table of contents.


🧭 What You’ll Learn


📦 Requirements


📋 Guide Outline

  1. Install Tailscale and authenticate
  2. Understand and configure key expiry
  3. Enable IP forwarding and advertise the exit node
  4. Set the Raspberry Pi as an exit node in the Tailscale admin console
  5. Verify setup and routing
  6. Troubleshooting tips

💡 Why I Wrote This

I wrote this guide because I wanted a secure, lightweight VPN I could trust — and I wanted to actually understand how it worked.

After cobbling together info from different docs and forums, I decided to write the guide I wish I’d had: clear, beginner-friendly, and actually fun to follow.

This project helped me dig deeper into networking, security, and Raspberry Pi tinkering — and it’s now something I use every day when I’m away from home.


🧭 Planned Enhancements


🤝 Contributing

Suggestions, improvements, or ideas? I’d love your input!


🧩 Run this site locally (preview before pushing)

💡 Note: Run all commands from your local terminal (VS Code → View → Terminal).

You can preview this GitHub Pages site locally using Jekyll — the same engine GitHub uses — so you don’t have to commit every tiny CSS tweak like I did. 🫠

  1. Install Bundler (macOS/Linux):

       gem install bundler
    
  2. Add a Gemfile in the docs/ folder:

     # docs/Gemfile
     source "https://rubygems.org"
    
     gem "github-pages", group: :jekyll_plugins
     gem "webrick" # required on Ruby 3+
    
  3. Install and serve:

     cd docs
     bundle install
     bundle exec jekyll serve --livereload
    
  4. Open the site:

    • http://127.0.0.1:4000

Tip: leave the server running — edits to Markdown, CSS, and images will auto-reload.


🐋 Option B: Docker (no local Ruby needed)

  1. From the repo root, run:

    docker run --rm -it -p 4000:4000 -v "$PWD":/srv/jekyll jekyll/jekyll \
    jekyll serve --source docs --livereload
    
  2. Open the site:

    • http://127.0.0.1:4000

🧹 Troubleshooting running the site locally


📄 License

This guide is licensed under the Creative Commons Attribution 4.0 License.

Use it, share it, remix it — just link back here and give credit. ✌️

Made with curiosity, coffee, and command-line trial & error ☕🖥️


Self-Hosting a VPN with Tailscale on a Raspberry Pi

Purpose of this guide

Inspired by my admiration for Tailscale and their innovative, open-source approach to networking, I decided to challenge myself by setting up a VPN on my Raspberry Pi. Along the way, I also wanted to create a walkthrough that anyone could follow, whether they’re just starting out or have more experience. The result? A detailed guide to configuring Tailscale on a Raspberry Pi, from flashing the microSD card to setting up an exit node.

Do you have a spare Raspberry Pi lying around just waiting for a fun project? If so, let’s give it a new purpose in life by turning it into our very own secure VPN! And, whether you’re a tech enthusiast, a Raspberry Pi hobbyist, or someone just starting out, I hope it inspires confidence to try something new.

Note: This is a personal project and not intended to be official in any way. It also doesn’t replace the wide range of official resources available in Tailscale’s own knowledgebase.


Table of Contents


Introduction

In this guide, we’ll walk through setting up Tailscale on a Raspberry Pi and making it our dedicated exit node. This project will enable us to route our internet traffic securely through the Raspberry Pi, effectively building our own personal VPN using Tailscale.

First, did I mention yet that we’ll be using Tailscale? Yes? Oh, I mentioned it a few times? Even better!

Tailscale creates a private network called a tailnet, built on top of WireGuard, an open-source VPN protocol. The magic of Tailscale is that it simplifies the peer-to-peer mesh networking, handling much of the heavy lifting for us. [Insert an appreciative sigh of relief here: we no longer need to manage a traditional VPN server or “trust” a commercial VPN service.]

Note: Going through this process yesterday was relatively quick, but I wanted to make sure I understood what I was doing, what I was observing, and what speed-bumps I might have been accidentally speeding over. While catching some air was fun for all but the metaphorical vehicle’s suspension, we’ll slow down a bit in this guide, taking it step by step, ensuring we understand the process, and troubleshooting any bumps along the way.

↑ Back to top


Prerequisites

Before we dive into setting up Tailscale and our exit node on the Raspberry Pi, here’s what we’ll need:

↑ Back to top


Preparing your Raspberry Pi

If you already know how to flash your microSD card with Raspberry Pi OS, you can skip ahead to the next section. For those of us who prefer a quick refresher or are new to this, let’s go over how to flash our microSD card with a Raspberry Pi OS!

↑ Back to top


Flashing the microSD Card

  1. Download and install the Raspberry Pi Imager:
  2. Download your preferred Raspberry Pi OS:
    • From the official Raspberry Pi website, choose the Raspberry Pi OS you’d like to use, download it, and extract the compressed file to get the .img file.
    • Since I’m using my Raspberry Pi for a few different projects, I chose Raspberry Pi OS with Desktop (64-bit) running Bookworm. This version gives us a full desktop environment while maintaining compatibility with modern software packages.
  3. Insert your microSD Card:
    • Insert your microSD card but before proceeding, be sure to back up any data on it as the next part of the process will erase it.
  4. Open Raspberry Pi Imager:
    • a. Click Choose Device, and select the Raspberry Pi model you’re using. My Raspberry Pi is a 4 B+, so I chose the Raspberry Pi 4 option.
    • b. Click Operating System, scroll down, and select Use custom.
    • c. Locate the Raspberry Pi OS .img file you downloaded earlier and click Open.
    • d. From the Storage list, select your microSD card.
    • e. With all three fields filled, click Next.
  5. Apply OS customisation
    • Customisation is where we set Wi-Fi, SSH, username, password, and more.
  6. Customisation — hostname, localisation, username, Wi-Fi
    • Set your hostname.
    • Set your localisation (capital city, time zone, keyboard layout).
    • Create the username + password you’ll use to log in via SSH:
    • Configure wireless LAN by entering your Wi-Fi’s SSID and password.

      💡 Password tip:
      While it’s okay to keep the default pi username, to ensure security, I highly recommend leveraging a password manager to generate and securely store a strong, unique password. While Tailscale secures the connection itself, once your Raspberry Pi is connected to the network, it may be accessible to devices on your network–particularly if you set it up as an exit node. Creating a strong password and storing it securely in a password manager not only protects your Raspberry Pi from unauthorized access but also simplifies managing and remembering your credentials.

  7. Enable SSH for Remote access
    • Go to the Remote Access / SSH section (Imager 2.0’s layout varies slightly by OS type).
    • Enable SSH → choose Use password authentication.
  8. Raspberry Pi Connect (leave disabled)
    • Imager may offer “Raspberry Pi Connect” — leave this turned off for now.
  9. App Options — optional but useful
    • Click the App Options button at the bottom left and enable Eject media when finished to avoid file-system warnings later.
  10. Review your settings
    • Imager shows a summary before writing:
    • Hostname configured
    • Localisation configured
    • User account configured
    • Wi-Fi configured
    • SSH enabled
  11. Write the Image:
    • a. A new window will come up alerting you to the fact that any existing data on your microSD card will be erased. Click Yes to acknowledge the warning and continue.
    • b. It should start writing at this point, so now we can let the imager do its thing. After it has finished writing, it will start verifying.
    • Note: This process may take several minutes.
  12. Eject the microSD card:
    • Once writing and verification are complete, eject the microSD card and insert it into your Raspberry Pi.

With that, we’re ready to SSH into our Raspberry Pi and start setting up Tailscale!

↑ Back to top


Using SSH to connect to your Raspberry Pi

  1. Find your Raspberry Pi’s IP address:

    • You can find your Raspberry Pi’s IP address through your router’s device management interface, or by using a network scanning tool like nmap. You can also use hostname -I from the Pi itself if you’re connected to it via a monitor and keyboard.
  2. SSH into the Raspberry Pi:

    • On your local machine, open a terminal and enter the following command, making sure to replace <Raspberry-Pi-IP-Address> with the actual IP. (The default username is pi, unless you changed it in Raspberry Pi Imager):

         ssh pi@<Raspberry-Pi-IP-Address>
      
  3. Enter the password:

    • When prompted, enter the password you set for the pi user. Once authenticated, you’ll be logged into your Raspberry Pi!
  4. Confirm the connection:

    • After logging in, you’ll be at the Raspberry Pi’s command prompt, ready to run commands.

↑ Back to top


Checking for Updates

Before moving forward, it’s a good practice to update our Raspberry Pi’s software to ensure that all the latest patches and security updates are installed. Here’s how:

  1. Update Package Lists:

    • Run the following command to update the list of available packages and their versions:

         sudo apt update
      
  2. Upgrade Installed Packages:

    • After updating the package list, run the following command to upgrade any installed packages to their latest versions:

         sudo apt upgrade -y
      
    • The -y flag automatically confirms the upgrade.

  3. Optional: Full Upgrade:

    • To ensure all packages are fully upgraded, run:

         sudo apt full-upgrade -y
      
  4. Clean Up Unused Packages:

    • After upgrading, you can remove unnecessary packages that are no longer required:

         sudo apt autoremove -y
      
  5. Reboot your Pi:

    • After updates are installed, reboot your Raspberry Pi to apply the changes:

         sudo reboot
      
  6. SSH back in:

    • Since the reboot will terminate the current SSH session, we’ll need to open a new terminal window and SSH back into the Raspberry Pi:

         ssh pi@<your_pi_ip_address>
      

Now we’re ready to start the fun part!

↑ Back to top


Setting up Tailscale on Raspberry Pi

1. Install Tailscale:

2. Authenticate Tailscale:

3. Locate the Tailscale IPv4 address:

High five! We’ve successfully installed and authenticated Tailscale on our Raspberry Pi, and located our Pi’s IPv4 address! Another excuse to stand up, stretch our legs, and treat ourselves to some celebratory noms!

↑ Back to top


Understanding Key Expiry

When setting up Tailscale, there’s an important security feature to consider: key expiry. To ensure security, Tailscale requires devices to reauthenticate after a certain period of time has elapsed. However, at the end of the initial set up, Tailscale’s official installation guide explains:

If the device you added is a server or remotely-accessed device, you may want to consider disabling key expiry to prevent the need to periodically re-authenticate.

Since key expiry is an important security feature, it’s worth diving into the details so we can make an informed decision. Let’s break it down! What the what is key expiry, you ask? By default, Tailscale’s device keys expire after 180 days, though this period may vary based on the pricing plan or domain settings. When a device key expires, the device will need to reauthenticate to remain part of our tailnet.

Let’s start with the perks! What are the benefits of keeping key expiry enabled?

On the other hand, what are some reasons we might want to disable key expiry?

My Personal Decision:

For this guide and my own Pi, I’ve chosen to disable key expiry on the Raspberry Pi. This decision aligns with my goal of maintaining continuous service in a trusted, private environment.

Which Should You Choose?

Ultimately, this decision depends on your use case, risk tolerance, and how comfortable you are with the trade-offs.

Security Considerations:

Security is a bit of a balancing act, like trying to walk a swaying tightrope between convenience and making sure our network doesn’t get hijacked. Disabling key expiry might make life easier for our always-on Raspberry Pi, but it’s also true that a little extra protection (like periodic reauthentication) can go a long way toward keeping things secure.

In the end, it’s all about finding that sweet spot where security and convenience shake hands without tripping over each other-or, in our metaphor, without throwing off the balance of the whole thing, like trying to continue across that tightrope with one foot out of balance.

Learn more about key expiry directly from Tailscale.

↑ Back to top


Configuring the Raspberry Pi as an Exit Node

For some context, Tailscale only routes traffic between the devices on which we’ve installed it. It does not touch our public traffic like when we’re browsing the web, so if all we’re after is secure communication between our devices, we may not need extra encryption for our connection to the internet.

In other cases, if we’re away from home and relegated to networks that we don’t control and can’t trust, we can leverage Tailscale to handle (or, more accurately, route) our public traffic through our Raspberry Pi by setting it up as an exit node.

When we route our internet traffic through an exit node, we’re essentially adding an extra layer of security and privacy. The traffic between our devices and the exit node is encrypted from end-to-end by WireGuard, the open-source protocol Tailscale uses. This means that any data sent from our device to the internet is secured and protected from eavesdropping, which is especially vital on public networks like Wi-Fi hotspots.

However, it’s also important to understand that once our traffic exits the node and reaches its destination on the public internet, it is subject to the usual security measures (or lack thereof) of the websites or services with which we’re interacting.

So, the exit node ensures our traffic is secure and encrypted while it’s within our private network (our tailnet) and until it leaves through the exit node. After that, the security depends on the destination site.

Ref: Exit nodes (route all traffic) - Tailscale

With that in mind, let’s set up our Raspberry Pi as an exit node for our tailnet! Since we’re running Linux, we’ll need to enable IP forwarding and advertise our Pi as an exit node.

When you’re ready, SSH into your Raspberry Pi and follow these steps:

  1. Enable IP forwarding:
    • IP forwarding allows your Raspberry Pi to pass traffic between its network interfaces. We can use the following commands to enable both IPv4 and IPv6 forwarding:

         echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
      
         echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
      
         sudo sysctl -p /etc/sysctl.conf
      

    The first two commands add the necessary settings to the sysctl.conf file while the final command applies the changes immediately without requiring a reboot.

  2. Advertise the exit node:
    • Let Tailscale know your Raspberry Pi is ready to route traffic:

         sudo tailscale up --advertise-exit-node
      
  3. Confirm your exit node is active:

    • a. Visit the Machines page from your Tailscale admin console.
    • b. Locate your Raspberry Pi, and verify that it has an exit node badge.
    • c. Click the ellipsis icon and select Edit route settings.
    • d. Check the box to Use as exit node, then choose Save.

From the Tailscale app on our other devices, we can now use the Raspberry Pi as an exit node for secure traffic routing. Tailscale has us covered with step-by-step instructions on how to use an exit node depending on the type of device.

↑ Back to top


Troubleshooting

When I went through the process, there were a few places where I got tripped up temporarily:

If you encounter any issues along the way, not to worry, as Tailscale has a fantastic knowledgebase to help:

⚙️ Optional: Improve UDP forwarding performance

If you see a warning like:

Warning: UDP GRO forwarding is suboptimally configured on eth0,
UDP forwarding throughput capability will increase with a configuration change.
See https://tailscale.com/s/ethtool-config-udp-gro

This means your network interface can be tuned for better throughput when acting as an exit node.
It’s optional — your setup will still work without it.

To enable UDP GRO forwarding permanently:

  1. Identify your primary interface:
    ip -o route get 8.8.8.8 | cut -f 5 -d " "
    

    (Commonly eth0 on a Raspberry Pi.)

  2. Create a small systemd service:
    sudo nano /etc/systemd/system/udpgroforwarding.service
    

    Paste this in, replacing eth0 with your interface name:

    [Unit]
    Description=Enable UDP GRO Forwarding
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Type=oneshot
    ExecStart=/sbin/ethtool -K eth0 rx-udp-gro-forwarding on rx-gro-list off
    
    [Install]
    WantedBy=multi-user.target
    
  3. Reload systemd and enable the service:
    sudo systemctl daemon-reload
    sudo systemctl enable --now udpgroforwarding
    
  4. Reboot, then verify:
    ethtool -k eth0 | egrep "(gro-list|forwarding)"
    

    You should see:

    rx-gro-list: off
    rx-udp-gro-forwarding: on
    

Credit to @brkdncr for surfacing this tip and sharing a reproducible service example (Issue #1).

↑ Back to top


Additional notes

↑ Back to top


Conclusion

Self-hosting a VPN (and setting up an exit node) with Tailscale on a Raspberry Pi is not only fun but also a great way to improve your privacy and security while browsing the internet. If you’re interested in building a similar setup or want to ask questions about the process as I experienced it, feel free to leave a comment or reach out.

↑ Back to top


Maintainer note: Want to edit or contribute to this guide?
See 🧩 Run this site locally for setup instructions.


Support this project

Thank you, reader, for following along with me!

(^-^)/

☕ If this guide helped you set up your own Tailscale exit node, consider buying me a coffee on Ko-fi using the Support me button at the bottom left, or the one below. It keeps the Raspberry Pi humming, the coffee flowing, and new guides coming. 💻❤️

↑ Back to top


License

This project is licensed under the Creative Commons License - see the LICENSE file for details.