Skip to content

buffpesos/vps-setup

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Securing Your VPS with Tailscale + Cloud Firewall

A practical guide to locking down any VPS (Hetzner, Hostinger, DigitalOcean, Vultr, etc.) so that admin interfaces like Coolify and SSH are only accessible through a private Tailscale network, while keeping public services (HTTP/HTTPS) open for your users.

What This Setup Achieves

  • Ports 80/443 — open to the public (your web apps, SSL cert generation)
  • SSH, Coolify dashboard, and all other ports — only accessible via Tailscale
  • Admin dashboards are invisible to the internet
  • No SSH brute-force attempts — port 22 is not publicly exposed
  • You can manage your server securely from anywhere via Tailscale

Prerequisites

  • A VPS with Ubuntu (22.04 or 24.04)
  • A Tailscale account (free for personal use)
  • Tailscale installed on your local machine (laptop/desktop)
  • Root/sudo access to the VPS

Step 1: Initial SSH Into Your Server

During initial setup, your VPS provider gives you an IP and SSH access. Use it now — we'll lock this down later.

ssh root@YOUR_SERVER_IP

If it asks "Are you sure you want to continue connecting?", type yes.


Step 2: Install Tailscale on the Server

curl -fsSL https://tailscale.com/install.sh | sh
tailscale up

This will print an authentication URL. Open it in your browser, log into your Tailscale account, and authorize the device.

Once authorized, get your server's Tailscale IP:

tailscale ip -4

This returns something like 100.85.99.49. Save this IP — this is how you'll access everything on your server from now on.


Step 3: Install Tailscale on Your Local Machine

If you haven't already, install Tailscale on your laptop/desktop:

Make sure you're logged into the same Tailscale account as your server.

Verify connectivity:

ping 100.x.x.x  # your server's Tailscale IP

Step 4: Verify Access via Tailscale

Before locking anything down, verify everything works through Tailscale.

SSH via Tailscale

ssh root@100.x.x.x  # Tailscale IP

Admin dashboard via Tailscale (e.g., Coolify)

http://100.x.x.x:8000

If both work, you're ready to lock down the firewall.


Step 5: Set Up the Cloud Firewall

Why Cloud Firewall Instead of UFW?

Docker bypasses UFW by directly modifying iptables rules. This means ufw deny 8000 will NOT block Docker-published ports. The most reliable solution is to use your VPS provider's cloud firewall, which operates at the network level before traffic even reaches your server.

Firewall Rules

Add only these inbound rules in your provider's firewall dashboard:

Protocol Port Source Purpose
TCP 80 Anywhere (0.0.0.0/0) HTTP — SSL cert generation (Let's Encrypt) + redirect to HTTPS
TCP 443 Anywhere (0.0.0.0/0) HTTPS — secure web traffic for your users
ICMP Anywhere (0.0.0.0/0) Ping — useful for diagnostics

That's it. No port 22. No port 8000. No other ports.

  • SSH (port 22) is NOT open publicly. You can only SSH via Tailscale.
  • Admin dashboards (port 8000, etc.) are NOT open publicly. Tailscale only.
  • All other ports are blocked from the public internet.

Outbound rules: Leave as default (allow all). Don't restrict outbound or you'll break things.

Why Port 80 Must Stay Open

Port 80 is required for Let's Encrypt SSL certificate generation and renewal. When you set up HTTPS for your domain, Let's Encrypt sends a verification request to port 80 to prove you own the domain. If blocked, your SSL certs will fail and HTTPS won't work. Port 80 also auto-redirects all traffic to HTTPS, so no unencrypted content is ever served.

Emergency Access Without Tailscale

If Tailscale goes down and you can't SSH in, every major VPS provider has a web console/VNC in their dashboard:

  • Hetzner: Server → Rescue → Console
  • Hostinger: VPS Dashboard → Browser Terminal
  • DigitalOcean: Droplet → Access → Launch Droplet Console
  • Vultr: Server → View Console

This gives you direct terminal access without needing SSH or Tailscale.

Provider-Specific Instructions

Hetzner Cloud

  1. Go to cloud.hetzner.comFirewallsCreate Firewall
  2. Add the three inbound rules above (TCP 80, TCP 443, ICMP)
  3. Under Apply to, select your server
  4. Create the firewall

Hostinger

  1. Go to your VPS dashboardFirewall
  2. Hostinger drops all incoming traffic by default
  3. Add Accept rules for TCP 80, TCP 443, and ICMP
  4. Save and activate

DigitalOcean

  1. Go to NetworkingFirewallsCreate Firewall
  2. Add the three inbound rules above
  3. Under Apply to Droplets, select your server
  4. Create the firewall

Vultr

  1. Go to ProductsNetworkFirewallAdd Firewall Group
  2. Add the three inbound rules above
  3. Link the firewall group to your server instance

Step 6: Test the Setup

After applying the firewall, run these tests:

Should NOT work (blocked by firewall)

# SSH via public IP — should timeout/refuse
ssh root@YOUR_PUBLIC_IP

# Admin dashboard via public IP — should timeout
http://YOUR_PUBLIC_IP:8000

SHOULD work (via Tailscale)

# SSH via Tailscale IP
ssh root@100.x.x.x

# Admin dashboard via Tailscale IP
http://100.x.x.x:8000

SHOULD work (public, for your users)

# Web traffic
http://YOUR_PUBLIC_IP        # port 80, redirects to HTTPS
https://yourdomain.com       # port 443

# Ping
ping YOUR_PUBLIC_IP

If public SSH and port 8000 timeout, but Tailscale access and HTTPS work — you're locked down!


How It Works

Public Internet                          Your Server
─────────────                          ──────────────
User → port 443    ──→  Cloud Firewall ──→  ✅ Allowed → Your Web App
User → port 80     ──→  Cloud Firewall ──→  ✅ Allowed → Redirect to HTTPS
User → port 22     ──→  Cloud Firewall ──→  ❌ Blocked
User → port 8000   ──→  Cloud Firewall ──→  ❌ Blocked

You (via Tailscale)                     Your Server
───────────────                         ──────────────
You → Tailscale encrypted tunnel ──→ (bypasses firewall) ──→  ✅ All ports
     ssh root@100.x.x.x                                       SSH, Coolify,
     http://100.x.x.x:8000                                    databases, etc.

Tailscale creates an encrypted WireGuard tunnel between your devices. Traffic through this tunnel arrives on a virtual network interface (tailscale0) directly on the server, completely bypassing the cloud firewall.


Day-to-Day Usage

SSH into your server

ssh root@100.x.x.x  # Always use Tailscale IP

Access Coolify dashboard

http://100.x.x.x:8000

Access any other admin interface

http://100.x.x.x:PORT

Adding more devices to your network

Install Tailscale on any device and log into the same account. It automatically joins the network — no config needed.

Adding more servers

Repeat Steps 1-5 for each new VPS. All your Tailscale devices can communicate with each other automatically through the mesh network.


Optional: Extra Hardening

Disable Root Password Login

Since SSH is already behind Tailscale, this adds another layer:

nano /etc/ssh/sshd_config

Set:

PermitRootLogin prohibit-password
PasswordAuthentication no

Restart SSH:

systemctl restart sshd

Create a Non-Root User

adduser deploy
usermod -aG sudo deploy

Copy your SSH key to the new user:

mkdir -p /home/deploy/.ssh
cp ~/.ssh/authorized_keys /home/deploy/.ssh/
chown -R deploy:deploy /home/deploy/.ssh

Then SSH as: ssh deploy@100.x.x.x

Keep Your System Updated

apt update && apt upgrade -y

Back Up Your Coolify .env

As Coolify warns on install, back up this file somewhere safe (not on the server):

cat /data/coolify/source/.env

Save the contents to a password manager or secure notes app.


Troubleshooting

Can't SSH at all after enabling firewall

Port 22 is intentionally blocked publicly. Use your Tailscale IP:

ssh root@100.x.x.x

If Tailscale is also not working, use your VPS provider's web console/VNC as emergency access.

Tailscale IP doesn't work from my laptop

Make sure Tailscale is running and connected on both your laptop and the server:

tailscale status

Check that both devices are listed and online.

Port 8000 is still accessible publicly after firewall

Double-check the firewall is applied to the correct server in your provider's dashboard. Some providers require you to explicitly assign the firewall to a server after creating it.

SSL certificates not generating

Make sure port 80 is open in your cloud firewall. Let's Encrypt requires port 80 for domain verification. Also ensure your domain's DNS A record points to the server's public IP.

Coolify shows "connection refused" via Tailscale

Verify Tailscale is connected on the server:

tailscale status

Then check Coolify is running:

docker ps | grep coolify

Summary

What Access Method
Your web apps (HTTPS) Public — https://yourdomain.com
SSL cert generation Public — port 80 (auto, handled by Let's Encrypt)
SSH Tailscale only — ssh root@100.x.x.x
Coolify dashboard Tailscale only — http://100.x.x.x:8000
Any other admin ports Tailscale only — http://100.x.x.x:PORT
Emergency access VPS provider's web console/VNC
Ping Public — for diagnostics

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published