Difficulties on setup docker stack with n8n, portainer and baserow

1. The problem I’m having:

I am trying to set up a machine with different web services on it, each one reachable using different third level domain. All of that using docker.
Since I am more of a front-end guy, I followed a guide that helped me set up n8n and caddy. It worked perfectly, my n8n instance is reachable using my third level domain and it support SSL, that was the main goal for that.

Now I would like to add baserow to the stack and portainer (this one is just optional, but i thought “why not?”)

So here is the docker-compose.yml:

version: "3.7"

services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    container_name: caddy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - caddy_data:/data
      - ${DATA_FOLDER}/caddy_config:/config
      - ${DATA_FOLDER}/caddy_config/Caddyfile:/etc/caddy/Caddyfile

  n8n:
    image: docker.n8n.io/n8nio/n8n
    container_name: n8n
    restart: always
    ports:
      - 5678:5678
    environment:
      - N8N_HOST=${N8N_SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${N8N_SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
    volumes:
      - n8n_data:/home/node/.n8n
      - ${DATA_FOLDER}/local_files:/files

  portainer-ce:
    ports:
      - 8000:8000
      - 9443:9443
    container_name: portainer
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${DATA_FOLDER}/portainer_data:/data
    image: portainer/portainer-ce:latest

baserow:
    container_name: baserow
    environment:
        - BASEROW_PUBLIC_URL=http://${BASEROW_SUBDOMAIN}.${DOMAIN_NAME}/
    volumes:
      - baserow_data:/baserow/data
    ports:
      - 3002:80
    restart: unless-stopped
    image: baserow/baserow:1.24.2


volumes:
  caddy_data:
    external: true
  n8n_data:
    external: true
  portainer_data:
    external: true
    name: portainer_data
  baserow_data:
    external: true
    name: baserow_data

And here’s the Caddyfile:
NOTE: the url are written in this form: sub.example.com and sanitazed for privacy

<n8n_subdomain>.<domain_name> {
    reverse_proxy n8n:5678 {
      flush_interval -1
    }
}
<portainer_subdomain>.<domain_name> {
        reverse_proxy portainer:9443
}
<baserow_subdomain>.<domain_name> {
        reverse_proxy baserow:3002
}

2. Error messages and/or full log output:

Visiting the baserow domain, I got a error 502.

I am not sure what I did wrong. I was able to reach baserow if I set the variable BASEROW_PUBLIC_URL in docker file to the n8n domain and I specify the port, which I set to 3002.
In that case, I can reach baserow using the n8n domain appending :3002, without SSL. The same is happening for portainer at :9443

3. Caddy version:

v2.7.6

4. How I installed and ran Caddy:

As I told before, I followed a guide from n8n documentation that helped me set up a docker stack with caddy and n8n. Here’s the guide for reference: Digital Ocean | n8n Docs

a. System environment:

Docker

d. My complete Caddy config:

<n8n_subdomain>.<domain_name> {
    reverse_proxy n8n:5678 {
      flush_interval -1
    }
}
<portainer_subdomain>.<domain_name> {
        reverse_proxy portainer:9443
}
<baserow_subdomain>.<domain_name> {
        reverse_proxy baserow:3002
}

You should use portainer’s HTTP port, not the HTTPS port. So probably port 8000.

Caddy proxies over HTTP to the upstream. There’s no real benefit to proxying over HTTPS because the traffic happens within your private network, so there’s not the same risk of tampering as when the traffic crosses public networks (the internet).

You can remove these lines from your Docker Compose config. You don’t need to publish the ports on the host, because the traffic goes through Caddy, and Caddy connects to those containers within the Docker network.

Having these ports publishes means that if someone can connect to your server on port 8000 or whatever, they could connect without HTTPS, unencrypted. You don’t want that, you want the only way to use the service to be over HTTPS, which Caddy handles for you.

You need to use the port internal to the Docker network to connect to it, so use reverse_proxy baserow:80. And you can remove the ports as per above as well.

2 Likes

Thank you, it worked!

I didn’t understand the portainer part you said.
Is it possible to reach portainer through 3rd level domain, too?
I tried replicate the steps for portainer, and it didn’t work.
Anyway, I:

  • took ports away from docker-compose.yml (portainer’s too)
  • edit the Caddyfile (portainer’s too) using :80 for baserow and portainer.

I don’t really use portainer, but I would like to start understanding it better, that’s why I put it on the server.

Thanks a lot! Baserow works perfectly!

You need to use specifically the port that Portainer listens on for HTTP requests. I assume that’s 8000 based on what you had in your docker-compose.yml. So try reverse_proxy portainer:8000.

1 Like