Run Multiple Cloudflare Tunnels on a Single VPS Effortlessly

Learn how to efficiently manage multiple domains with Cloudflare tunnels on one Ubuntu server without complex setups.

·Matija Žiberna·
Run Multiple Cloudflare Tunnels on a Single VPS Effortlessly

☁️ Cloudflare Edge Development Guides

Complete Cloudflare guides with practical examples, deployment strategies, and developer prompts to help you build and ship edge applications faster.

No spam. Unsubscribe anytime.

If you’ve followed my previous guide on exposing Docker containers with Cloudflared and no open ports, you’ve seen how easy it is to set up a single Cloudflare Tunnel for one domain.

But things get tricky once you try to manage multiple domains or zones from the same VPS.

I recently needed to run two separate domains — each with its own Docker services — behind Cloudflare Tunnels on a single Ubuntu server. That’s when I discovered how limited the traditional CLI setup is for multi-zone configurations, and how moving to Cloudflare’s remotely managed tunnels completely fixes the problem.

This article walks you through the exact setup, what went wrong, and how to do it the right way.


Problem: Only One Zone Authenticated per VPS

When you first authenticate Cloudflared using:

cloudflared login

Cloudflare issues a file called cert.pem and ties it to one specific zone. That file lives in ~/.cloudflared/ and all your tunnels rely on it.

So if you have:

  • api.example-one.com → Port 8585
  • automate.example-two.com → Port 5678

You quickly run into problems because the CLI tools assume a single zone per certificate.

When I tried to link my second tunnel to another domain, I kept hitting this message:

INF example-two.com is already configured to route to your tunnel tunnelID=c101ebf4...

Or worse, when switching certs, the existing tunnels broke entirely with:

Error 1033: Cloudflare Tunnel error

Even re-logging in or exporting the certificate path didn’t help for long:

export TUNNEL_ORIGIN_CERT=/home/user/.cloudflared/cert.pem

Eventually, I realized this setup simply isn’t meant for multiple zones.


The Wrong Approach (and Why It Fails)

Here’s what I tried, and what failed along the way:

AttemptCommand / ActionOutcome
Created multiple tunnels via CLIcloudflared tunnel create nameEach tunnel tied to one zone only
Tried to rerun cloudflared loginSwitched zone but broke existing tunnel
Added multiple config files in /etc/cloudflaredOnly one could be active at a time
Used --config and --credentials-file flagsSome flags unsupported by service install
Installed as a systemd service manuallyWorked for one tunnel, not multiple
Ran tunnels with sudoLost TUNNEL_ORIGIN_CERT path, missing cert.pem
Got 1033 errorTunnel connected but no matching route in DNS

At that point, it was clear: the CLI + cert.pem model is designed for single-zone setups. The fix was to switch to the modern, token-based (remotely managed) approach.


Solution: Manage Each Tunnel via the Cloudflare Dashboard

The modern approach uses Cloudflare Zero Trust to manage tunnels remotely. Instead of dealing with local certificates, you connect each tunnel via a unique token.

This allows you to:

  • Run multiple tunnels (one per domain) on the same VPS
  • Keep all zones authenticated in the dashboard
  • Manage routing (CNAMEs, hostnames, ports) centrally via UI
  • Avoid cert.pem conflicts or 1033 errors

Step 1: Create a New Tunnel in Cloudflare Zero Trust

  1. Go to Cloudflare Dashboard → Zero Trust → Networks → Tunnels
  2. Click Create a Tunnel
  3. Choose Cloudflared
  4. Name your tunnel (e.g., api-tunnel or automation-tunnel)
  5. Copy the provided installation command — it’ll look like this:
sudo cloudflared service install eyJhIjoiMWFhY2Y4Y...

That eyJ... string is your tunnel token — a secure way to authenticate the tunnel to Cloudflare without a cert.


Step 2: Run the Tunnel on Your VPS

If Cloudflared isn’t installed yet:

sudo apt install cloudflared

Then paste the command you copied earlier:

sudo cloudflared service install eyJhIjoiMWFhY2Y4Y...

This automatically installs a system service (cloudflared) that connects your server to Cloudflare and starts at boot.

You can verify it’s connected by checking:

sudo systemctl status cloudflared

or

cloudflared tunnel info

Step 3: Add a Public Hostname (Map to Your Docker Service)

In the Cloudflare dashboard:

  1. Open your new tunnel
  2. Scroll to Public Hostnames
  3. Click Add a public hostname

Fill in the following:

FieldExampleDescription
SubdomainapiFor api.example-one.com
Domainexample-one.comChoose from dropdown
TypeHTTP
URLhttp://localhost:8585Your Docker container port
Path(leave blank)Optional if you want full domain routing

Then click Save hostname

📸 Screenshot opportunity #1 — Add Public Hostname form

Repeat this process for every local service or domain you want to expose.


Step 4: Add Another Tunnel for Another Zone

To connect a second domain (different zone):

  1. Go back to Tunnels → Create a Tunnel
  2. Repeat the steps above (new token, new tunnel name)
  3. Run the second install command on the same VPS

Example:

sudo cloudflared service install eyJhbGciOiJIUzI1...

Then add a new public hostname for that zone, such as:

HostnamePortDescription
automation.example-two.com5678Dockerized n8n instance

📸 Screenshot opportunity #2 — multiple tunnels in Cloudflare dashboard

Cloudflare will manage both tunnels independently, each linked to its zone.


Step 5: Test Everything

Once both tunnels are running, visit your domains:

  • https://api.example-one.com → should proxy to your local API
  • https://automation.example-two.com → should proxy to your n8n instance

To confirm both connectors are live:

cloudflared tunnel list

You should see both tunnel IDs listed and connected.


Common Errors and Fixes

ErrorCauseFix
Error 1033: Cloudflare Tunnel errorTunnel not running or hostname not mappedStart cloudflared or add hostname in dashboard
Cannot determine default origin certificate pathMissing or wrong cert.pemNot needed for token-based tunnels
flag provided but not defined: -configOlder cloudflared versionUse --config before run, or upgrade
wrong zone configuredTried to route via CLISwitch to dashboard-based hostnames
Tunnel stops when you run anotherSame cert.pem reusedEach managed tunnel uses its own token

Step 6: Optional – Connect to Docker Network by Name

If your services run under Docker with custom networks, you can refer to containers by name:

http://n8n:5678

To make this work:

  • Add cloudflared to the same Docker network
  • Or keep using localhost:<port> if the container is exposed to the host

📸 Screenshot opportunity #3 — Docker network diagram (optional)


Conclusion

If you’re managing more than one domain on a single VPS, don’t fight the CLI. Use Cloudflare’s remotely managed tunnels instead.

This approach removes the one-zone limitation, eliminates cert conflicts, and lets you manage everything visually in the dashboard — one connector per zone, all running side by side on your VPS.

You’ll never have to touch cert.pem or deal with the --config flag again.

Hope this helps other developers who hit the same wall I did when scaling beyond a single domain.

Thanks, Matija

0

Comments

Leave a Comment

Your email will not be published

10-2000 characters

• Comments are automatically approved and will appear immediately

• Your name and email will be saved for future comments

• Be respectful and constructive in your feedback

• No spam, self-promotion, or off-topic content

Matija Žiberna
Matija Žiberna
Full-stack developer, co-founder

I'm Matija Žiberna, a self-taught full-stack developer and co-founder passionate about building products, writing clean code, and figuring out how to turn ideas into businesses. I write about web development with Next.js, lessons from entrepreneurship, and the journey of learning by doing. My goal is to provide value through code—whether it's through tools, content, or real-world software.