Rewrite to another domain using Caddy v2

1. Output of caddy version:

v2.6.1 h1:EDqo59TyYWhXQnfde93Mmv4FJfYe00dO60zMiEt+pzo=

2. How I run Caddy:

I installed Cddy using sudo apt install caddy on my Ubuntu server, and I run it as a systemctl service.

a. System environment:

OS: Ubuntu 22.04 x64

b. Command:

systemctl reload caddy

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane. -->

d. My complete Caddy config:

/etc/caddy/ {
	root * /var/www/html/

	# 404 errors
	handle_errors {
		@404 {
			expression {http.error.status_code} == 404

		rewrite @404 /404.html
} {
	redir{uri} permanent
/etc/caddy/ {

:80 {
	# Set this path to your site's directory.
	root * /usr/share/caddy

	# Enable the static file server.

	# Another common task is to set up a reverse proxy:
	# reverse_proxy localhost:8080

	# Or serve a PHP site through php-fpm:
	# php_fastcgi localhost:9000

import ./

import ./

3. The problem I’m having:

So I have a static website hosted at and a NodeJS app with a reverse proxy on (see above Caddyfiles).

I want that if someone visits, they are shown the site, without changing the URL (so not a redirect).

4. Error messages and/or full log output:

Paste logs/commands/output here.

5. What I already tried:

I’ve tried rewrite /tools to and rewrite /tools to

6. Links to relevant resources:


Howdy @segbedji, welcome to the Caddy community. Thanks for filling out the help template! Your current config, good description of the problem and your goals, and what you’ve already tried give me a pretty good idea of what you’re after.

So: rewrites are totally agnostic of the domain; to a rewrite, the only thing that really exists is the URI.

You want to silently “rewrite” (kind of) the domain by reverse proxying, and rewrite the URI separately beforehand; just the URI. These are two separate operations for the webserver that can be done at the same time, but they both need to be configured.

There’s a few techniques you can use for this. The first is handle_path, which implicitly strips the path in question before passing it on: handle_path (Caddyfile directive) — Caddy Documentation {
  handle_path /tools* {

If you don’t want handle_path to do the prefix stripping implicitly, there’s the uri directive - which effectively just does rewrite under the hood, but is easy to wield - that you can use to manually specify the URI manipulation for this purpose: uri (Caddyfile directive) — Caddy Documentation

You could use it inside a handle: {
  handle /tools* {
    uri strip_prefix /tools

Or you can use a matcher to catch these requests: Request matchers (Caddyfile) — Caddy Documentation {
  @tools path /tools*
  uri @tools strip_prefix /tools
  reverse_proxy @tools

Finally, I note that you’re hosting on the same web server as, so instead of proxying from the latter to the former, you could reverse proxy directly from to your backend, skipping one request. You might need to set the Host header going upstream so the backend treats this request the same as it would a request to (See: reverse_proxy (Caddyfile directive) — Caddy Documentation) {
  handle_path /tools* {
    reverse_proxy {
      header_up Host

Hello @Whitestrake. Thank you so much. That’s a very great and helpful explanation. I never got to understand properly how rewrites work, and now I have a brief idea.

I went with the third option with a direct reverse proxy to the backend, and it works seamlessly.

Only thing remaining to figure out is how to properly handle the assets from the backend.

Thanks again :).


This topic was automatically closed after 30 days. New replies are no longer allowed.