Unable to run FileMakerServer trough Caddy reverse_proxy

1. The problem I’m having:

Hello, I’m trying to host on the same VPS both some personal websites and Filemakerserver by Claris.
I’m using Docker for everything. I made a docker image of filemaker using this guide ( ClarisPKB ) and pulling the official caddy image from docker repo.

I can properly resolve, trough reverse proxy, to the main page, everything work; but when I try to connect to the admin page, it will not resolve.

2. Error messages and/or full log output:

Error from curl

 curl -v vucr.app/admin-console/
*   Trying 164.132.224.98:80...
* Connected to vucr.app (164.132.224.98) port 80 (#0)
> GET /admin-console/ HTTP/1.1
> Host: vucr.app
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 308 Permanent Redirect
< Connection: close
< Location: https://vucr.app/admin-console/
< Server: Caddy
< Date: Tue, 06 Aug 2024 15:57:27 GMT
< Content-Length: 0

From Caddy log

caddy              | {"level":"debug","ts":1722960251.7090673,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"fms-dockercompose:80","duration":0.000305067,"request":{"remote_ip":"81.56.94.77","remote_port":"40963","client_ip":"81.56.94.77","proto":"HTTP/2.0","method":"GET","host":"vucr.app","uri":"/admin-console/","headers":{"X-Forwarded-Proto":["https"],"Sec-Gpc":["1"],"Sec-Fetch-Mode":["navigate"],"X-Forwarded-For":["81.56.94.77"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Accept-Language":["it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"],"X-Forwarded-Host":["vucr.app"],"Te":["trailers"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"],"Sec-Fetch-Dest":["document"],"Dnt":["1"],"Upgrade-Insecure-Requests":["1"],"Priority":["u=0, i"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"vucr.app"}},"headers":{"Connection":["keep-alive"],"Location":["https://vucr.app:443/admin-console/"],"Access-Control-Allow-Origin":["fms-dockercompose"],"Content-Length":["138"],"Date":["Tue, 06 Aug 2024 16:04:11 GMT"],"Content-Type":["text/html"],"Access-Control-Allow-Credentials":["True"],"Access-Control-Allow-Headers":["Content-Type,Authorization"],"Server":["nginx"]},"status":302}
caddy              | {"level":"debug","ts":1722960251.7502472,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"fms-dockercompose:80","total_upstreams":1}
caddy              | {"level":"debug","ts":1722960251.7511933,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"fms-dockercompose:80","duration":0.000376467,"request":{"remote_ip":"81.56.94.77","remote_port":"40963","client_ip":"81.56.94.77","proto":"HTTP/2.0","method":"GET","host":"vucr.app","uri":"/admin-console/","headers":{"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"],"X-Forwarded-Host":["vucr.app"],"Sec-Fetch-Mode":["navigate"],"Priority":["u=0, i"],"Sec-Gpc":["1"],"Sec-Fetch-User":["?1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Te":["trailers"],"X-Forwarded-Proto":["https"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"],"Accept-Language":["it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"],"Dnt":["1"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Site":["none"],"X-Forwarded-For":["81.56.94.77"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"vucr.app"}},"headers":{"Date":["Tue, 06 Aug 2024 16:04:11 GMT"],"Content-Type":["text/html"],"Content-Length":["138"],"Connection":["keep-alive"],"Location":["https://vucr.app:443/admin-console/"],"Server":["nginx"],"Access-Control-Allow-Origin":["fms-dockercompose"],"Access-Control-Allow-Credentials":["True"],"Access-Control-Allow-Headers":["Content-Type,Authorization"]},"status":302}
caddy              | {"level":"debug","ts":1722960251.7885177,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"fms-dockercompose:80","total_upstreams":1}
caddy              | {"level":"debug","ts":1722960251.7893164,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"fms-dockercompose:80","duration":0.000307265,"request":{"remote_ip":"81.56.94.77","remote_port":"40963","client_ip":"81.56.94.77","proto":"HTTP/2.0","method":"GET","host":"vucr.app","uri":"/admin-console/","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"],"Dnt":["1"],"Sec-Gpc":["1"],"Sec-Fetch-Site":["none"],"Sec-Fetch-Dest":["document"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"],"Sec-Fetch-User":["?1"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["vucr.app"],"Upgrade-Insecure-Requests":["1"],"Accept-Language":["it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"],"Te":["trailers"],"Sec-Fetch-Mode":["navigate"],"Priority":["u=0, i"],"Accept-Encoding":["gzip, deflate, br, zstd"],"X-Forwarded-For":["81.56.94.77"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"vucr.app"}},"headers":{"Content-Length":["138"],"Connection":["keep-alive"],"Access-Control-Allow-Credentials":["True"],"Server":["nginx"],"Content-Type":["text/html"],"Location":["https://vucr.app:443/admin-console/"],"Access-Control-Allow-Origin":["fms-dockercompose"],"Access-Control-Allow-Headers":["Content-Type,Authorization"],"Date":["Tue, 06 Aug 2024 16:04:11 GMT"]},"status":302}
caddy              | {"level":"debug","ts":1722960251.8285227,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"fms-dockercompose:80","total_upstreams":1}
caddy              | {"level":"debug","ts":1722960251.8294282,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"fms-dockercompose:80","duration":0.000297221,"request":{"remote_ip":"81.56.94.77","remote_port":"40963","client_ip":"81.56.94.77","proto":"HTTP/2.0","method":"GET","host":"vucr.app","uri":"/admin-console/","headers":{"X-Forwarded-For":["81.56.94.77"],"Upgrade-Insecure-Requests":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Accept-Language":["it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"],"Sec-Fetch-Site":["none"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"],"Sec-Fetch-User":["?1"],"Priority":["u=0, i"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"],"X-Forwarded-Proto":["https"],"X-Forwarded-Host":["vucr.app"],"Sec-Gpc":["1"],"Te":["trailers"],"Dnt":["1"],"Sec-Fetch-Dest":["document"],"Sec-Fetch-Mode":["navigate"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"vucr.app"}},"headers":{"Access-Control-Allow-Credentials":["True"],"Access-Control-Allow-Headers":["Content-Type,Authorization"],"Date":["Tue, 06 Aug 2024 16:04:11 GMT"],"Content-Type":["text/html"],"Content-Length":["138"],"Connection":["keep-alive"],"Location":["https://vucr.app:443/admin-console/"],"Server":["nginx"],"Access-Control-Allow-Origin":["fms-dockercompose"]},"status":302}
caddy              | {"level":"debug","ts":1722960251.8656907,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"fms-dockercompose:80","total_upstreams":1}
caddy              | {"level":"debug","ts":1722960251.866608,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"fms-dockercompose:80","duration":0.000382431,"request":{"remote_ip":"81.56.94.77","remote_port":"40963","client_ip":"81.56.94.77","proto":"HTTP/2.0","method":"GET","host":"vucr.app","uri":"/admin-console/","headers":{"Sec-Gpc":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"],"Sec-Fetch-Dest":["document"],"X-Forwarded-For":["81.56.94.77"],"X-Forwarded-Host":["vucr.app"],"Sec-Fetch-Mode":["navigate"],"Te":["trailers"],"Accept-Language":["it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3"],"X-Forwarded-Proto":["https"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8"],"Dnt":["1"],"Accept-Encoding":["gzip, deflate, br, zstd"],"Upgrade-Insecure-Requests":["1"],"Sec-Fetch-Site":["none"],"Sec-Fetch-User":["?1"],"Priority":["u=0, i"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"vucr.app"}},"headers":{"Date":["Tue, 06 Aug 2024 16:04:11 GMT"],"Content-Length":["138"],"Connection":["keep-alive"],"Access-Control-Allow-Origin":["fms-dockercompose"],"Access-Control-Allow-Credentials":["True"],"Server":["nginx"],"Content-Type":["text/html"],"Location":["https://vucr.app:443/admin-console/"],"Access-Control-Allow-Headers":["Content-Type,Authorization"]},"status":302}
caddy              | {"level":"debug","ts":1722960251.9106214,"logger":"http.handlers.reverse_proxy","msg":"selected upstream","dial":"fms-dockercompose:80","total_upstreams":1}

3. Caddy version:

v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=

4. How I installed and ran Caddy:

I used this docker compose:

services:
  caddy:
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /home/ubuntu/CaddyFiles/Caddyfile:/etc/caddy/Caddyfile
      - /home/ubuntu/CaddyFiles/data:/data
      - /home/ubuntu/CaddyFiles/config:/config
      - /home/ubuntu/CaddyFiles/site:/srv
    depends_on:
      - filemakerserver
    image: caddy:latest

  filemakerserver:
    restart: unless-stopped
    hostname: fms-dockercompose
    container_name: fms-dockercompose
    privileged: true
    ports:
#      - "80:80"
#      - "443:443"
      - "8080:80"
      - "8443:443"
      - "2399:2399"
      - "5003:5003"
      - "16001:16001"
    volumes:
      - /home/ubuntu/FileMakerFiles:/opt/FileMaker/FileMaker Server/Data
    image: fmsdocker:final

a. System environment:

ubuntu 22.04
Docker version 27.1.1, build 6312585

b. Command:

See the docker compose gile

c. Service/unit/compose file:

services:
  caddy:
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /home/ubuntu/CaddyFiles/Caddyfile:/etc/caddy/Caddyfile
      - /home/ubuntu/CaddyFiles/data:/data
      - /home/ubuntu/CaddyFiles/config:/config
      - /home/ubuntu/CaddyFiles/site:/srv
    depends_on:
      - filemakerserver
    image: caddy:latest

  filemakerserver:
    restart: unless-stopped
    hostname: fms-dockercompose
    container_name: fms-dockercompose
    privileged: true
    ports:
#      - "80:80"
#      - "443:443"
      - "8080:80"
      - "8443:443"
      - "2399:2399"
      - "5003:5003"
      - "16001:16001"
    volumes:
      - /home/ubuntu/FileMakerFiles:/opt/FileMaker/FileMaker Server/Data
    image: fmsdocker:final

d. My complete Caddy config:

{
	debug
}

vucr.app {
	reverse_proxy fms-dockercompose:80
}

personal_site_name.com {
	#site folder
}

5. Links to relevant resources:

Official guide to run filemaker in docker ClarisPKB

Howdy @Jhyrachy, welcome to the Caddy community.

This curl result simply shows a redirect from HTTP to HTTPS. It appears to be working fine.

You would need to curl HTTPS or use -L to show what happens when you follow the redirect.

These have a little more information:

  • "upstream":"fms-dockercompose:80": Caddy attempted to connect to the container on port 80. (By default, this is HTTP.)
  • "Server":["nginx"]: Caddy connected to an upstream nginx server.
  • "status":302: Caddy received a 302 response from that server.
  • "Location":["https://vucr.app:443/admin-console/"]: The upstream server told Caddy that the client should connect to HTTPS on port 443.

As the client is already connected, presumably, over HTTPS to Caddy, I would expect this to result in an infinite redirect loop. (Client connects to Caddy on HTTPS → Caddy connects to upstream on HTTP → Upstream says “come back over HTTPS” → Caddy returns this response to the client → Client reconnects to Caddy on HTTPS → Caddy connects to upstream on HTTP…)

Based on this behaviour, and your description:

I’d assume that your upstream server requires HTTPS connections for the admin console, but does not require them for the main page.

The ideal place to fix this behaviour is in your upstream server. Ideally, it should treat all traffic the same to ensure consistent operation behind a reverse proxy.

If that doesn’t work, you could use a route (Caddyfile directive) — Caddy Documentation for the /admin-console/ path that proxies directly to HTTPS, or you might simply try proxying to HTTPS for the entire site.

1 Like

Yes, you are right!
the admin console require https, but since it does not automatically manage autorenewal I would have to install and manage certbot inside the docker image of filemaker; but since filemaker comes with a self signed certificate I wonder if we could work with that…

You can use tls_insecure_skip_verify in your reverse proxy to have Caddy ignore an untrusted certificate when connecting to upstream HTTPS.

We generally recommend against this in production, but it is no worse (except a little bit of unnecessary overhead) than simply proxying plain old insecure HTTP, which should be fine as long as the network is isolated (such as via a Docker network).

1 Like

I tried with this caddyfile

vucr.app {                                                                           reverse_proxy fms-dockercompose:80 {
                transport http {
                        tls_insecure_skip_verify
                }
        }
}

And this is the output of curl -v -L vucr.app/admin-config/

~ $ curl -v -L vucr.app/admin-console/          *   Trying 164.132.224.98:80...
* Connected to vucr.app (164.132.224.98) port 80 (#0)
> GET /admin-console/ HTTP/1.1                  > Host: vucr.app
> User-Agent: curl/7.83.0                       > Accept: */*
>                                               * Mark bundle as not supporting multiuse
< HTTP/1.1 308 Permanent Redirect               < Content-Length: 0
< Date: Wed, 07 Aug 2024 05:13:22 GMT           < Location: https://vucr.app/admin-console/
< Server: Caddy                                 <
* Connection #0 to host vucr.app left intact
* Clear auth, redirects to port from 80 to 443
* Issue another request to this URL: 'https://vucr.app/admin-console/'
*   Trying 164.132.224.98:443...
* Connected to vucr.app (164.132.224.98) port 443 (#1)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /data/data/com.termux/files/usr/etc/tls/cert.pem
*  CApath: /data/data/com.termux/files/usr/etc/tls/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=vucr.app
*  start date: Aug  5 10:00:52 2024 GMT
*  expire date: Nov  3 10:00:51 2024 GMT
*  subjectAltName: host "vucr.app" matched cert's "vucr.app"
*  issuer: C=US; O=Let's Encrypt; CN=E6
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* h2h3 [:method: GET]
* h2h3 [:path: /admin-console/]
* h2h3 [:scheme: https]
* h2h3 [:authority: vucr.app]
* h2h3 [user-agent: curl/7.83.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0xb4000070edd7d7b0)
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET /admin-console/ HTTP/2
> Host: vucr.app
> user-agent: curl/7.83.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 502
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Wed, 07 Aug 2024 05:13:22 GMT
<
* Connection #1 to host vucr.app left intact

But still it will not resolve, only an empty page; in contrast, doing a reverse-proxy fmsdockercompose:443 would just give a plain error for routing an http connection trough https

You still need the reverse_proxy directive and to specify the upstream.

If you go to the example section (https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#examples) you’ll see a full example.

Reverse proxy to an HTTPS upstream, but :warning: disable TLS verification. This is NOT RECOMMENDED, since it disables all security checks that HTTPS offers; proxying over HTTP in private networks is preferred if possible, because it avoids the false sense of security:

example.com {
	reverse_proxy 10.0.0.1:443 {
		transport http {
			tls_insecure_skip_verify
		}
	}
}
2 Likes

That’s it!

Now it looks like everything work!
I will have to do some more tests but in the meantime thanks a lot!

2 Likes

No worries!

1 Like

Just another question, should I reverse_proxy each port?
For example, desktop client require ports 2399 and 5003.

Should I do
reverse_proxy :2399 fmsdockercompose:2399
or it would cause conflicts?
Thanks again!

Are those ports used for HTTP(S)?

You could reverse proxy them by having Caddy listen on them and forwarding to the relevant port. The simplest way to configure that would probably be with multiple sites.

example.com {
  reverse_proxy https://upstream
}

example.com:2399 {
  reverse_proxy https://upstream:2399
}

# etc...
1 Like

I did a lot of test and read a lot of docs.

In short, those ports are https (but i can make it ignore on client, so is not really a problem I guess); but I found that there is a websocket page that does not work…

the page should be vucr.app/fmi/*, so I added in the caddyfile

vucr.app/fmi/* {
        reverse_proxy fms-dockercompose/fmi/
}

But it kinda broke everything beacuse multiple redirect stopped working

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