How I Secured My VPS with Tailscale and Cloudflare

Running a VPS with public services like a website can quickly become risky if ports are left wide open. I recently hardened my Ubuntu VPS using a combination of Tailscale, Cloudflare, and a strict UFW firewall for my private coding environment setup. This setup follows a true zero-trust model, ie nothing is trusted by default.


Initial Situation

My VPS had Nginx serving a website and SSH enabled. A quick check revealed the issue:

sudo ss -tulnp

Ports 22 (SSH), 80, and 443 were listening on 0.0.0.0, meaning they were potentially accessible to anyone scanning the public IP.


Step 1: Configure a Strict Firewall with UFW

I installed UFW and applied a default-deny policy for maximum security:

sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing


Key changes made:

  • Restricted SSH (port 22) to accept connections only from the Tailscale network range.
  • Removed all broad “Anywhere” rules for web ports 80 and 443.
  • Added precise allow rules for only Cloudflare’s official IP ranges (both IPv4 and IPv6). This allows legitimate traffic coming through Cloudflare while blocking everything else.
  • Allowed full access through the Tailscale interface for safe administration:
sudo ufw allow in on tailscale0

After applying the rules, I checked the final configuration:

sudo ufw status verbose


Step 2: Enable Tailscale SSH

In the Tailscale admin console, I enabled Tailscale SSH. This lets me connect securely using the VPS’s Tailscale IP instead of exposing the public SSH port.


Step 3: Verification

To confirm everything was working correctly:

  • I performed external port scans using nmap from a machine outside my Tailscale network.
  • Direct access to the VPS public IP (on ports 22, 80, or 443) was blocked or filtered.
  • The website continued to load normally when accessed through the Cloudflare-proxied domain.


Why This Setup Works So Well

This combination is effective because each tool plays a specific, complementary role:

  • Tailscale creates a private, encrypted mesh network. All administrative access (SSH, management, etc.) happens inside this trusted overlay network instead of over the public internet. No public SSH exposure means drastically fewer brute-force and scanning attacks.
  • Cloudflare acts as a smart reverse proxy. It handles DDoS protection, Web Application Firewall (WAF), and global caching. By restricting UFW to only allow Cloudflare’s IP ranges, I ensure the web server only accepts traffic that has already been filtered and validated by Cloudflare.
  • UFW serves as the final strict gatekeeper on the server itself. With a default-deny policy and very specific allow rules, even if something bypasses Cloudflare or Tailscale, the server still blocks unwanted traffic.


Together, they create defense-in-depth:

  • Visitors enjoy a fast, protected website via Cloudflare.
  • Administrators get secure, private access via Tailscale.
  • The VPS itself has a minimal attack surface.

The result is a much more secure server without sacrificing performance or usability.


Final Thoughts

This zero-trust approach — Tailscale for private access, Cloudflare for public services, and strict UFW rules — has significantly improved my VPS security. In the future, I plan to explore Cloudflare Tunnel for even stronger isolation (zero public ports at all).


Have you implemented a similar setup on your VPS? Do you prefer Tailscale, Cloudflare Tunnel, WireGuard, or another combination?

Note: This blog post was curated by AI. The ideas, thoughts, and real-world use cases described are entirely my own. Posts without this note are written solely by me.