Incorrect documentation

Issue #859 new
rcd created an issue

https://poste.io/doc/faq suggest using .well-known from nginx-proxy-manager container, but there is no .well-known folders there.

# docker exec -ti nginx-proxy-manager bash
bash-5.0# find / -name .well-known -print
bash-5.0#

The faq also refers to jwilder/nginx-proxy but it is now called jwilder/nginx-proxy-manager, and has Lets Encrypt embedded, so no companion container is used now.

Given the nginx-proxy-manager will take are of the user-faced certificate, would it not be easier to just mount the folder with the certificates and allow users to self-sign the TLS certificates which would allow for 10 year certs…

Comments (22)

  1. Mike DiMeglio

    .well-known is exposed in nginx-proxy-manager as /<data folder>/letsencrypt-acme-challenge. You can see this in the nginx.conf for nginx-proxy-manager which refers to that folder as a proxy location. You’d have to map this folder into poste.io container with the proper permissions. One issue poste.io has is unpredictable UID/GID, so it requires some loose permissions on that folder to read/write to.

  2. rcd reporter

    The /data/letsencrypt-acme-challenge is empty here, so is /data/letsencrypt-workdir. /data/letsencrypt has a number of files and directories - keys, certs, config files etc. but no .well-known files.

    I’m using the jlesage/nginx-proxy-manager:latest image.

    # docker exec -ti nginx-proxy-manager bash
    bash-5.0# cd /data/letsencrypt-acme-challenge/
    bash-5.0# pwd
    /data/letsencrypt-acme-challenge
    bash-5.0# ls -al
    total 8
    drwxr-xr-x    2 app      app           4096 May  5 00:25 .
    drwxr-xr-x    9 app      app           4096 May  6 09:51 ..
    bash-5.0#
    

    What could be the problem?

  3. Mike DiMeglio

    .well-known (letsencrypt-acme-challenge in this container) is supposed to be empty unless there’s an active cert request being processed. Nothing is wrong. You have to map poste.io’s .well-known to that folder so it can use it.

  4. rcd reporter

    Ok now I understand.

    Anyway, I tried mounting the volumes as you suggested, i.e:

    volumes:
      - /data/poste.io/data:/data
      - /data/nginx-proxy-manager/config/letsencrypt-acme-challenge:/opt/www/.well-known/acme-challenge
    

    Now when I go to poste.io admin interface and attempt to create a TLS cert it takes a bit longer than before, and a new file appears in /data/nginx-proxy-manager/config/letsencrypt-acme-challenge, so something seems to go ok, but the API log still throws an error:

    [2021-05-07 23:43:58] LEScript.INFO: Getting list of URLs for API
    [2021-05-07 23:44:02] LEScript.INFO: Requesting new nonce for client communication
    [2021-05-07 23:44:07] LEScript.INFO: Account already registered. Continuing.
    [2021-05-07 23:44:07] LEScript.INFO: Sending registration to letsencrypt server
    [2021-05-07 23:44:07] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-acct
    [2021-05-07 23:44:12] LEScript.INFO: Account: https://acme-v02.api.letsencrypt.org/acme/acct/111248833
    [2021-05-07 23:44:12] LEScript.INFO: Starting certificate generation process for domains
    [2021-05-07 23:44:12] LEScript.INFO: Requesting challenge for mail.robust.net
    [2021-05-07 23:44:12] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-order
    [2021-05-07 23:44:16] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/authz-v3/12934704942
    [2021-05-07 23:44:21] LEScript.INFO: Got challenge token for mail.robust.net
    [2021-05-07 23:44:21] LEScript.INFO: Token for mail.robust.net saved at /opt/www//.well-known/acme-challenge/uJDM3Pk7MvThfom2X2e0AWCfW-d_avsDo4ZCdmN70v0 and should be available at http://mail.robust.net/.well-known/acme-challenge/uJDM3Pk7MvThfom2X2e0AWCfW-d_avsDo4ZCdmN70v0
    [2021-05-07 23:44:21] LEScript.INFO: Sending request to challenge
    [2021-05-07 23:44:21] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12934704942/ODqORw
    [2021-05-07 23:44:25] LEScript.INFO: Verification pending, sleeping 1s
    [2021-05-07 23:44:26] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12934704942/ODqORw
    [2021-05-07 23:44:31] LEScript.ERROR: 400 {   "type": "urn:ietf:params:acme:error:malformed",   "detail": "Unable to update challenge :: authorization must be pending",   "status": 400 }
    [2021-05-07 23:44:31] LEScript.ERROR: #0 /opt/admin/vendor/analogic/lescript/Lescript.php(544): Analogic\ACME\Client->curl('POST', 'https://acme-v0...', '{"protected":"e...')
    [2021-05-07 23:44:31] LEScript.ERROR: #1 /opt/admin/vendor/analogic/lescript/Lescript.php(422): Analogic\ACME\Client->post('https://acme-v0...', '{"protected":"e...')
    [2021-05-07 23:44:31] LEScript.ERROR: #2 /opt/admin/vendor/analogic/lescript/Lescript.php(165): Analogic\ACME\Lescript->signedRequest('https://acme-v0...', Array)
    [2021-05-07 23:44:31] LEScript.ERROR: #3 /opt/admin/src/AppBundle/Handler/LeHandler.php(62): Analogic\ACME\Lescript->signDomains(Array)
    [2021-05-07 23:44:31] LEScript.ERROR: #4 /opt/admin/src/AppBundle/Controller/LeController.php(71): AppBundle\Handler\LeHandler->renew(true)
    [2021-05-07 23:44:31] LEScript.ERROR: #5 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(151): AppBundle\Controller\LeController->issueAction(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-07 23:44:31] LEScript.ERROR: #6 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
    [2021-05-07 23:44:31] LEScript.ERROR: #7 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(200): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    [2021-05-07 23:44:31] LEScript.ERROR: #8 /opt/admin/web/app.php(16): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-07 23:44:31] LEScript.ERROR: #9 {main}
    

  5. Mike DiMeglio

    That’s more interesting for sure - looks like you did everything right and it’s attempting to communicate with LetsEncrypt. Given that only 5 seconds go by before it tries to verify twice, and the error is "Unable to update challenge :: authorization must be pending", "status": 400 that seems to be a timeout. Maybe it’s not waiting long enough for a reply or LetsEncrypt is busy?

  6. rcd reporter

    I just tried again:

    [2021-05-08 10:33:39] LEScript.INFO: Getting list of URLs for API
    [2021-05-08 10:33:44] LEScript.INFO: Requesting new nonce for client communication
    [2021-05-08 10:33:48] LEScript.INFO: Account already registered. Continuing.
    [2021-05-08 10:33:48] LEScript.INFO: Sending registration to letsencrypt server
    [2021-05-08 10:33:48] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-acct
    [2021-05-08 10:33:53] LEScript.INFO: Account: https://acme-v02.api.letsencrypt.org/acme/acct/111248833
    [2021-05-08 10:33:53] LEScript.INFO: Starting certificate generation process for domains
    [2021-05-08 10:33:53] LEScript.INFO: Requesting challenge for mail.robust.net
    [2021-05-08 10:33:53] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-order
    [2021-05-08 10:33:58] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/authz-v3/12946908172
    [2021-05-08 10:34:02] LEScript.INFO: Got challenge token for mail.robust.net
    [2021-05-08 10:34:02] LEScript.INFO: Token for mail.robust.net saved at /opt/www//.well-known/acme-challenge/-YmlGOFtVE52JmqRJuUNMp-68fwaCjcqS4aAfAnUVCQ and should be available at http://mail.robust.net/.well-known/acme-challenge/-YmlGOFtVE52JmqRJuUNMp-68fwaCjcqS4aAfAnUVCQ
    [2021-05-08 10:34:02] LEScript.INFO: Sending request to challenge
    [2021-05-08 10:34:02] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12946908172/wtc4MA
    [2021-05-08 10:34:07] LEScript.INFO: Verification pending, sleeping 1s
    [2021-05-08 10:34:08] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12946908172/wtc4MA
    [2021-05-08 10:34:12] LEScript.ERROR: 400 {   "type": "urn:ietf:params:acme:error:malformed",   "detail": "Unable to update challenge :: authorization must be pending",   "status": 400 }
    [2021-05-08 10:34:12] LEScript.ERROR: #0 /opt/admin/vendor/analogic/lescript/Lescript.php(544): Analogic\ACME\Client->curl('POST', 'https://acme-v0...', '{"protected":"e...')
    [2021-05-08 10:34:12] LEScript.ERROR: #1 /opt/admin/vendor/analogic/lescript/Lescript.php(422): Analogic\ACME\Client->post('https://acme-v0...', '{"protected":"e...')
    [2021-05-08 10:34:12] LEScript.ERROR: #2 /opt/admin/vendor/analogic/lescript/Lescript.php(165): Analogic\ACME\Lescript->signedRequest('https://acme-v0...', Array)
    [2021-05-08 10:34:12] LEScript.ERROR: #3 /opt/admin/src/AppBundle/Handler/LeHandler.php(62): Analogic\ACME\Lescript->signDomains(Array)
    [2021-05-08 10:34:12] LEScript.ERROR: #4 /opt/admin/src/AppBundle/Controller/LeController.php(71): AppBundle\Handler\LeHandler->renew(true)
    [2021-05-08 10:34:12] LEScript.ERROR: #5 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(151): AppBundle\Controller\LeController->issueAction(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-08 10:34:12] LEScript.ERROR: #6 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
    [2021-05-08 10:34:12] LEScript.ERROR: #7 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(200): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    [2021-05-08 10:34:12] LEScript.ERROR: #8 /opt/admin/web/app.php(16): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-08 10:34:12] LEScript.ERROR: #9 {main}
    

    … and I noticed, going to the link referenced - should be available at http://mail.robust.net/.well-known/acme-challenge/-YmlGOFtVE52JmqRJuUNMp-68fwaCjcqS4aAfAnUVCQ throws an error 404 Not Found by the proxy manager so I suppose it’s not surprising the challenge fails?

    mail.robust.net is pointing directly to http://poste:80 on the internal docker network (i.e. not redirecting to a sub folder or anything). Is that ok?

  7. rcd reporter

    A bit more testing:
    I created an index.html in /opt/www/.well-known/acme-challenge but going to http://mail.robust.net/.well-known/acme-challenge/index.html threw a 404 Not Found.

    I then moved it up to .well-known – and now it’s found.

    So

    https://mail.robust.net/.well-known/acme-challenge/index.html → not found

    https://mail.robust.net/.well-known/index.html → found

    I noticed the acme-challenge folder is mode 777 so perhaps it was restricted due to lax permissions but changing it to 755 threw same error.

    So checking the /var/log/nginx/access_log in the poste.io container, I get an entry every time I go to https://mail.robust.net/.well-known/index.html but nothing when I go to https://mail.robust.net/.well-known/acme-challenge/index.html. So it seems like nginx doesn’t even get the request for files under acme-challenge? Would that be something configured in poste.io’s nginx config, or in nginx-proxy-managers nginx config? I feel it’s too specific to have been caused by nginx-proxy-manager. On the other hand, why should either of them block access to acme-challenge?

  8. rcd reporter

    Sorry, so to clarify:

    The challenge files are present under /opt/www/.well-known/acme-challenge, but nginx don’t show them.

  9. Mike DiMeglio

    Try changing your map of /data/nginx-proxy-manager/config/letsencrypt-acme-challenge:/opt/www/.well-known/acme-challenge/data/nginx-proxy-manager/config/letsencrypt-acme-challenge:/opt/www/.well-known/and seeing if that changes anything?

  10. rcd reporter
    volumes:
      - /data/poste.io/data:/data
      - /data/nginx-proxy-manager/config/letsencrypt-acme-challenge:/opt/www/.well-known
    

    But still same error:

    [2021-05-08 17:09:24] LEScript.INFO: Getting list of URLs for API
    [2021-05-08 17:09:28] LEScript.INFO: Requesting new nonce for client communication
    [2021-05-08 17:09:33] LEScript.INFO: Account already registered. Continuing.
    [2021-05-08 17:09:33] LEScript.INFO: Sending registration to letsencrypt server
    [2021-05-08 17:09:33] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-acct
    [2021-05-08 17:09:37] LEScript.INFO: Account: https://acme-v02.api.letsencrypt.org/acme/acct/111202360
    [2021-05-08 17:09:37] LEScript.INFO: Starting certificate generation process for domains
    [2021-05-08 17:09:37] LEScript.INFO: Requesting challenge for mail.robust.net
    [2021-05-08 17:09:37] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/new-order
    [2021-05-08 17:09:42] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/authz-v3/12953723697
    [2021-05-08 17:09:47] LEScript.INFO: Got challenge token for mail.robust.net
    [2021-05-08 17:09:47] LEScript.INFO: Token for mail.robust.net saved at /opt/www//.well-known/acme-challenge/vqBQ_1B8N4RnAL9fDvpswVyOr40IfUWJMBMRVxRF1nk and should be available at http://mail.robust.net/.well-known/acme-challenge/vqBQ_1B8N4RnAL9fDvpswVyOr40IfUWJMBMRVxRF1nk
    [2021-05-08 17:09:47] LEScript.INFO: Sending request to challenge
    [2021-05-08 17:09:47] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12953723697/G6JaHA
    [2021-05-08 17:09:51] LEScript.INFO: Verification pending, sleeping 1s
    [2021-05-08 17:09:52] LEScript.INFO: Sending signed request to https://acme-v02.api.letsencrypt.org/acme/chall-v3/12953723697/G6JaHA
    [2021-05-08 17:09:57] LEScript.ERROR: 400 {   "type": "urn:ietf:params:acme:error:malformed",   "detail": "Unable to update challenge :: authorization must be pending",   "status": 400 }
    [2021-05-08 17:09:57] LEScript.ERROR: #0 /opt/admin/vendor/analogic/lescript/Lescript.php(544): Analogic\ACME\Client->curl('POST', 'https://acme-v0...', '{"protected":"e...')
    [2021-05-08 17:09:57] LEScript.ERROR: #1 /opt/admin/vendor/analogic/lescript/Lescript.php(422): Analogic\ACME\Client->post('https://acme-v0...', '{"protected":"e...')
    [2021-05-08 17:09:57] LEScript.ERROR: #2 /opt/admin/vendor/analogic/lescript/Lescript.php(165): Analogic\ACME\Lescript->signedRequest('https://acme-v0...', Array)
    [2021-05-08 17:09:57] LEScript.ERROR: #3 /opt/admin/src/AppBundle/Handler/LeHandler.php(62): Analogic\ACME\Lescript->signDomains(Array)
    [2021-05-08 17:09:57] LEScript.ERROR: #4 /opt/admin/src/AppBundle/Controller/LeController.php(71): AppBundle\Handler\LeHandler->renew(true)
    [2021-05-08 17:09:57] LEScript.ERROR: #5 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(151): AppBundle\Controller\LeController->issueAction(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-08 17:09:57] LEScript.ERROR: #6 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
    [2021-05-08 17:09:57] LEScript.ERROR: #7 /opt/admin/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php(200): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
    [2021-05-08 17:09:57] LEScript.ERROR: #8 /opt/admin/web/app.php(16): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
    [2021-05-08 17:09:57] LEScript.ERROR: #9 {main}
    

    Anyway, I think the mapping was correct before, the challenge is in the folder where it should be. The problem was that the webserver for some reason wasn’t able to get to that folder.

  11. rcd reporter

    Actually I use neither, but https://hub.docker.com/r/jlesage/nginx-proxy-manager. I think they all use the same nginx-proxy-manager code, they just packet it differently - like jc21 use a separate mysql container for data storage. It looks more like the poste.io webserver for some reason isn’t allowed to read from that folder, probably due to configuration.

    Is there any way to get any debugging information out of the webserver in poste.io? Running “docker-compose logs -f” while trying a TLS cert renew produce nothing…

  12. Mike DiMeglio

    Jlesage's is based on jc21 but neither is the same as nginx-proxy. I just spun up jlesage here and will see if I can get anything different on my end.

  13. Mike DiMeglio

    oh I got it - your URL for the letsencrypt acme-challenge folder is being passed (correctly) by nginx-proxy-manager to the poste.io server. The thing is, that location doesn’t exist on the server, it exists on nginx-proxy-manager only. I bet if you did a curl from the command line of the server poste.io is running on using localhost:port/.well-known/acme-challenge/<token> it would work. Just tried it on mine and the response wasn’t a 404. So basically we need to figure out how to not let nginx-proxy-manager to intercept traffic to .well-known for subdomains.

  14. Mike DiMeglio

    Poste.io isn’t the problem.

    In the nginx-proxy-manager:

    # cat /etc/nginx/conf.d/include/letsencrypt-acme-challenge.conf
    
    # Hide /acme-challenge subdirectory and return 404 on all requests.
    # It is somewhat more secure than letting Nginx return 403.
    # Ending slash is important!
    location = /.well-known/acme-challenge/ {
            return 404;
    }
    

  15. Mike DiMeglio

    https://github.com/jc21/nginx-proxy-manager/issues/210

    What if instead you have nginx-proxy-manager pull the key for you from its interface, and then mapped the certificates in poste.io’s data directory ssl subfolder (ca.crt, server.crt, and server.key) to their respective files in nginx-proxy-manager data directory/letsencrypt/archive/npm-<id>/ fullchain1.pem, cert1.pem, and privkey1.pem, respectively?

  16. rcd reporter

    Actually one of the first things I tried was just brute copying the keys from nginx-proxy-manager to poste.io, but that didn’t work at all. I don’t know exactly why not, but trying to read mail then just threw an error- hence my question in the op 😉

  17. Mike DiMeglio

    Copying the keys works if you rename them correctly and have the right permissions.. Tried it here, poste.io seems happy. I would close this Issue out.

  18. rcd reporter

    Yes, I can confirm it works for me by copying or linking the certs. Symlinks does not work though, so it’s possible for a careless poste.io admin to break the proxy-manager certs. A little unsafe, but at least it works.

    ln /data/nginx-proxy-manager/config/letsencrypt/archive/npm-7/fullchain1.pem /data/poste.io/data/ssl/ca.crt
    ln /data/nginx-proxy-manager/config/letsencrypt/archive/npm-7/cert1.pem /data/poste.io/data/ssl/server.crt
    ln /data/nginx-proxy-manager/config/letsencrypt/archive/npm-7/privkey1.pem /data/poste.io/data/ssl/server.key
    

    To activate this I also had to restart the poste.io container. Isn’t there a less invasive reload possibility?

  19. Log in to comment