Hedgedoc 2 - cloudflare tunnel

Has anyone got hedgedoc v2 running behind cf tunnel?

My version of HedgeDoc is: docker develop

What I expected to happen:

I want to deploy with cf tunnel. Different projects prefer different methods, caddy, nginx-proxy, traefik, etc. My port 80/443 is already used by other system. The cf tunnel would be independent of that.

What actually happened:

I tried many things, but got either 502 bad gateway or just a white web page.

I already tried:

I have it running locally, so I wanted to use the tunnel to make it available on the web.

locally:

I tried many settings in cloudflare, caddyfile and .env.

I am getting this:
You can’t open this page using this URL. For this endpoint “http://hedge2dproxy:8080/” is expected but got “https://hedge2d.daveg.win”.

cloudflare setup…

frontend-1      | [2025-06-26 14:20:08] (Base URL Configuration) Editor base URL http://hedge2dproxy:8080/
frontend-1      | [2025-06-26 14:20:08] (Base URL Configuration) Renderer base URL http://hedge2dproxy:8080/
frontend-1      | Yjs was already imported. This breaks constructor checks and will lead to issues! - https://github.com/yjs/yjs/issues/438
hedge2dproxy-1  | {"level":"info","ts":1750947650.6778095,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"hedge2d.daveg.win"}
hedge2dproxy-1  | {"level":"info","ts":1750947650.6904933,"logger":"http","msg":"creating new account because no account for configured email is known to us","email":"","ca":"https://acme-staging-v02.api.letsencrypt.org/directory","error":"open /data/caddy/acme/acme-staging-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
hedge2dproxy-1  | {"level":"info","ts":1750947650.6911416,"logger":"http","msg":"ACME account has empty status; registering account with ACME server","contact":[],"location":""}
hedge2dproxy-1  | {"level":"info","ts":1750947650.7108114,"logger":"http","msg":"creating new account because no account for configured email is known to us","email":"","ca":"https://acme-staging-v02.api.letsencrypt.org/directory","error":"open /data/caddy/acme/acme-staging-v02.api.letsencrypt.org-directory/users/default/default.json: no such file or directory"}
hedge2dproxy-1  | {"level":"info","ts":1750947651.2042317,"logger":"http","msg":"new ACME account registered","contact":[],"status":"valid"}
hedge2dproxy-1  | {"level":"info","ts":1750947651.2095656,"logger":"http","msg":"using ACME account","account_id":"https://acme-staging-v02.api.letsencrypt.org/acme/acct/208563933","account_contact":[]}
hedge2dproxy-1  | {"level":"info","ts":1750947651.3262362,"msg":"trying to solve challenge","identifier":"hedge2d.daveg.win","challenge_type":"http-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
hedge2dproxy-1  | {"level":"info","ts":1750947651.689065,"logger":"http","msg":"served key authentication","identifier":"hedge2d.daveg.win","challenge":"http-01","remote":"172.19.0.3:36908","distributed":false}
hedge2dproxy-1  | {"level":"info","ts":1750947651.841357,"logger":"http","msg":"served key authentication","identifier":"hedge2d.daveg.win","challenge":"http-01","remote":"172.19.0.3:36908","distributed":false}
hedge2dproxy-1  | {"level":"info","ts":1750947652.0371695,"logger":"http","msg":"served key authentication","identifier":"hedge2d.daveg.win","challenge":"http-01","remote":"172.19.0.3:36908","distributed":false}
hedge2dproxy-1  | {"level":"info","ts":1750947652.154611,"logger":"http","msg":"served key authentication","identifier":"hedge2d.daveg.win","challenge":"http-01","remote":"172.19.0.3:36908","distributed":false}
hedge2dproxy-1  | {"level":"info","ts":1750947652.5233467,"logger":"http","msg":"served key authentication","identifier":"hedge2d.daveg.win","challenge":"http-01","remote":"172.19.0.3:36908","distributed":false}
hedge2dproxy-1  | {"level":"info","ts":1750947653.2032115,"msg":"authorization finalized","identifier":"hedge2d.daveg.win","authz_status":"valid"}
hedge2dproxy-1  | {"level":"info","ts":1750947653.2033236,"msg":"validations succeeded; finalizing order","order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/208563933/25649346143"}
hedge2dproxy-1  | {"level":"info","ts":1750947656.454575,"msg":"got renewal info","names":["hedge2d.daveg.win"],"window_start":1756051587,"window_end":1756207036,"selected_time":1756057920,"recheck_after":1750969256.4545383,"explanation_url":""}
hedge2dproxy-1  | {"level":"info","ts":1750947656.621224,"msg":"got renewal info","names":["hedge2d.daveg.win"],"window_start":1756051587,"window_end":1756207036,"selected_time":1756177100,"recheck_after":1750969256.6211996,"explanation_url":""}
hedge2dproxy-1  | {"level":"info","ts":1750947656.6218731,"msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-staging-v02.api.letsencrypt.org/acme/cert/2c576f604d344f310cc23c3ee8d76e37e1b9"}
hedge2dproxy-1  | {"level":"info","ts":1750947656.6231437,"logger":"http","msg":"waiting on internal rate limiter","identifiers":["hedge2d.daveg.win"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
hedge2dproxy-1  | {"level":"info","ts":1750947656.6233177,"logger":"http","msg":"done waiting on internal rate limiter","identifiers":["hedge2d.daveg.win"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
hedge2dproxy-1  | {"level":"info","ts":1750947656.6234124,"logger":"http","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/2490476081","account_contact":[]}
hedge2dproxy-1  | {"level":"error","ts":1750947656.7305098,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"hedge2d.daveg.win","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 429 urn:ietf:params:acme:error:rateLimited - too many certificates (5) already issued for this exact set of identifiers in the last 168h0m0s, retry after 2025-06-28 00:27:52 UTC: see https://letsencrypt.org/docs/rate-limits/#new-certificates-per-exact-set-of-hostnames"}
hedge2dproxy-1  | {"level":"error","ts":1750947656.7311492,"logger":"tls.obtain","msg":"will retry","error":"[hedge2d.daveg.win] Obtain: [hedge2d.daveg.win] creating new order: attempt 1: https://acme-v02.api.letsencrypt.org/acme/new-order: HTTP 429 urn:ietf:params:acme:error:rateLimited - too many certificates (5) already issued for this exact set of identifiers in the last 168h0m0s, retry after 2025-06-28 00:27:52 UTC: see https://letsencrypt.org/docs/rate-limits/#new-certificates-per-exact-set-of-hostnames (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":2,"retrying_in":120,"elapsed":66.548927158,"max_duration":2592000}
w Enable Watch

# SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
# SPDX-License-Identifier: AGPL-3.0-only
---
# http://192.168.88.77:3001

networks:
  sister2:
    name: sister2
    external: true
  sister:
    name: sister
    external: true
    
services:

  backend:
    image: ghcr.io/hedgedoc/hedgedoc/backend:develop
    volumes:
      - $PWD/.env:/usr/src/app/backend/.env
      - hedgedoc_uploads:/usr/src/app/backend/uploads
    environment:
      HD_BASE_URL: "${HD_BASE_URL}"
      HOST: 0.0.0.0
    networks:
      - sister2
      - sister
    ports:
      - "13000:3000"  
      
  frontend:
    image: ghcr.io/hedgedoc/hedgedoc/frontend:develop
    environment:
      HD_BASE_URL: "${HD_BASE_URL}"
      HOST: 0.0.0.0
    ports:
      - "13001:3001"
    networks:
      - sister2
      - sister
      
  db:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: "${HD_DATABASE_USER}"
      POSTGRES_PASSWORD: "${HD_DATABASE_PASS}"
      POSTGRES_DB: "${HD_DATABASE_NAME}"
    networks:
      - sister2
      - sister
      
  hedge2dproxy:
    image: caddy:latest
    restart: unless-stopped
    environment:
      HD_BASE_URL: "${HD_BASE_URL}"
    ports:
      - "3380:80"
      - "8084:8080"
      - "3443:443"
      - "3443:443/udp"
    volumes:
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    networks:
      - sister2
      - sister
      
volumes:
  hedgedoc_uploads:
  caddy_data:
# 192.168.88.103 https://hedgedoc2.localhost 

#HD_BASE_URL="https://hedgedoc2.localhost"
HD_BASE_URL="http://hedge2dproxy:8080"
#HD_BASE_URL="https://hedge2d.daveg.win"

HD_SESSION_SECRET="2201change_me_in_production"
# Database settings
HD_DATABASE_TYPE="postgres"
HD_DATABASE_HOST="db"
HD_DATABASE_PORT="5432"
HD_DATABASE_NAME="hedgedoc2"
HD_DATABASE_USER="muser"
HD_DATABASE_USERNAME="muser"
HD_DATABASE_PASS="xx"
HD_DATABASE_PASSWORD="xx"
# Uploads
HD_MEDIA_BACKEND="filesystem"
HD_MEDIA_BACKEND_FILESYSTEM_UPLOAD_PATH="uploads/"
# Auth
HD_AUTH_LOCAL_ENABLE_LOGIN="true"
HD_AUTH_LOCAL_ENABLE_REGISTER="true"

#
# SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file)
#
# SPDX-License-Identifier: AGPL-3.0-only
#

# Allow private ranges as proxies, for example when running Caddy behind another reverse proxy
# Otherwise Caddy strips the required X-Forwarded-Proto and X-Forwarded-Host headers
# This is a common scenario when exposing a local dev setup to someone else
{
    servers {
        trusted_proxies static private_ranges
    }
}

# Use port 8080 by default, but allow overriding using CADDY_HOST env variable
{$CADDY_HOST::8080} {

    log {
	    output stdout
        level WARN
	    format console
    }

	reverse_proxy /realtime http://backend:3000
	reverse_proxy /api/* http://backend:3000
	reverse_proxy /public/* http://backend:3000
	reverse_proxy /uploads/* http://backend:3000
	reverse_proxy /apidoc/* http://backend:3000
	reverse_proxy /* http://frontend:3001
}

https://hedge2d.daveg.win {

	reverse_proxy /realtime http://backend:3000
	reverse_proxy /api/* http://backend:3000
	reverse_proxy /public/* http://backend:3000
	reverse_proxy /uploads/* http://backend:3000
	reverse_proxy /apidoc/* http://backend:3000
	reverse_proxy /* http://frontend:3001
}

# reverse_proxy frontend:3001
 

Unfortunately, I can’t help with that, but I can tell you that I run HedgeDoc v1 behind a Pangolin tunnel with no problems - just a hint: Pangolin has an integrated Treafik reverse proxy, so you do not need a separated Caddy setup. I am not familiar with CF tunnels.

I too have hedgedoc v1 behind a tunnel - a clouldflare tunnel. I hope we can figure out how to do it with hedgedoc v2.

Please, if there is anyone out there that may have a hint for information, let us know.