Postgres TCP Reverse Proxy Layer4

1. The problem I’m having:

I’m trying to reverse proxy my postgres image in docker so that i can interact with it within my NodeJS project. I’ve installed xCaddy with Layer4 but the documentation is too bloated and I’m not sure where to modify. Basically I just want to reverse proxy TCP the port 5432; which is postgres.

2. Error messages and/or full log output:

May 24 19:54:17 mwa1 caddy[8400]: Error: adapting config using caddyfile: Unexpected '{' on a new line; did you mean to place the '{' on the previous line?, at /etc/caddy/Caddyfile:41
May 24 19:54:17 mwa1 systemd[1]: caddy.service: Main process exited, code=exited, status=1/FAILURE
May 24 19:54:17 mwa1 systemd[1]: caddy.service: Failed with result 'exit-code'.
May 24 19:54:17 mwa1 systemd[1]: Failed to start caddy.service - Caddy.

3. Caddy version:

v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=

4. How I installed and ran Caddy:

I’ve used caddy to quite some times and had no problem reverse proxy http, but this is my first time trying out TCP reverse proxy. I installed xcaddy and layer4 because i read it is used to reverse proxy TCP.

a. System environment:

Ubuntu VPS

c. Service/unit/compose file:

docker-compose.yml

services:
  mwa1-backend:
    image: 'nrmnqdds/mwa-backend:v0.0.29'
    ports: 
      - '3040:3040'
    restart: always
    environment:
      - DATABASE_URL=old_supabase_url
      - JWT_SECRET=secret
      - RESEND_KEY=secret

  postgres:
    image: 'postgres:16'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=db-test
    ports:
      - "5432:5432"
    restart: always

  pg-admin:
    image: 'dpage/pgadmin4:8'
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@admin.org
      - PGADMIN_DEFAULT_PASSWORD=password
      - PGADMIN_LISTEN_PORT=5050
    ports:
      - "5050:5050"
    restart: always

d. My complete Caddy config:

Caddyfile:

api.mwa.mulhaq.org {
	reverse_proxy localhost:3040
}

pgadmin.mulhaq.org {
	reverse_proxy localhost:5050
}

{
	"servers": {
		"secure-imap": {
			"listen": ["0.0.0.0:993"],
			"routes": [
			{
				"handle": [
				{
					"handler": "tls"
				},
				{
					"handler": "proxy",
					"proxy_protocol": "v1",
					"upstreams": [
					{"dial": ["localhost:5432"]}
					]
				}
				]
			}
			]
		},
	}
}

5. Links to relevant resources:

The config of the l4 app is in JSON, not Caddyfile, so you can’t just put both formats in the same file. As you see, it doesn’t work. If you want to use the l4 app, you have to switch to JSON to configure Caddy.

To start, clean up your Caddyfile by removing the l4 stuff at the bottom, for now. Then run caddy adapt --config /etc/caddy/Caddyfile --pretty, and save the output to a file. The new file only has configuration for the HTTP app. Add the l4 app configuration under apps. Once you updated the configuration, update the systemd unit. See instructions here:

That said, there are 4 issues with your l4 configuration:
1- The tls handler doesn’t work with postgres SSL because postgres uses its own TLS/SSL handshake sequence.
2- The presence of proxy_protocol is suspicious. Do you need it? Do you know if you need it?
3- There’s an extra , (comma) on line 21 of the JSON. It makes it invalid.
4- Your JSON directly jumps into "servers". It needs to be nested under apps > layer4. Study the examples.

2 Likes

This plugins allows the use of only the Caddyfile

2 Likes

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