Could not find solver for: tls-alpn-01

1. My Caddy version (caddy -version):

docker image caddy/caddy:alpine. I don’t know what version of 2 that is and also don’t know how to find out.

2. How I run Caddy:

in docker using docker-compose

a. System environment:

OS, relevant versions, systemd? docker? etc.
digital ocean marketplace docker droplet running Ubuntu Docker 5:19.03.1~3 on 18.04

b. Command:

docker-compose up -d --force-recreate

c. Service/unit/compose file:

version: '3.7'
services:
  db:
    # specify container name to make it easier to run commands.
    # for example, you could run docker exec -i postgres psql -U postgres postgres < schema.sql to run an SQL file against the Postgres database
    container_name: ae_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
  graphql:
    container_name: ae_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',
        'ae',
        '--append-plugins',
        'postgraphile-plugin-connection-filter,@graphile-contrib/pg-order-by-related',
        '--jwt-token-identifier',
        'auth.jwt_token',
        '--default-role',
        'anon',
        '--jwt-secret',
        '${JWT_SECRET}',
        '--cors',
        '--disable-query-log',
        '--enable-query-batching',
        '--retry-on-init-fail',
      ]
  json:
    container_name: ae_json
    restart: always
    build:
      context: ./json
    networks:
      - network
    expose:
      - '4000'
    ports:
      - '4000:4000'
    depends_on:
      - db
    env_file:
      - ./.env
  caddy:
    # https://hub.docker.com/r/caddy/caddy/dockerfile
    image: caddy/caddy:alpine
    container_name: ae_caddy
    networks:
      - network
    depends_on:
      - graphql
      - json
    restart: always
    # 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/.caddy
volumes:
  db_data:
  sik_data:
  caddy_certs:
networks:
  network:

d. My complete Caddyfile:

{
  email alex.barbalex@gmail.com
}

api.art-eigenschaften.ch {
  reverse_proxy /graphql/* localhost:5000
  reverse_proxy /graphiql/* localhost:5000
  reverse_proxy /artendb/* localhost:4000
  reverse_proxy /evab/* localhost:4000
  reverse_proxy /alt/* localhost:4000
}

3. The problem I’m having:

When I start up docker-compose there is an error in the caddy log saying that no solver could be found for tls-alpn-01.

Later when I try to connect to the services, for instance typing https://api.art-eigenschaften.ch/alt in the browser, the server responds with a 200 status but without any response (page remains blank). Looking at the caddy log there seems to be a handshake error.

4. Error messages and/or full log output:

Recreating the services:

root@artdaten-docker:~/ae# docker-compose up -d --force-recreate
Recreating ae_db ... done
Recreating ae_json    ... done
Recreating ae_graphql ... done
Recreating ae_caddy   ... done

Checking the logs after recreating and trying to connect:

root@artdaten-docker:~/ae# docker logs ae_caddy
2020/02/03 13:10:36.162 INFO    using provided configuration    {"config_file": "/etc/caddy/Caddyfile", "config_adapter": "caddyfile"}
2020/02/03 13:10:36.327 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["localhost:2019"]}
2020/02/03 13:10:36.327 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2020/02/03 13:10:36.327 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2020/02/03 13:10:36.328 INFO    http    enabling automatic TLS certificate management   {"domains": ["api.art-eigenschaften.ch"]}
2020/02/03 13:10:36.330 INFO    tls     cleaned up storage units
2020/02/03 13:10:36.330 INFO    autosaved config        {"file": "/root/.config/caddy/autosave.json"}
2020/02/03 13:10:36.330 INFO    serving initial configuration
2020/02/03 13:10:36 [INFO][cache:0xc000190910] Started certificate maintenance routine
2020/02/03 13:10:37 [INFO] acme: Registering account for alex.barbalex@gmail.com
2020/02/03 13:10:37 [INFO][api.art-eigenschaften.ch] Obtain certificate
2020/02/03 13:10:37 [INFO][api.art-eigenschaften.ch] Obtain: Waiting on rate limiter...
2020/02/03 13:10:37 [INFO][api.art-eigenschaften.ch] Obtain: Done waiting
2020/02/03 13:10:37 [INFO] [api.art-eigenschaften.ch] acme: Obtaining bundled SAN certificate
2020/02/03 13:10:38 [INFO] [api.art-eigenschaften.ch] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/2621774933
2020/02/03 13:10:38 [INFO] [api.art-eigenschaften.ch] acme: Could not find solver for: tls-alpn-01
2020/02/03 13:10:38 [INFO] [api.art-eigenschaften.ch] acme: use http-01 solver
2020/02/03 13:10:38 [INFO] [api.art-eigenschaften.ch] acme: Trying to solve HTTP-01
2020/02/03 13:10:38 [INFO][api.art-eigenschaften.ch] Served key authentication (distributed)
2020/02/03 13:10:38 [INFO][api.art-eigenschaften.ch] Served key authentication (distributed)
2020/02/03 13:10:38 [INFO][api.art-eigenschaften.ch] Served key authentication (distributed)
2020/02/03 13:10:38 [INFO][api.art-eigenschaften.ch] Served key authentication (distributed)
2020/02/03 13:10:41 [INFO] [api.art-eigenschaften.ch] The server validated our request
2020/02/03 13:10:41 [INFO] [api.art-eigenschaften.ch] acme: Validations succeeded; requesting certificates
2020/02/03 13:10:42 [INFO] [api.art-eigenschaften.ch] Server responded with a certificate.
2020/02/03 13:15:21 http: TLS handshake error from 34.211.60.134:55128: no certificate to complete TLS-ALPN challenge for SNI name: api.art-eigenschaften.ch
2020/02/03 13:15:21 http: TLS handshake error from 18.224.20.83:15354: no certificate to complete TLS-ALPN challenge for SNI name: api.art-eigenschaften.ch

5. What I already tried:

Scratched my head. Did not help :smile:

6. Links to relevant resources:

Here is the complete code: ae2/backend at master · FNSKtZH/ae2 · GitHub

This message:

Could not find solver for: tls-alpn-01

is normal. Caddy randomly chooses a challenge to start with, so in your case it chose HTTP-01 first. Is there actually something not working?

A blank page usually means the TLS handshake succeeded but no routes were configured for your request. Using curl -v will help you know better.

FYI I think in Caddy v2 the volume you should persist is different. The paths are /root/.config/caddy and /root/.local/share/caddy

See Conventions — Caddy Documentation

thanks @matt and @francislavoie
great help!
I now adjusted the file locations but am running into rate limiting again :crazy_face:
Meanwhile I have gone through 3 domains already and the config still does not work.
Will have to experiment with a fourth I guess…

I think this might be one of the issues - Caddy will only proxy paths that start with /alt/. If you need /alt to work, make the path matcher /alt*

1 Like

@francislavoie
Really nice of you to spot that!

After correcting that I got cors errors. So I tried enabling cors and now with this Caddyfile:
(inspired by V2: how to add the CORS authorization via Caddyfile?)

{
  email alex.barbalex@gmail.com
}

api.arten-foerdern.ch {
  reverse_proxy /graphql* localhost:5000
  reverse_proxy /graphiql* localhost:5000
  reverse_proxy /artendb/* localhost:4000
  reverse_proxy /evab* localhost:4000
  reverse_proxy /alt* localhost:4000
  header / {
    Access-Control-Allow-Origin *
    -Server
  }
}

I get this log after rebuilding:

root@artdaten-docker:~/ae# docker logs ae_caddy
2020/02/03 19:16:46.069 INFO    using provided configuration    {"config_file": "/etc/caddy/Caddyfile", "config_adapter": "caddyfile"}
2020/02/03 19:16:46.143 INFO    admin   admin endpoint started  {"address": "localhost:2019", "enforce_origin": false, "origins": ["localhost:2019"]}
2020/02/03 19:16:46.143 INFO    http    server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS {"server_name": "srv0", "https_port": 443}
2020/02/03 19:16:46.143 INFO    http    enabling automatic HTTP->HTTPS redirects        {"server_name": "srv0"}
2020/02/03 19:16:46.144 INFO    http    enabling automatic TLS certificate management   {"domains": ["api.arten-foerdern.ch"]}
2020/02/03 19:16:46.144 INFO    tls     cleaned up storage units
2020/02/03 19:16:46.146 INFO    autosaved config        {"file": "/root/.config/caddy/autosave.json"}
2020/02/03 19:16:46.146 INFO    serving initial configuration
2020/02/03 19:16:46 [INFO][cache:0xc000160d20] Started certificate maintenance routine
2020/02/03 19:16:47 [INFO] acme: Registering account for alex.barbalex@gmail.com
2020/02/03 19:16:47 [INFO][api.arten-foerdern.ch] Obtain certificate
2020/02/03 19:16:47 [INFO][api.arten-foerdern.ch] Obtain: Waiting on rate limiter...
2020/02/03 19:16:47 [INFO][api.arten-foerdern.ch] Obtain: Done waiting
2020/02/03 19:16:47 [INFO] [api.arten-foerdern.ch] acme: Obtaining bundled SAN certificate
2020/02/03 19:16:47 [INFO] [api.arten-foerdern.ch] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/2625990049
2020/02/03 19:16:47 [INFO] [api.arten-foerdern.ch] acme: Could not find solver for: tls-alpn-01
2020/02/03 19:16:47 [INFO] [api.arten-foerdern.ch] acme: use http-01 solver
2020/02/03 19:16:47 [INFO] [api.arten-foerdern.ch] acme: Trying to solve HTTP-01
2020/02/03 19:16:48 [INFO][api.arten-foerdern.ch] Served key authentication (distributed)
2020/02/03 19:16:48 [INFO][api.arten-foerdern.ch] Served key authentication (distributed)
2020/02/03 19:16:48 [INFO][api.arten-foerdern.ch] Served key authentication (distributed)
2020/02/03 19:16:48 [INFO][api.arten-foerdern.ch] Served key authentication (distributed)
2020/02/03 19:16:55 [INFO] [api.arten-foerdern.ch] The server validated our request
2020/02/03 19:16:55 [INFO] [api.arten-foerdern.ch] acme: Validations succeeded; requesting certificates
2020/02/03 19:16:56 [INFO] [api.arten-foerdern.ch] Server responded with a certificate.

But can’t connect to https://api.arten-foerdern.ch/graphql:

2020/02/03 19:17:14.107 ERROR   http.log.error  dial tcp 127.0.0.1:5000: connect: connection refused    {"request": {"method": "OPTIONS", "uri": "/graphql", "proto": "HTTP/2.0", "remote_addr": "77.57.29.8:54225", "host": "api.arten-foerdern.ch", "headers": {"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"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36"], "Accept-Encoding": ["gzip, deflate, br"], "Access-Control-Request-Headers": ["content-type"], "Origin": ["https://arten-foerdern.ch"], "Sec-Fetch-Mode": ["cors"], "Sec-Fetch-Site": ["same-site"], "Referer": ["https://arten-foerdern.ch/"], "Accept": ["*/*"], "Access-Control-Request-Method": ["POST"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "api.arten-foerdern.ch"}}, "status": 502, "err_id": "u81h92ats", "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:362)"}

On the app side a cors error is still logged:

Access to fetch at 'https://api.arten-foerdern.ch/graphql' from origin 'https://arten-foerdern.ch' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I am a frontend guy. Probably I am completely bungling up this routing…

1 Like

I have now changed the Caddyfile to:

{
  email alex.barbalex@gmail.com
}

api.arten-foerdern.ch {
  reverse_proxy /graphql* {
    to localhost:5000
    header_down Access-Control-Allow-Origin *
  }
  reverse_proxy /graphiql* {
    to localhost:5000
    header_down Access-Control-Allow-Origin *
  }
  reverse_proxy /artendb/* {
    to localhost:4000
    header_down Access-Control-Allow-Origin *
  }
  reverse_proxy /evab* {
    to localhost:4000
    header_up Access-Control-Allow-Origin *
  }
  reverse_proxy /alt* {
    to localhost:4000
    header_down Access-Control-Allow-Origin *
  }
}

as I feel that is more likely what it should be according to the docs. But I am not sure at all. There seemst to be no example on how to set cors or even place a header.

Unfortunately the proxied routes are still not answering.

This is the output from curl -v https://api.arten-foerdern.ch/graphql:

root@artdaten:~/ae# curl -v https://api.arten-foerdern.ch/graphql
*   Trying 167.172.187.231...
* TCP_NODELAY set
* Connected to api.arten-foerdern.ch (167.172.187.231) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Unknown (8):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Client hello (1):
* TLSv1.3 (OUT), TLS Unknown, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=api.arten-foerdern.ch
*  start date: Feb  4 16:27:50 2020 GMT
*  expire date: May  4 16:27:50 2020 GMT
*  subjectAltName: host "api.arten-foerdern.ch" matched cert's "api.arten-foerdern.ch"
*  issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* Using Stream ID: 1 (easy handle 0x55e66bb6f580)
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
> GET /graphql HTTP/2
> Host: api.arten-foerdern.ch
> User-Agent: curl/7.58.0
> Accept: */*
>
* TLSv1.3 (IN), TLS Unknown, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* TLSv1.3 (OUT), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
* TLSv1.3 (IN), TLS Unknown, Unknown (23):
< HTTP/2 502
< server: Caddy
< content-length: 0
< date: Tue, 04 Feb 2020 17:57:53 GMT
<
* Connection #0 to host api.arten-foerdern.ch left intact

The issue was solved here: How to reverse_proxy and allow cors in v2 - #5 by Alexander_Gabriel

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