Reverse proxy only a certain path

1. Caddy version (caddy version):

v2.3.0

2. How I run Caddy:

Default systemd service provided by ubuntu

a. System environment:

Ubuntu 20.04 via systemd

b. Command:

Systemd service

c. Service/unit/compose file:

Default provided by ubuntu

d. My complete Caddyfile or JSON config:

www.domain.com {
  # The import is for DNS certificate management
  import cert-1
  encode gzip zstd
  reverse_proxy /route/* differ.domain.com {
    header_up +X-Du-Token ***********
    header_up +X-Du-IP {header.X-Forwarded-For}
  }
  root * /var/www/www
  php_fastcgi * unix//run/php/php7.4-fpm.sock
  file_server
  push
}

3. The problem I’m having:

I want /route/* to be proxied to differ.domain.com, with the two headers added, and everything else to the FastCGI handler. However, everything is getting passed to the FastCGI handler, and the reverse_proxy seemingly ignored.

4. Error messages and/or full log output:

N/A

5. What I already tried:

See: config snippet provided

6. Links to relevant resources:

n/a

Okay, looks like the /route/* has to come after the main part

I’m not sure what you mean by “after the main part”.

Caddy directives are sorted according to this pre-determined order:

I would recommend configuring your site like this, because it’s clearer when using handle how requests are being routed:

www.domain.com {
	# The import is for DNS certificate management
	import cert-1

	push
	encode gzip zstd

	handle /route/* {
		reverse_proxy http://differ.domain.com {
			header_up X-Du-Token ***********
			header_up X-Du-IP {header.X-Forwarded-For}
		}
	}

	# Fallback for requests not otherwise handled
	handle {
		root * /var/www/www
		php_fastcgi * unix//run/php/php7.4-fpm.sock
		file_server
	}
}

The handle directive lets you define mutually-exclusive blocks, so things from one block won’t affect another.

1 Like

If i define /route/* before the * directive, /route/* does not apply. If I define after, it works fine. Intended behavior or not, I cannot say.

Here’s what works

www.domain.com {
  import cert-1
  encode gzip
  root * /var/www/www
  php_fastcgi * unix//run/php/php7.4-fpm.sock
  reverse_proxy /route/* differ.domain.com {
    header_up X-Du-Token ****************
    header_up X-Du-IP {http.request.remote}
  }
  file_server
  push
}

The order in which you define directives in the Caddyfile does not matter. You can verify this by running caddy adapt --pretty and comparing. The Caddyfile adapter will sort directives before outputting the underlying JSON config.

Nonetheless unless I define them in the order its in right now, they do not work. The order you provided (albeit not the syntax) results in a WordPress 404 page (hint: means it’s getting passed to php_fastcgi)

Adapting your config from your original post (and removing import cert-1 because you didn’t include it in what you posted – please don’t omit config next time you ask questions!):

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "www.domain.com"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "vars",
                          "root": "/var/www/www"
                        },
                        {
                          "encodings": {
                            "gzip": {},
                            "zstd": {}
                          },
                          "handler": "encode"
                        },
                        {
                          "handler": "push"
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "headers": {
                            "request": {
                              "add": {
                                "X-Du-Ip": [
                                  "{http.request.header.X-Forwarded-For}"
                                ],
                                "X-Du-Token": [
                                  "***********"
                                ]
                              }
                            }
                          },
                          "upstreams": [
                            {
                              "dial": "differ.domain.com:80"
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "/route/*"
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "static_response",
                          "headers": {
                            "Location": [
                              "{http.request.uri.path}/"
                            ]
                          },
                          "status_code": 308
                        }
                      ],
                      "match": [
                        {
                          "file": {
                            "try_files": [
                              "{http.request.uri.path}/index.php"
                            ]
                          },
                          "not": [
                            {
                              "path": [
                                "*/"
                              ]
                            }
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "rewrite",
                          "uri": "{http.matchers.file.relative}"
                        }
                      ],
                      "match": [
                        {
                          "file": {
                            "split_path": [
                              ".php"
                            ],
                            "try_files": [
                              "{http.request.uri.path}",
                              "{http.request.uri.path}/index.php",
                              "index.php"
                            ]
                          }
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "transport": {
                            "protocol": "fastcgi",
                            "split_path": [
                              ".php"
                            ]
                          },
                          "upstreams": [
                            {
                              "dial": "unix//run/php/php7.4-fpm.sock"
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "*.php"
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "file_server",
                          "hide": [
                            ".\\Caddyfile"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

And adapting your config you said works:

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "www.domain.com"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "vars",
                          "root": "/var/www/www"
                        },
                        {
                          "encodings": {
                            "gzip": {}
                          },
                          "handler": "encode"
                        },
                        {
                          "handler": "push"
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "headers": {
                            "request": {
                              "set": {
                                "X-Du-Ip": [
                                  "{http.request.remote}"
                                ],
                                "X-Du-Token": [
                                  "****************"
                                ]
                              }
                            }
                          },
                          "upstreams": [
                            {
                              "dial": "differ.domain.com:80"
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "/route/*"
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "static_response",
                          "headers": {
                            "Location": [
                              "{http.request.uri.path}/"
                            ]
                          },
                          "status_code": 308
                        }
                      ],
                      "match": [
                        {
                          "file": {
                            "try_files": [
                              "{http.request.uri.path}/index.php"
                            ]
                          },
                          "not": [
                            {
                              "path": [
                                "*/"
                              ]
                            }
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "rewrite",
                          "uri": "{http.matchers.file.relative}"
                        }
                      ],
                      "match": [
                        {
                          "file": {
                            "split_path": [
                              ".php"
                            ],
                            "try_files": [
                              "{http.request.uri.path}",
                              "{http.request.uri.path}/index.php",
                              "index.php"
                            ]
                          }
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "transport": {
                            "protocol": "fastcgi",
                            "split_path": [
                              ".php"
                            ]
                          },
                          "upstreams": [
                            {
                              "dial": "unix//run/php/php7.4-fpm.sock"
                            }
                          ]
                        }
                      ],
                      "match": [
                        {
                          "path": [
                            "*.php"
                          ]
                        }
                      ]
                    },
                    {
                      "handle": [
                        {
                          "handler": "file_server",
                          "hide": [
                            ".\\Caddyfile"
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    }
  }
}

The only differences I see in the JSON output are that you removed zstd, and you changed the proxy headers. Nothing else is different. So I don’t trust that statement.

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