How to Expose Your Rails Localhost Securely Using Cloudflare Tunnel.

Published on December 02, 2025
Written by Victor Cobos

When you’re building web applications, most of the work happens safely on localhost. But every now and then, you need the outside world to reach into your development environment. Maybe you’re integrating a payment provider that sends webhooks, testing OAuth redirects, sharing a feature preview with a teammate, or demoing progress to a client. In all of these cases, your local Rails server needs a temporary window to the internet.

Traditionally, tools like Ngrok have filled that gap — simple, fast, and wildly popular. But they come with limitations: short-lived URLs, rate limits, and features locked behind paid plans. Recently, I’ve been using Cloudflare Tunnel instead, and it’s quickly become my preferred way to expose a local Rails app. It’s secure, stable, completely free, and surprisingly easy to set up.

Why Cloudflare Tunnel?

Cloudflare Tunnel works differently from traditional tunneling tools. Instead of opening a port on your machine and forwarding traffic through a third-party service, it creates an outbound, encrypted connection from your computer directly to Cloudflare’s network. The result is a stable public URL, automatic HTTPS, and no need to poke holes in your firewall or router. And because the connection is outbound, it works even behind strict corporate networks.

Best of all: it’s free. Completely. No time limits, no rotating URLs, no upgrade to Pro banners just to get a persistent domain. If you already use Cloudflare to manage your DNS, you’re basically one command away from exposing your local Rails app to the world.

There are actually two different ways to expose your Rails app using Cloudflare Tunnel, depending on whether you need something quick and temporary or something stable and tied to your own domain.
The first method is a fast, zero-setup option that gives you a public URL in seconds. The second method requires a bit more configuration but gives you a permanent, HTTPS-secured subdomain you can use again and again. Let’s look at both approaches.

Option 1: Quick Tunnel using TryCloudflare — super fast & no setup

This is the fastest, easiest way to get a public URL to your local Rails app — no DNS, no account, no custom domain required.

How it works

1. Follow these instructions to install cloudflared

2. Make sure your Rails server is running (e.g. on localhost:3000)

3. Run one simple command:

cloudflared tunnel --url http://localhost:3000

cloudflared will connect to Cloudflare’s network, and in return provide a random public URL — something like https://modern-stack-42d9.trycloudflare.com

4. Share that URL with anyone:

They’ll connect through Cloudflare’s global edge network, which then forwards requests to your local Rails app. HTTPS + DDoS-protected by default.

Pros

  • Instant: one command and you’re online. No DNS or domain setup.
  • Free and anonymous: you don’t need a Cloudflare account or to own a domain.
  • Good for quick testing, demos, webhooks, or sharing a temporary build.

Cons

  • URL is random and changes every time you re-run the tunnel. Not ideal for long-term sharing.
  • There is a limit on concurrent proxied requests (e.g. 200 in-flight requests). If exceeded, you may see HTTP 429 errors.
  • Doesn’t support custom domains or advanced routing.
  • Not suitable for production — meant for quick experiments, local dev, or ephemeral demos.

In short: Quick Tunnels / TryCloudflare are perfect when you just want to spin up a public URL in 30 seconds to test a webhook, show a quick demo to a client, or let a friend see your work — no strings attached.

Option 2: Full Cloudflare Tunnel — custom domain, stable URL, more control

If you want something more stable, repeatable, or “production-like” — e.g. a fixed subdomain, own domain name, ability to integrate with DNS, maybe share with teammates / clients over days — you go with the full version of Cloudflare Tunnel.

This assumes you already have the cloudflared CLI installed — now we’ll use it to create a permanent tunnel connected to your own domain.

1. Log in to Cloudflare

First, authenticate cloudflared with your Cloudflare account:

cloudflared tunnel login

This opens a browser window where you select the domain you want to use. After approving, Cloudflare stores a certificate on your machine so cloudflared can create tunnels and manage DNS entries for that domain.

2. Create a named tunnel

Next, create a tunnel and give it a memorable name, for example:

cloudflared tunnel create rails-app

This command generates:

  • a tunnel ID
  • a credentials JSON file in ~/.cloudflared/

That JSON file is what identifies your tunnel and must be referenced in your config.

3. Create a config file for your Rails app

Now define how requests should be routed from the public internet to your local Rails server.
Create config/cloudflare-tunnel.yml with the following contents:

# config/clouflare-tunnel.yml
tunnel: rails-app
credentials-file: /Users/victor/.cloudflared/e487a6d4-a917-469e-b79c-294d27fc1d70.json

ingress:
  - hostname: rails-app.dotruby.dev
    service: http://localhost:3000
  - service: http_status:404

Replace:

  • rails-app with the name of your tunnel (if you used something else)
  • /Users/victor/.cloudflared/... with your actual absolute path
  • rails-app.dotruby.dev with the hostname you want to use

The ingress rules say traffic for rails-app.dotruby.dev should go to your Rails app on http://localhost:3000 and everything else should return a 404.

A quick gotcha: use the full path for credentials-file. Cloudflare does not expand $HOME or ~ in the credentials-file path.

4. Validate your tunnel config

Before moving on, let’s check that the config is valid:

cloudflared tunnel --config config/cloudflare-tunnel.yml ingress validate rails

If everything is fine, you’ll see an OK and you know the YAML + ingress rules are correct.

5. Add an example config to git (optional but nice 😉)

You usually don’t want to commit your real tunnel ID and credentials path, but it’s useful to have an example config in the repo so others (or future you) can copy it.
A common pattern:

echo config/cloudflare-tunnel.yml >> .gitignore
cp config/cloudflare-tunnel.yml config/cloudflare-tunnel.yml.example

Then edit config/cloudflare-tunnel.yml.example and redact the sensitive bits:

# config/cloudflare-tunnel.yml.example
tunnel: CHANGE_ME
credentials-file: CHANGE_ME

ingress:
  - hostname: rails-app.dotruby.dev
    service: http://localhost:3000
  - service: http_status:404

Finally:

git add config/cloudflare-tunnel.yml.example

Now your teammates (or future you) can copy the example file, fill in their own tunnel name and credentials path, and be ready to go.

6. Add the DNS record

Next, tell Cloudflare to route your chosen hostname through the tunnel:

cloudflared tunnel route dns rails-app rails-app.dotruby.dev

This creates the appropriate DNS record so that rails-app.dotruby.dev resolves via your tunnel.

7. Run the tunnel

You’re ready to start the tunnel:

cloudflared tunnel --config config/cloudflare-tunnel.yml run

If everything is set up correctly, https://rails-app.dotruby.dev will now forward to your local Rails app running on http://localhost:3000.

8. Allow the hostname in Rails

By default, Rails protects you from unexpected hostnames. To avoid Blocked host errors in development, you need to add your tunnel hostname to the allowed list.
In config/environments/development.rb:

# config/environments/development.rb

Rails.application.configure do
    # ...

    config.hosts << "rails-app.dotruby.dev"
end

You can also configure things like mailers to use this host if you rely on full URLs in emails:

config.action_mailer.default_url_options = {
    host: "rails-app.dotruby.dev",
    protocol: "https"
}

And just like that, your local Rails app is accessible through a clean, permanent HTTPS domain.

Pros:

  • Stable, reusable URL: You get a predictable domain like dev.example.com — perfect for testing webhooks, OAuth redirects, or sharing with teammates and clients.

  • Automatic HTTPS: Cloudflare handles certificates for you. Your dev environment runs behind real TLS, closer to how your production app works.

  • Runs behind any network: Corporate firewalls, NAT, hotel Wi-Fi — doesn’t matter. All traffic is outbound from cloudflared, so you rarely need to adjust anything.

  • Integrated with DNS: Your custom domain makes debugging and testing much more realistic than using a randomly generated subdomain.

  • Secure by default: Requests go through Cloudflare’s edge network. Your local machine is never exposed directly.

  • Tunnels work for multiple services: You can forward multiple hostnames or paths to different local servers if needed (Rails + Sidekiq UI, Rails + vite dev server, etc.).

Cons

  • More configuration overhead: You have to create a tunnel, write a config file, update DNS, and manage credentials. Not a “one command and done” workflow.

  • Requires owning a domain: Unlike Quick Tunnels, this method depends on Cloudflare DNS. If you don’t already use Cloudflare for a domain, setup is slower.

  • Not ideal for extremely quick tests: If you just need a temporary URL for 30 seconds, Quick Tunnel is easier.

🎁 Bonus: Make the tunnel easy to run

Starting cloudflared in a separate terminal tab gets old quickly. The good news: both options — Quick Tunnel and the full, named tunnel — can be wired into your usual dev workflow.

You’ve got two nice options: use a Procfile or add a small bin/cloudflared helper script.

Option A: Add Cloudflare to your Procfile

If you’re already using a Procfile / Procfile.dev (for example with bin/dev, Foreman, Overmind, etc.), just add a tunnel process next to your Rails server.

# Quick Tunnel:
tunnel: cloudflared tunnel --url http://localhost:3000

# Full, named tunnel:
tunnel: cloudflared tunnel --config config/cloudflare-tunnel.yml run

Now when you run your usual dev command (for example bin/dev or foreman start), Rails and the tunnel start together, and you’re instantly online.

Option B: Create a tiny bin/cloudflared helper

If you prefer to keep things manual but easy to remember, add a small script:

# bin/cloudflared
#!/usr/bin/env bash
set -e

# Quick Tunnel:
# cloudflared tunnel --url http://localhost:3000

# Full, named tunnel:
cloudflared tunnel --config config/cloudflare-tunnel.yml run

Make it executable:

chmod +x bin/cloudflared

Now you can just run:

bin/cloudflared

Wrapping up

Once you’ve wired Cloudflare Tunnel into your dev setup, you stop thinking of it as a trick and start treating it as a superpower. Share a preview, test a webhook, run OAuth flows — all from plain old localhost. Go ahead and add it to your toolbox; your Rails app will never feel boxed in again.

References

Subscribe to get future articles via the RSS feed .