Fastcgi not working

1. Caddy version (caddy version):

caddy/caddy:2.1.1-alpine

2. How I run Caddy:

using docker:

FROM caddy/caddy:2.1.1-alpine
COPY Caddyfile /etc/caddy/Caddyfile

and docker-compose:

version: '3.7'
services:
  db:
    # specify container name to make it easier to run commands
    container_name: apf_db
    restart: always
    image: db
    build:
      context: ./db
    env_file:
      - ./.env
    networks:
      - network
    expose:
      - '5432'
    ports:
      # make the Postgres database accessible from outside the Docker container on port 5432
      - '5432:5432'
    volumes:
      - db_data:/var/lib/postgresql/data
      - sik_data:/sik_data
  ss:
    build:
      context: ./ss
    networks:
      - network
    container_name: ss
    restart: always
    env_file:
      - ./.env
    expose:
      - '7000'
    ports:
      - '7000:7000'
  graphql:
    container_name: apf_graphql
    restart: unless-stopped
    build:
      context: ./graphql
    networks:
      - network
    expose:
      - '5000'
    ports:
      - '5000:5000'
    depends_on:
      - db
    env_file:
      - ./.env
    command: [
        '--connection',
        '${DATABASE_URL}',
        '--schema',
        'apflora',
        '--append-plugins',
        'postgraphile-plugin-connection-filter,@graphile-contrib/pg-order-by-related,@graphile/postgis,postgraphile-plugin-connection-filter-postgis',
        '--jwt-token-identifier',
        'auth.jwt_token',
        '--default-role',
        'postgres',
        #'authenticator',
        '--jwt-secret',
        '${JWT_SECRET}',
        '--body-size-limit',
        '300kb',
        '--cors',
        '--disable-query-log',
        '--enable-query-batching',
        '--retry-on-init-fail',
      ]
  qgisserver:
    #image: camptocamp/qgis-server
    build:
      context: ./qgisserver
    volumes:
      - qgisserver_data:/data
    #links:
    #  - db:db
    ports:
      - '5555:80'
    expose:
      - '5555'
    restart: always
    networks:
      - network
    container_name: qgisserver
  caddy:
    build:
      context: ./caddy
    container_name: apf_caddy
    networks:
      - network
    depends_on:
      - graphql
      - qgisserver
    restart: always
    # original image downgrades user but that seems not to work
    # see: https://caddy.community/t/basic-docker-compose-setup-failing/6892/7?u=alexander_gabriel
    user: root
    ports:
      - '80:80'
      - '443:443'
    env_file:
      - ./.env
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - caddy_certs:/root/.local/share/caddy
      - caddy_config:/root/.config/caddy
volumes:
  db_data:
  sik_data:
  caddy_certs:
  caddy_config:
  qgisserver_data:
networks:
  network:

a. System environment:

a docker droplet on digitalocean.com (ubuntu I think)

d. My complete Caddyfile or JSON config:

# see: https://caddyserver.com/docs/caddyfile/concepts
{
  email alex.barbalex@gmail.com
  #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
  #debug
}

api.apflora.ch {
  reverse_proxy * apf_graphql:5000 {
    header_down Access-Control-Allow-Origin *
  }
}

ss.apflora.ch {
  reverse_proxy * ss:7000 {
    header_down Access-Control-Allow-Origin *
    header_down Access-Control-Allow-Methods "GET, POST, OPTIONS"
    header_up Host {http.request.host}
    header_up X-Real-IP {http.request.remote}
    header_up X-Forwarded-For {http.request.remote}
    header_up X-Forwarded-Port {http.request.port}
    header_up X-Forwarded-Proto {http.request.scheme}
  }
}

# caddy docs: 
# https://caddyserver.com/docs/modules/http.reverse_proxy.transport.fastcgi
# https://caddyserver.com/docs/caddyfile/directives/reverse_proxy
# example: https://github.com/opengisch/qgisserver-caddy/blob/master/Caddyfile
# nginx example: https://docs.qgis.org/3.10/en/docs/user_manual/working_with_ogc/server/containerized_deployment.html#usable-sample
gisdata.apflora.ch {
  reverse_proxy * qgisserver:5555 {
    transport fastcgi
  }
}

3. The problem I’m having:

Every time I hit https://gisdata.apflora.ch/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities, a 402 is returned and this error is logged:

{
  "level": "error",
  "ts": 1600184605.7592506,
  "logger": "http.log.error",
  "msg": "dial tcp 172.18.0.6:5555: connect: connection refused",
  "request": {
    "method": "GET",
    "uri": "/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities",
    "proto": "HTTP/2.0",
    "remote_addr": "77.57.29.8:55440",
    "host": "gisdata.apflora.ch",
    "headers": {
      "Cache-Control": ["max-age=0"],
      "Upgrade-Insecure-Requests": ["1"],
      "Dnt": ["1"],
      "User-Agent": [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
      ],
      "Accept": [
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
      ],
      "Sec-Fetch-Mode": ["navigate"],
      "Sec-Fetch-User": ["?1"],
      "Sec-Fetch-Site": ["cross-site"],
      "Sec-Fetch-Dest": ["document"],
      "Accept-Encoding": ["gzip, deflate, br"],
      "Accept-Language": [
        "de-CH,de;q=0.9,en-US;q=0.8,en;q=0.7,es-CR;q=0.6,es;q=0.5,de-DE;q=0.4"
      ]
    },
    "tls": {
      "resumed": false,
      "version": 772,
      "ciphersuite": 4865,
      "proto": "h2",
      "proto_mutual": true,
      "server_name": "gisdata.apflora.ch"
    }
  },
  "duration": 0.001660532,
  "status": 502,
  "err_id": "846kztqpg",
  "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:411)"
}

5. What I already tried:

I have tried adding options inside the transport fastcgi part of the Caddyfile. But that did not help and to be honest, I don’t know what is needed as there seem to be reasonable defaults but it is not clear to me whether that means that I skip them completely.

These paths aren’t right - in the Docker image for Caddy v2, the data is in /data and the config autosave is in /config. You should use this instead:

      - caddy_data:/data
      - caddy_config:/config

I don’t think any of these lines are necessary - Caddy already passes through the Host, and manipulates For and Proto appropriately.

Looking at the example linked for qgisserver, I think you’ll need to share a volume that contains the scripts to your Caddy container and use root to tell Caddy where to look for files. The example there looks about right.

Thanks for the hints concerning headers and volumes. I have been using caddy 2 since way back in beta so that might explain why these values were set.

As for the fastcgi problem, I am not sure I have understood you correctly.

I have tried this in the Caddyfile:

gisdata.apflora.ch {
  root * /etc/qgisserver
  reverse_proxy * qgisserver:5555 {
    transport fastcgi {
      env PGSERVICEFILE /etc/qgisserver/pg_service.conf
      env QGIS_PROJECT_FILE /etc/qgisserver/osm.qgs
    }
  }
}

But the next time I restarted the server I got the same error as before - only caddy completely stopped working.

When using:

gisdata.apflora.ch {
  root * /etc/qgisserver
  reverse_proxy * qgisserver:5555 {
    transport fastcgi {
      env QGIS_PROJECT_FILE /etc/qgisserver/osm.qgs
    }
  }
}

I got:

{
  "level": "error",
  "ts": 1600191736.7377632,
  "logger": "http.log.error",
  "msg": "dialing backend: dial tcp 172.18.0.6:5555: connect: connection refused",
  "request": {
    "method": "GET",
    "uri": "/?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities",
    "proto": "HTTP/2.0",
    "remote_addr": "77.57.29.8:56084",
    "host": "gisdata.apflora.ch",
    "headers": {
      "Upgrade-Insecure-Requests": ["1"],
      "Dnt": ["1"],
      "User-Agent": [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
      ],
      "Sec-Fetch-Site": ["cross-site"],
      "Sec-Fetch-Mode": ["navigate"],
      "Cache-Control": ["max-age=0"],
      "Accept": [
        "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
      ],
      "Sec-Fetch-User": ["?1"],
      "Sec-Fetch-Dest": ["document"],
      "Accept-Encoding": ["gzip, deflate, br"],
      "Accept-Language": [
        "de-CH,de;q=0.9,en-US;q=0.8,en;q=0.7,es-CR;q=0.6,es;q=0.5,de-DE;q=0.4"
      ]
    },
    "tls": {
      "resumed": false,
      "version": 772,
      "ciphersuite": 4865,
      "proto": "h2",
      "proto_mutual": true,
      "server_name": "gisdata.apflora.ch"
    }
  },
  "duration": 0.00169636,
  "status": 502,
  "err_id": "hcm4sbi75",
  "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:411)"
}


If the qgisserver scripts are in /etc/qgisserver, then you’ll need to share a docker volume between the Caddy container and the qgisserver container, so that Caddy can serve the files for it.

Also, are you sure you’re using the right port number? The example you linked uses 9993. This might be the port the fastcgi server is listening on in that container.

You did port map 5555:80, but that’s on the host, not inside the docker network.

Reading the example, you’ll also need the file_server and the matcher to make fastcgi only happen on certain paths.

gisdata.apflora.ch {
    root * /io/www/html
    file_server

    @ows path_regexp map_file ^/ows/(.*)
    reverse_proxy @ows qgisserver:9993 {
        transport fastcgi {
            env QUERY_STRING {query}&map=/io/data/{re.map_file.1}.qgs
            env PGSERVICEFILE /io/.pg_service.conf
        }
    }
}

But frankly, I know nothing about qgisserver, I’m just going on what that linked example says, which looks reasonable to me, and I think we can assume it’s a working example.

You might want to open an issue on that repo to ask whoever wrote it some more detail about the setup (like what the docker stack looks like, etc, assuming it’s run in docker – which I think it is, because of the use of qgisserver as the proxy upstream, which looks like a container name)

o.k., will see what I manage with your great help. Thanks a lot!