The way we host applications is changing fast.
A few years ago, spinning up a VPS or cloud virtual machine, assigning a public IP, opening ports 22, 80, and 443, and calling it a day was normal. That approach is becoming increasingly risky. Automated scanners, AI-assisted vulnerability discovery, and constant probing of public IP ranges mean that any service exposed directly to the internet is under continuous attack.
I recently went through the process of hardening a production environment while building Blast Post, a social media scheduling platform. During that work I moved away from the traditional “public IP + open ports” model and adopted a combination of Tailscale and Cloudflare Tunnel. The difference in security posture is significant.
This article explains why the old model is breaking down, what the new recommended architecture looks like, and how you can apply it to Azure VMs, AWS EC2, Google Cloud VMs, or any regular VPS.
Why Public IPs on VPS and Cloud VMs Are Becoming Dangerous
Every cloud provider and VPS host still makes it easy to attach a public IP. The problem is not the IP itself — it is what that IP represents: a permanent, reachable address that anyone on the internet can probe.
Attackers (and now AI-assisted tools) continuously scan large ranges of public IPs looking for:
- Open SSH ports (default port 22)
- Outdated software with known CVEs
- Misconfigured web servers
- Exposed databases or admin panels
- Services with weak or default credentials
Even if you use SSH key authentication and keep your system updated, the attack surface remains large. A single zero-day in OpenSSH, a web framework, or a system dependency can turn a public IP into an entry point. The number of automated probes hitting any public IP within minutes of it being assigned is not hypothetical — it is measurable in server logs.
Pieter Levels (levels.io) highlighted this exact issue publicly. He recommended taking VPS instances off the public internet wherever possible and routing both administrative access and web traffic through more controlled channels. That recommendation reflects what many operators are experiencing in practice in 2026.
The Two Main Attack Paths on a Typical Server
There are two primary ways an attacker reaches a server:
- Through the application — web exploits, file upload vulnerabilities, SQL injection, authentication bypasses, dependency vulnerabilities
- Through the server itself — SSH brute force, open management ports, services accidentally exposed on public interfaces
Traditional hardening tries to make both paths difficult: strong SSH config, firewall rules, fail2ban, regular patching. The modern approach goes further — it removes the public-facing paths entirely wherever possible.
The Modern Architecture: Tailscale + Cloudflare Tunnel
The combination gaining strong traction among solo developers and small teams is:
- Tailscale for private administrative access (SSH, database connections, internal tools)
- Cloudflare Tunnel for public web traffic (HTTP/HTTPS serving)
How Tailscale Works for Server Access
Tailscale builds a private encrypted mesh network (called a “tailnet”) between your devices and servers using WireGuard as its underlying protocol. WireGuard is a modern, audited VPN protocol that is significantly simpler and faster than OpenVPN or IPsec. Once a server joins your tailnet:
- You SSH to it using a stable private IP address in the
100.64.0.0/10CGNAT range (e.g.100.x.x.x) - Port 22 does not need to be open on any public firewall
- Access is controlled by identity and device membership in your tailnet, not by IP allow-lists
- The connection traverses NAT automatically using DERP relay servers when direct UDP paths are unavailable
The setup is: install Tailscale on the server, run tailscale up and authenticate, confirm you can SSH over the Tailscale IP, then remove port 22 from all public inbound rules. From that point, SSH is only reachable by devices already authenticated to your tailnet.
Tailscale also supports ACLs (Access Control Lists) in its admin panel, so you can restrict which users or devices can reach which servers — useful if you are working in a team.
How Cloudflare Tunnel Works for Web Traffic
Cloudflare Tunnel works through the cloudflared daemon you run on your server. This daemon establishes persistent outbound connections to Cloudflare’s edge network. Your public website or API is then proxied through Cloudflare to users — without your server ever accepting inbound connections on ports 80 or 443.
Key advantages:
- Ports 80 and 443 can stay closed on the server’s public firewall
- The application can bind to
localhostonly — it never needs to be reachable from outside directly - Cloudflare’s WAF (Web Application Firewall), DDoS protection, and bot management protect the public endpoint — available on the free plan
- The server’s public IP is no longer the ingress point for web traffic
Because the server initiates connections outward, an attacker scanning the public IP finds no open ports to target for the web application.
Why This Combination Is Stronger Than Traditional Hardening
| Approach | SSH Exposure | Web Exposure | DDoS Protection | Complexity |
|---|---|---|---|---|
| Public IP + open ports | High | High | Provider-level only | Low |
| Public IP + strict firewall | Medium | Medium | Limited | Medium |
| Tailscale + Cloudflare Tunnel | Very Low | Proxied via Cloudflare | Strong (Cloudflare edge) | Medium |
By removing inbound listeners, you eliminate an entire class of automated attacks — port scanners, brute-force bots, and opportunistic exploit scripts have nothing to connect to. The remaining attack surface shrinks to:
- Compromising a device or identity already in your Tailscale tailnet
- Finding an application-level vulnerability that bypasses Cloudflare’s WAF
- Compromising your Cloudflare or Tailscale account directly
This is a substantially smaller surface than a permanently open port 22 and open web ports.
Practical Application Across Cloud Providers and VPS Hosts
The same pattern applies regardless of where the server runs:
- Azure VM: Keep a public IP for outbound connectivity if needed, but set the Network Security Group (NSG) to deny all inbound traffic. Serial Console remains available for emergency access via the Azure portal.
- AWS EC2: Lock Security Groups to deny all inbound. Use EC2 Instance Connect or Systems Manager Session Manager as a recovery fallback.
- Google Cloud VM: Remove ingress firewall rules. Cloud Console SSH via IAP (Identity-Aware Proxy) stays available as a recovery path.
- Hetzner, DigitalOcean, Linode, Vultr (regular VPS): Use the provider’s cloud firewall to deny all inbound. The provider’s web console or out-of-band access (VNC/KVM) serves as fallback.
In all cases the server still requires outbound internet access so that tailscaled and cloudflared can maintain their connections to their respective networks. Blocking outbound traffic breaks both services.
Implementation Steps (High Level)
- Install Tailscale on the server:
curl -fsSL https://tailscale.com/install.sh | sh, thensudo tailscale up - Authenticate the server to your tailnet via the URL printed in the terminal
- Install Tailscale on your personal devices (laptop, workstation) and join the same tailnet
- Confirm SSH works over the Tailscale IP (
ssh user@100.x.x.x) before closing any ports - Install cloudflared on the server and authenticate:
cloudflared tunnel login - Create a tunnel and route a hostname to your local application:
cloudflared tunnel route dns <tunnel-name> yourdomain.com - Configure the tunnel to forward traffic from the hostname to
http://localhost:<port> - Test that the public hostname resolves and the application is reachable through Cloudflare
- Close public inbound ports (22, 80, 443) in the provider firewall or security group
- Verify that direct access to the public IP no longer works for SSH or HTTP
Important: Always keep a recovery path — Azure Serial Console, EC2 SSM Session Manager, provider VNC/KVM — until you have confirmed the new access methods are reliable. Locking yourself out of a production server without a fallback is a real risk.
Security Considerations and Honest Limitations
This architecture is significantly stronger than leaving services open, but it is not a complete solution on its own:
- Tailscale account security matters. Enable MFA on your Tailscale account. If the account is compromised, all servers in your tailnet are reachable.
- Cloudflare is now part of your trust boundary. Cloudflare terminates TLS and can see plaintext traffic. For most applications this is acceptable, but it is worth understanding.
- Outbound connectivity is required. If your outbound network is restricted, both services will fail. Plan accordingly.
- Application vulnerabilities are still your responsibility. Cloudflare’s WAF catches many common attacks but is not a substitute for secure application code, dependency management, or input validation.
cloudflaredprocess must stay running. Use a process manager (systemctl) to keep it alive across reboots.
The goal is not perfect security — that does not exist. The goal is to eliminate the easy, automated, high-volume attack paths that are actively targeting public IPs at scale.
How This Relates to Building Blast Post
While building Blast Post — a social media scheduling and cross-posting platform for creators, agencies, and small teams — I applied exactly this model. The application needs to be publicly reachable for users, but the underlying server infrastructure and SSH access do not need to be exposed to the internet.
The same principles that shaped the infrastructure decisions also inform product decisions in Blast Post: minimize unnecessary exposure, prefer well-understood patterns over clever ones, and treat security as a baseline rather than an afterthought. If you are running an application that handles user data, scheduled jobs, or API keys for third-party platforms, reducing the public attack surface of your host is a reasonable baseline requirement in 2026.
Final Recommendation
If you currently run a VPS or cloud VM with a public IP and open management ports, evaluating Tailscale for private access and Cloudflare Tunnel for web traffic is a practical next step. The initial setup takes a few hours. The ongoing reduction in risk is continuous.
The old model — “public IP + open ports + correct firewall rules + hope” — is increasingly fragile as scanning and exploitation become more automated. Moving administrative access into a private network and public traffic through a well-managed edge is becoming the standard approach for small and medium deployments in 2026.
The recommended sequence:
- Set up Tailscale and confirm private SSH works
- Set up Cloudflare Tunnel and confirm public web traffic works through it
- Close inbound ports on the provider firewall
- Test every access path thoroughly
- Document your recovery procedure
The internet is more aggressive than it was. Your infrastructure should reflect that.
Last Updated: October 27, 2026 | If this helped you, consider sharing it with someone running an unprotected VPS.