1. Caddy version (caddy version):
v2.4.0-beta.1 built from the master including the Cloudflare module
2. How I run Caddy:
I use Caddyfile rather than JSON.
a. System environment:
FreeNAS 11.3 (a FreeBSD derivative)
b. Command:
service caddy start
c. Service/unit/compose file:
n/a
d. My complete Caddyfile or JSON config:
This is an extract from the relevant section of my Caddyfile that I’m looking at enhancing.
udance.com.au www.udance.com.au {
  encode gzip
  import tlsdns
  import logging udance
  import authproxy /phpmyadmin*
  reverse_proxy /tautulli* 10.1.1.26:8181
  reverse_proxy /transmission* 10.1.1.28:9091
  reverse_proxy 10.1.1.55
}
To avoid cluttering the above extract, I’ve not included the snippets. For completeness, I’ve included them below.
(tlsdns) {
  tls {
    dns cloudflare [REDACTED]
  }
}
(authproxy) {
  basicauth {args.0} {
    admin [REDACTED]
  }
}
(logging) {
  log {
    format json
    output file /var/log/caddy/{args.0}.log {
      roll_keep 7
    }
  }
}
3. The problem I’m having:
The Caddy block serves the domain and two sub-paths. I wanted some flexibility around taking individual services offline and thought that the map directive (which I’ve recently become a big fan of) could help me here.
Here’s my attempt at building this flexibility into the Caddy block with the focus, at this stage, just on the /tautulli sub-path. I noticed that there was a redirect to udance.com.au/tautulli/auth/login?redirect_uri=/tautulli if I entered udance.com.au/tautulli in a browser address bar, therefore, I had to use a regular expression for the path.
udance.com.au www.udance.com.au {
  encode gzip
  import tlsdns
  import logging udance
  import authproxy /phpmyadmin*
  map {path} {backend} {online} {
#   PATH            BACKEND        ONLINE
#---------------------------------------------------------------
    ~^/tautulli.*   10.1.1.26:8181   yes
#   /transmission   10.1.1.28:9091   yes
#   /               10.1.1.55:80     yes  
    default         unknown          yes
  }
# Error handling
  @unknown expression `{backend} == "unknown"`
  handle @unknown {
    respond "Denied {path}" 403
  }
#
  @offline expression `{online} == "no"`
  handle @offline {
    # Do whatever e.g. respond/redir 
  }
  reverse_proxy {path} {backend}
}
4. Error messages and/or full log output:
The solution works approximately 50% of the time. Reloading the page seems to randomly switch me between the Tautulli login screen or the browser responding with a 502 error.
There are invalid dial address entries in the Caddy log file with missing port address. Here’s a couple of entries:
{"level":"error","ts":1615865654.7320564,"logger":"http.log.error.log3","msg":"making dial info: upstream {http.request.uri.path}:invalid dial address /tautulli/home: address tautulli/home: missing port in address","request":{"remote_addr":"10.1.1.136:57213","proto":"HTTP/2.0","method":"GET","host":"udance.com.au","uri":"/tautulli/home","headers":{"Authorization":["Basic YWRtaW46OComQXZLTFJ0SCUyITJGaUFlZQ=="],"Upgrade-Insecure-Requests":["1"],"Cache-Control":["max-age=0"],"Sec-Ch-Ua":["\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\""],"User-Agent":["Mozilla/5.0(Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Sec-Fetch-Site":["same-origin"],"Sec-Fetch-Mode":["navigate"],"Sec-Ch-Ua-Mobile":["?0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"],"Sec-Fetch-User":["?1"],"Sec-Fetch-Dest":["document"],"Accept-Encoding":["gzip, deflate, br"],"Cookie":["tautulli_token_5837b2dff06e4f0e9f86551fd6ec5efc=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxNTQzNTU3LCJ1c2VyIjoiYmFzaWxoIiwidXNlcl9ncm91cCI6ImFkbWluIiwiZXhwIjoxNjE4NDU2NzU2fQ._BgPiEFn3XchkSRdY6SsWfAmebv58it-waZ84Clf1r0; tk_or=%22%22; tk_lr=%22%22; wordpress_logged_in_01ad53d5bf4f84d52a16c29bd439eb90=basil%7C1645606391%7Cg0BlFaRlmpOtRQIufy2y3zkZMaJQ5kBwHgodcQZTCol%7C21fc4a76a8a48a1988b5664d18c3115b251ad355646ec0b0bbf00b4cd0c0aa34; wp-settings-1=libraryContent%3Dbrowse; wp-settings-time-1=1614070400;__cfduid=d9d479562ae0d9e9a028d749d6594ad101615662603"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","proto_mutual":true,"server_name":"udance.com.au"}},"duration":0.00032652,"status":502,"err_id":"uf8m3q16a","err_trace":"reverseproxy.statusError (reverseproxy.go:827)"}
{"level":"error","ts":1615865657.5854928,"logger":"http.log.error.log3","msg":"making dial info: upstream {http.request.uri.path}: invalid dial address /tautulli/home:address tautulli/home: missing port in address","request":{"remote_addr":"10.1.1.136:57213","proto":"HTTP/2.0","method":"GET","host":"udance.com.au","uri":"/tautulli/home","headers":{"Cache-Control":["max-age=0"],"Sec-Fetch-User":["?1"],"Accept-Language":["en-GB,en-US;q=0.9,en;q=0.8"],"Authorization":["Basic YWRtaW46OComQXZLTFJ0SCUyITJGaUFlZQ=="],"Sec-Ch-Ua":["\"Google Chrome\";v=\"89\", \"Chromium\";v=\"89\", \";Not A Brand\";v=\"99\""],"Upgrade-Insecure-Requests":["1"],"Accept-Encoding":["gzip, deflate, br"],"Sec-Ch-Ua-Mobile":["?0"],"Sec-Fetch-Site":["same-origin"],"Sec-Fetch-Mode":["navigate"],"Cookie":["tautulli_token_5837b2dff06e4f0e9f86551fd6ec5efc=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxNTQzNTU3LCJ1c2VyIjoiYmFzaWxoIiwidXNlcl9ncm91cCI6ImFkbWluIiwiZXhwIjoxNjE4NDU2NzU2fQ._BgPiEFn3XchkSRdY6SsWfAmebv58it-waZ84Clf1r0; tk_or=%22%22; tk_lr=%22%22; wordpress_logged_in_01ad53d5bf4f84d52a16c29bd439eb90=basil%7C1645606391%7Cg0BlFaRlmpOtRQIufy2y3zkZMaJQ5kBwHgodcQZTCol%7C21fc4a76a8a48a1988b5664d18c3115b251ad355646ec0b0bbf00b4cd0c0aa34; wp-settings-1=libraryContent%3Dbrowse; wp-settings-time-1=1614070400; __cfduid=d9d479562ae0d9e9a028d749d6594ad101615662603"],"User-Agent":["Mozilla/5.0 (WindowsNT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"],"Sec-Fetch-Dest":["document"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","proto_mutual":true,"server_name":"udance.com.au"}},"duration":0.000250855,"status":502,"err_id":"x9x62bdu2","err_trace":"reverseproxy.statusError (reverseproxy.go:827)"}
Relevant output from caddy adapt --pretty
                                                {
                                                        "match": [
                                                                {
                                                                        "host": [
                                                                                "udance.com.au",
                                                                                "www.udance.com.au"
                                                                        ]
                                                                }
                                                        ],
                                                        "handle": [
                                                                {
                                                                        "handler": "subroute",
                                                                        "routes": [
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "defaults": [
                                                                                                                "unknown",
                                                                                                                "yes"
                                                                                                        ],
                                                                                                        "destinations": [
                                                                                                                "{backend}",
                                                                                                                "{online}"
                                                                                                        ],
                                                                                                        "handler": "map",
                                                                                                        "mappings": [
                                                                                                                {
                                                                                                                        "input_regexp": "^/tautulli.*",
                                                                                                                        "outputs": [
                                                                                                                                "10.1.1.26:8181",
                                                                                                                                "yes"
                                                                                                                        ]
                                                                                                                }
                                                                                                        ],
                                                                                                        "source": "{http.request.uri.path}"
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "authentication",
                                                                                                        "providers": {
                                                                                                                "http_basic": {
                                                                                                                        "accounts": [
                                                                                                                                {
                                                                                                                                        "password": [REDACTED],
                                                                                                                                        "username": "admin"
                                                                                                                                }
                                                                                                                        ],
                                                                                                                        "hash": {
                                                                                                                                "algorithm": "bcrypt"
                                                                                                                        },
                                                                                                                        "hash_cache": {}
                                                                                                                }
                                                                                                        }
                                                                                                }
                                                                                        ],
                                                                                        "match": [
                                                                                                {
                                                                                                        "path": [
                                                                                                                "/phpmyadmin*"
                                                                                                        ]
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "encodings": {
                                                                                                                "gzip": {}
                                                                                                        },
                                                                                                        "handler": "encode"
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "group": "group9",
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "subroute",
                                                                                                        "routes": [
                                                                                                                {
                                                                                                                        "handle": [
                                                                                                                                {
                                                                                                                                        "body": "Denied {http.request.uri.path}",
                                                                                                                                        "handler": "static_response",
                                                                                                                                        "status_code": 403
                                                                                                                                }
                                                                                                                        ]
                                                                                                                }
                                                                                                        ]
                                                                                                }
                                                                                        ],
                                                                                        "match": [
                                                                                                {
                                                                                                        "expression": "{backend} == \"unknown\""
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "group": "group9",
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "subroute",
                                                                                                        "routes": [
                                                                                                                {
                                                                                                                        "handle": [
                                                                                                                                {
                                                                                                                                        "handler": "static_response",
                                                                                                                                        "headers": {
                                                                                                                                                "Location": [
                                                                                                                                                        "https://udance.statuspage.io"
                                                                                                                                                ]
                                                                                                                                        },
                                                                                                                                        "status_code": 302
                                                                                                                                }
                                                                                                                        ]
                                                                                                                }
                                                                                                        ]
                                                                                                }
                                                                                        ],
                                                                                        "match": [
                                                                                                {
                                                                                                        "expression": "{online} == \"no\""
                                                                                                }
                                                                                        ]
                                                                                },
                                                                                {
                                                                                        "handle": [
                                                                                                {
                                                                                                        "handler": "reverse_proxy",
                                                                                                        "upstreams": [
                                                                                                                {
                                                                                                                        "dial": "{http.request.uri.path}"
                                                                                                                },
                                                                                                                {
                                                                                                                        "dial": "{backend}"
                                                                                                                }
                                                                                                        ]
                                                                                                }
                                                                                        ]
                                                                                }
                                                                        ]
                                                                }
                                                        ],
                                                        "terminal": true
                                                },
  
5. What I already tried:
- Checked the Caddy log.
- Confirmed the regex expression used.