Configure Caddy as if it were only a firewall and have it forward incoming request from an external hostname to a server inside the LAN that uses nginx

1. My Caddy version (caddy -version):

As a Home Assistant addon

2. How I run Caddy:

Internet ===> Router forwards port 443 to 443 of IP 192.168.1.12 where I ran Home Assistant and its Caddy addon, wit the below configuration. I also give duckdns token and email for letsencrypt.

xxx.duckdns.org {
    tls {
	    dns duckdns
	}
	log data/requests.log {
	rotate_size 50  # Rotate after 50 MB
	rotate_age  90  # Keep rotated files for 90 days
	rotate_keep 20  # Keep at most 20 log files
	rotate_compress # Compress rotated log files in gzip format
    }
    header / {
    Strict-Transport-Security "max-age=31536000; includeSubdomains"
    X-XSS-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "same-origin"
    -Server
}
    proxy / 192.168.1.12:8123 {
        websocket
        transparent
        header_upstream Authorization {>Authorization}
    }
}

3. The problem I’m having:

The configuration above is rock solid. all communication from https://xxx.duckdns.org goes to http://192.168.1.12:8123 perfectly

3b. What I am trying to achieve:

Inside my LAN (on a different machine 192.168.1.20) I want to add another server (BigBlueButton.org) that is using nginx, There are some processes on the BigBlueButton server that only listen on 127.0.0.1 and rely on nginx to route incoming calls.

For this to work I do need configure Caddy as if it were only a firewall and have it forward incoming request from my external hostname to the BigBlueButton server

Is this possible? COuld you give me the how to/instructions?

Thanks

BUMP, no hint?

Is this possible and just have to find a way to configure Caddy, or is it impossible?

I don’t find the question very clear, but I think what you’re trying to do is to make Caddy handle requests to a different domain name to your other server? If so, all you need to do is add another site block to your Caddyfile.

xxx.duckdns.org {
   ... existing config
}

otherdomain.org {
    proxy / 192.168.1.20 {
        transparent
    }
}

Something like that.

In this case, your other domain name’s DNS would point to the same IP address as your duckdns domain; you can use CNAME to point your other domain to your duckdns domain, so that your other domain doesn’t also need a dynamic IP.

Sorry if I misunderstood what you’re asking, if so it would be best if you could give as much detail as you can to help us understand what you’re trying to achieve.

Thanks for answering, I try to be more clear

I succesfully installed Rocketchat server on a Ubuntu server 18.04 VM with DOCKER and NGINX in my home LAN and works great. So I know the installation is fine.
But now I need to fix the installation according my home LAN specifications that has other 2 servers.

Basically my situation is as below

Internet ===> Router port 443 ===>  Caddy proxy server ====> http://server1
                                                       ====> http://server2
                                                       ====>  (wish to do this but is not working ) rhttp://ocket.chat server

Basically my Caddy Proxy server forwards all encrypted communication to the appropriate server inside my LAN

https://server1-klagio.duckdns.org  ====>                    ======> http://server1
                                          Caddy proxy server  
https://server2-klagio.duckdns.org  ====>                    =====>  http://server2

In order to make ROCKETCHAT work in my environment, I think I have 2 option
a) make all internat communication of RocketChat unencrypted but I guess will not work
b) make Caddy passthorught all the communications towards the ROCKETCHAT server
https://rocketchat-klagio.duckdns.org =====> direct to rockechat server inside LAN (https)
c) othe rsolutions?

https://server1-klagio.duckdns.org  ====>                    ======> http://server1
                                          Caddy proxy server  
https://server2-klagio.duckdns.org  ====>                    =====>  http://server2
AND

https://rocket-chat-klagio.duckdns.org. bypass Caddy directly to https://192.168.1.13 internal IP of RocketChat (it has Nginx) 


I hope I made myself clear

In RocketChat’s docs, they describe how to use Caddy as a proxy in front of it: https://rocket.chat/docs/installation/manual-installation/configuring-ssl-reverse-proxy/#running-behind-a-caddy-reverse-proxy-with-free-ssl

Basically, you’ll disable TLS on RocketChat, letting Caddy terminate TLS.

Your config will probably look something like:

rocket-chat-klagio.duckdns.org {
    proxy / 192.168.1.20:3000 {
        transparent
        websocket
    }
    tls {
        dns duckdns
    }
}

(The header_upstream lines can be replaced by the transparent shorthand)

Hey thanks a lot. I can definetely try that. On my (already done) installation of rocket chat I will just have to disable the nginx service, modify my Caddy settings, and that’s it, correct?

On another program (BigBlkueButton) the settings Caddy ==> BBB server without Nginx, was not working, because those servers have a lot of services (voice, video, screen sharing, chat, and so on), and some of those services were relying on local Nginx.

But nevertheless I will try your solution, perhaps this works with rochechat and its jitsi integration (actually what I am interested primarily is VOICE and VIDEO self hosted solution)

Hi Now I am getting closer to my solution.

To recapitulate my configuration

  1. I have only 1 IP available, but multiple servers that also need port 443 and 80

  2. each server that is hosted inside my LAN has to be accessible from outside

    https://server1-klagio.duckdns.org
    https://server2-klagio.duckdns.org (same public IP as server1)

  3. My idea was to have a server with Caddy on it that handles port 80 and 443, and instradate the communication to the various servers

Rocketchat is not good, since it relyes on Jitsi-Meet which is not self-hosted. Since my main goal is to have a self-hosted Voice/Video server I go direct to self-hosting JITSY-MEET

On the JITSY forum (Issues with using NginX on separate server - Install & Config - Jitsi Community Forum - developers & users) a user has succesfully done what I want, but using NGINX instead of CADDY, so basically now I need help to translate the below NGINX configuratiuon into a valid CADDY configuration.

Any help please

server {
    server_name scry.mydomain.com;  
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/scry.mydomain.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/scry.mydomain.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location / {
        ssi on;
        proxy_pass https://10.254.0.104/;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
    }
    # BOSH
    location /http-bind {
        proxy_pass http://10.254.0.104:5280/http-bind;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
    }

    # xmpp websockets
    location /xmpp-websocket {
        proxy_pass              http://10.254.0.104:5280/xmpp-websocket;
        proxy_http_version      1.1;
        proxy_set_header        Upgrade $http_upgrade;
        proxy_set_header        Connection "upgrade";
        proxy_set_header        Host $host;
        tcp_nodelay             on;
    }
}

My current Caddyfile is as below

server1-klagio.duckdns.org {
    tls {
	    dns duckdns
	}
	log data/requests.log {
	rotate_size 50  # Rotate after 50 MB
	rotate_age  90  # Keep rotated files for 90 days
	rotate_keep 20  # Keep at most 20 log files
	rotate_compress # Compress rotated log files in gzip format
    }
    header / {
    Strict-Transport-Security "max-age=31536000; includeSubdomains"
    X-XSS-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "same-origin"
    -Server
}
    proxy / 192.168.1.9:8123 {
        websocket
        transparent
        header_upstream Authorization {>Authorization}
    }
}

server2-klagio.duckdns.org {
    tls {
	    dns duckdns
	}
	log data/requests.log {
	rotate_size 50  # Rotate after 50 MB
	rotate_age  90  # Keep rotated files for 90 days
	rotate_keep 20  # Keep at most 20 log files
	rotate_compress # Compress rotated log files in gzip format
    }
    header / {
    Strict-Transport-Security "max-age=31536000; includeSubdomains"
    X-XSS-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "same-origin"
    -Server
}
    proxy / 192.168.1.10:5865 {
        websocket
        transparent
        header_upstream Authorization {>Authorization}
    }
}

I see the ssi on; option in the first block, there’s no equivalent to that in Caddy. Hopefully that isn’t required. SSI is “Server Side Includes”, I’ve never used it but it seems to read the response from the service, look for HTML comment blocks, and include other HTML content inline to replace that comment.

There’s also no tcp_nodelay equivalent option, but I think using websocket for that block should be enough. I hope.

rocket-chat-klagio.duckdns.org {
    tls {
        dns duckdns
    }

    proxy / https://192.168.1.20 {
        transparent
    }

    # BOSH
    proxy /http-bind http://192.168.1.20:5280/http-bind {
        transparent
    }

    # xmpp websockets
    location /xmpp-websocket http://10.254.0.104:5280/xmpp-websocket {
        transparent
        websocket
    }
}

I am not good enoug to understand this, but below there is a post pointing at templates. And somewhere else I red that this SSI is important, will try your solution as is tonight

Yeah, the templates feature is great if you’re building your own site from scratch, but if you’re proxying to another app that you don’t control, it won’t help here. It’s a similar feature, but the syntax is different, therefore they’re incompatible.

Hi I tried but I get an error in Caddy LOG

:45:01 /share/caddy/Caddyfile:67 - Error during parsing: Unknown directive ‘location’

EDIT I change location to proxy.

Restarting all, when I go to https://xxx.duckdns.org, I receive an error

502 Bad Gateway

Not sure if this helps, it says that SSI are available now in Caddy v2

https://github.com/caddyserver/caddy/issues/1490

Whoops, sorry about that one :stuck_out_tongue:

@matt was just saying that the template directive now implements a sub-requests feature, not that it supports SSI.

Hmm. This is where things become hard to debug. That essentially means that Caddy tried to make a request to the proxy backend, but something went wrong.

Make sure the IP addresses in there are correct, I just typed up that Caddyfile example in a hurry, and I also don’t know what your network looks like, was just taking guesses based on your earlier comments.

Below my Caddyfile

klagio-video-server.duckdns.org {
    tls {
        dns duckdns
    }

    proxy / https://192.168.1.1 {
        transparent
    }

    # BOSH
    proxy /http-bind http://192.168.1.1:5280/http-bind {
        transparent
    }

    # xmpp websockets
    proxy  /xmpp-websocket http://192.168.1.1:5280/xmpp-websocket {
        transparent
        websocket
    }
}


klagio-other-server.duckdns.org {
    tls {
	    dns duckdns
	}
	log data/requests.log {
	rotate_size 50  # Rotate after 50 MB
	rotate_age  90  # Keep rotated files for 90 days
	rotate_keep 20  # Keep at most 20 log files
	rotate_compress # Compress rotated log files in gzip format
    }
    header / {
    Strict-Transport-Security "max-age=31536000; includeSubdomains"
    X-XSS-Protection "1; mode=block"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "same-origin"
    -Server
}
    proxy / 192.168.1.9:8123 {
        websocket
        transparent
        header_upstream Authorization {>Authorization}
    }
}

I do not know where to look for log files.

Ahh
When I disable CADDY, and forward my port 443 to the JITSI-MEET server, everything works: I mean JITSI-SERVER NGINX installation is final.

When I switch to CADDY as per above configuration, beside forwarding 443 to CADDY (and not anymore to JITSI-MEET) do I have to do something at the JITSI_MEET installation in regards of its NGINX install?

Let’s step back a bit to confirm the config:

klagio-video-server.duckdns.org {
    tls {
        dns duckdns
    }

    proxy / https://192.168.1.1 {
        transparent
    }

    # BOSH
    proxy /http-bind http://192.168.1.1:5280/http-bind {
        transparent
    }

    # xmpp websockets
    proxy  /xmpp-websocket http://192.168.1.1:5280/xmpp-websocket {
        transparent
        websocket
    }
}

The first proxy directive has the upstream https://192.168.1.1. Is upstream listening on https? If so, is the certificate self-signed? If not, is the port correct?

If yes, it’s listening on https with the correct port number of 443 and the certificate is self-signed, then you will need to add insecure_skip_verify within the first proxy block. So it becomes:

proxy / https://192.168.1.1 {
        transparent
        insecure_skip_verify
}

If it’s not listening on https, then confirm you have the correct IP address and port number.

1 Like

adding that it works. Now I can access the front page of the server

Let me check if voice/video works. EDIT, not yet will check further

1 Like

I spoke to @Mohammed90 elsewhere, he mentioned maybe you need to add the except subdirective to some of those proxies so they properly fall through to the others. See https://caddyserver.com/v1/docs/proxy

klagio-video-server.duckdns.org {
    tls {
        dns duckdns
    }

    proxy / https://192.168.1.1 {
        except /http-bind /xmpp-websocket
        transparent
        insecure_skip_verify
    }

    # BOSH
    proxy /http-bind http://192.168.1.1:5280/http-bind {
        transparent
    }

    # xmpp websockets
    proxy  /xmpp-websocket http://192.168.1.1:5280/xmpp-websocket {
        transparent
        websocket
    }
}

Ok, thanks added that. I can connect, so thats an improvement, but the audio/video is not working and I keep being disconnected from the server. I know this is related to trhe server, but the problem lies in Caddy somewhere. This is the console of the Browser, that shows the error 404

strophe.js:5666 POST https://xxx-video.duckdns.org/http-bind?room=test 404

and

ogger.js:154 2020-01-28T08:48:31.618Z [features/base/tracks] Failed to create local tracks (2) [“audio”, “video”] a {gum: {
}, name: “gum.not_found”, message: “Requested device(s) was/were not found: audio, video”, stack: “Error↔ at new a (https://xxx-video.duckdns.or
dns.org/libs/lib-jitsi-meet.min.js?v=3729:6:96997”}

constraints:  {video: {
}, audio: {
}}
**strophe.js:5666 POST https://xxx-video.duckdns.org/http-bind?room=test 404**
l @ strophe.js:5666
_processRequest @ strophe.js:5681
_throttledRequestHandler @ strophe.js:5827
_connect @ strophe.js:5150
connect @ strophe.js:3051


_c @ react-dom.production.min.js:272
render @ react-dom.production.min.js:273
(anonymous) @ index.web.js:25
Show 160 more frames
Logger.js:154 2020-01-28T08:48:31.455Z [JitsiMeetJS.js] <Object.getGlobalOnErrorHandler>:  **UnhandledError: null Script: null Line: null Column: null StackTrace:  Error: Strophe: request id 1.1 error 404 happened**
    at Object.i.Strophe.log (strophe.util.js:89)


(anonymous) @ middleware.js:16
(
(anonymous) @ index.web.js:25
Show 167 more frames
Logger.js:154 2020-01-28T08:48:31.459Z [modules/xmpp/strophe.util.js] <Object.i.Strophe.log>:  Strophe: request id 1.1 error 404 happened
o @ Logger.js:154
i.Strophe.log @ strophe.util.js:90

Logger.js:154 2020-01-28T08:48:31.461Z [modules/xmpp/strophe.util.js] <Object.i.Strophe.log>:  Strophe: request errored, status: 404, number of errors: 1
o @ Logger.js:154
i.Strophe.log @ strophe.util.js:77
warn @ strophe.js:2073

(anonymous) @ index.web.js:25
Show 165 more frames
Logger.js:154 2020-01-28T08:48:31.464Z [modules/xmpp/xmpp.js] <t.value>:  (TIME) Strophe disconnecting:	 933.5550000000694
Logger.js:154 2020-01-28T08:48:31.465Z [modules/xmpp/xmpp.js] <t.value>:  (TIME) Strophe disconnected:	 934.7199999999702
Logger.js:154 2020-01-28T08:48:31.466Z [modules/xmpp/xmpp.js] <t.value>:  XMPP connection dropped!

Logger.js:154 2020-01-28T08:48:31.469Z [modules/statistics/statistics.js] <Function.S.sendAnalyticsAndLog>:  {"type":"operational","action":"connection.failed","attributes":{"error_type":"connection.droppedError","error_message":"connection-dropped-error","suspend_time":0,"time_since_last_success":null}}
Logger.js:154 2020-01-28T08:48:31.470Z [connection.js] <c.l>:  CONNECTION FAILED: connection.droppedError
o @ Logger.js:154
l @ connection.js:145
c.emit @ events.js:151

 
Show 157 more frames
Logger.js:154 2020-01-28T08:48:31.618Z [features/base/tracks] Failed to create local tracks (2) ["audio", "video"] a {gum: {
}, name: "gum.not_found", message: "Requested device(s) was/were not found: audio, video", stack: "Error↔    at new a (https://xxx-video.duckdns.or
dns.org/libs/lib-jitsi-meet.min.js?v=3729:6:96997"}
o @ Logger.js:154
(anonymous) @ functions.js:93
Promise.catch (async)