DEV Community

Sam Newby for Vizalo

Posted on

3 1 1 1 1

Path-Based Reverse Proxying with Caddy

Caddy is a great web server built with Go and can be used for a multitude of things. Here at Vizalo we use it on nearly all of our servers that power our network.

This guide explains how to set up Caddy as a reverse proxy that routes traffic to different backend services based on URL paths. This is useful when you have multiple services running on different ports and want to expose them under a single domain.

Basic Setup

Create a Caddyfile in your project directory:

example.com {
    handle /api/* {
        reverse_proxy localhost:3000
    }

    handle /admin/* {
        reverse_proxy localhost:8080
    }

    handle /* {
        reverse_proxy localhost:5000
    }
}
Enter fullscreen mode Exit fullscreen mode

This configuration will:

  • Send /api/* requests to a service running on port 3000
  • Send /admin/* requests to a service running on port 8080
  • Send all other requests to port 5000

A More Complete Example

Here's a more practical example that includes common settings you might need:

example.com {
    # API Service
    handle /api/* {
        reverse_proxy localhost:3000 {
            header_up Host {upstream_hostport}
            header_up X-Real-IP {remote_host}
            header_up X-Forwarded-For {remote_host}
        }
    }

    # Admin Dashboard
    handle /admin/* {
        reverse_proxy localhost:8080 {
            # Health checks
            health_uri /health
            health_interval 30s

            # Timeout settings
            timeout 30s
        }
    }

    # Frontend App
    handle /* {
        reverse_proxy localhost:5000 {
            # Load balancing
            lb_policy round_robin
            lb_try_duration 30s
        }

        # Enable compression
        encode gzip
    }

    # Global options
    log {
        output file /var/log/caddy/access.log
        format json
    }
}
Enter fullscreen mode Exit fullscreen mode

Running Multiple Backend Services

For testing, you might run these simple backend services:

# API Service (Node.js/Express)
node api.js        # Runs on :3000

# Admin Dashboard (Go)
go run admin.go    # Runs on :8080

# Frontend (React)
npm start         # Runs on :5000
Enter fullscreen mode Exit fullscreen mode

Verifying the Setup

Test your configuration:

# Test API endpoint
curl example.com/api/users

# Test admin endpoint
curl example.com/admin/dashboard

# Test frontend
curl example.com
Enter fullscreen mode Exit fullscreen mode

Common Patterns

Stripping Path Prefixes

If your backend service doesn't expect the /api prefix:

handle /api/* {
    uri strip_prefix /api
    reverse_proxy localhost:3000
}
Enter fullscreen mode Exit fullscreen mode

Adding Headers

Add authentication headers or API keys:

handle /api/* {
    reverse_proxy localhost:3000 {
        header_up X-API-Key {env.API_KEY}
    }
}
Enter fullscreen mode Exit fullscreen mode

That's it. The beauty of Caddy is that it handles HTTPS certificates automatically and has sensible defaults for most settings. Most of the "extra" configurations shown above are only needed for specific use cases.

Image of AssemblyAI tool

Challenge Submission: SpeechCraft - AI-Powered Speech Analysis for Better Communication

SpeechCraft is an advanced real-time speech analytics platform that transforms spoken words into actionable insights. Using cutting-edge AI technology from AssemblyAI, it provides instant transcription while analyzing multiple dimensions of speech performance.

Read full post

Top comments (1)

Collapse
 
phocks profile image
Joshua Byrd • Edited

Thanks for this. Just pointing out that if you use this config and then try to go to /api (without the trailing slash) it will be handled by the end /* fallback. Seems like you can fix this by doing handle /api*

or by doing a redirect:

handle /art {
        redir * /art/
    }
Enter fullscreen mode Exit fullscreen mode

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay