Letsencrypt certbot renew failing

I have set up letsencrypt on my website running Seafile 4.4.3 on Nginx.
Now I need to renew my certificate, and I get the following error message:

------------------------------------------------------------------------------
Cert is due for renewal, auto-renewing...
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for seafile.domain.com
Waiting for verification...
Cleaning up challenges
Attempting to renew cert from /etc/letsencrypt/renewal/seafile.domain.com.conf produced an unexpected error: Failed authorization procedure. seafile.domain.com (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://seafile.domain.com/.well-known/acme-challenge/EViRGg9kxSEVUgFAXbGBllEbqaOFq0bbSmvxp5BIN7s: "<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>". Skipping.

All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/seafile.domain.com/fullchain.pem (failure)
1 renew failure(s), 0 parse failure(s)

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: seafile.domain.com
   Type:   unauthorized
   Detail: Invalid response from
   http://seafile.domain.com/.well-known/acme-challenge/EViRGg9kxSEVUgFAXbGBllEbqaOFq0bbSmvxp5BIN7s:
   "<html>
   <head><title>404 Not Found</title></head>
   <body bgcolor="white">
   <center><h1>404 Not Found</h1></center>
   <hr><center>"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A record(s) for that domain
   contain(s) the right IP address.

I followed this tutorial on how to set up letsencrypt, and so far this has worked fine. But now the renewal does not work.

Here’s my Nginx config:

server {
    listen       80;
    server_name  seafile.domain.com
    rewrite ^ https://$http_host$request_uri? permanent;    # force redirect http to https
}
server {
    listen 443;
    root /usr/share/nginx/html;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/seafile.domain.com/fullchain.pem;        # path to your cacert.pem
    ssl_certificate_key /etc/letsencrypt/live/seafile.domain.com/privkey.pem;    # path to your privkey.pem
    server_name seafile.domain.com
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    proxy_set_header X-Forwarded-For $remote_addr;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    server_tokens off;

    location / {
        fastcgi_pass    127.0.0.1:8000;
        fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
        fastcgi_param   PATH_INFO           $fastcgi_script_name;

        fastcgi_param   SERVER_PROTOCOL        $server_protocol;
        fastcgi_param   QUERY_STRING        $query_string;
        fastcgi_param   REQUEST_METHOD      $request_method;
        fastcgi_param   CONTENT_TYPE        $content_type;
        fastcgi_param   CONTENT_LENGTH      $content_length;
        fastcgi_param   SERVER_ADDR         $server_addr;
        fastcgi_param   SERVER_PORT         $server_port;
        fastcgi_param   SERVER_NAME         $server_name;
        fastcgi_param   HTTPS               on;
        fastcgi_param   HTTP_SCHEME         https;

        access_log      /var/log/nginx/seahub.access.log;
        error_log       /var/log/nginx/seahub.error.log;
    }
    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        client_max_body_size 0;            
	proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_send_timeout  36000s;
    }
    location ~ /.well-known {
            allow all;
    }
 }

What might be going on here?

Your server can’t be accessed via http because you have a rewrite to https.

You have to remove the first entry in your nginx config when updating letsencrypt.

I have an extra config file for all https rewrites to be easily enabled and disabled

So how would I need to change the config?
If I just delete the first server block, nginx does not even listen on port 80, correct?

You need a server block for port 80 like this. All other server blocks for port 80 have to comment out then

server{
    listen [::]:80 default_server ipv6only=off;
    server_name subdomain1*. subdomain2.*;

    location ^~ /.well-known/acme-challenge {
        default_type text/plain;
        root /var/www/letsencrypt;
    }

    location = /.well-known/acme-challenge/ {
        return 404;
    }
}

Awesome, thank you for posting this, will try!
Hopefully last question: my nginx root is /usr/share/nginx/html, I guess I need to change this from your script?

Yes and you have to edit your subdomains

Hm, so I did what you suggested, but I stell get the same error.
Step by step what I did:

  1. Change /etc/nginx/sites-available/seafile.domain.com.conf like so:

    #server {

    listen 80;

    server_name seafile.domain.com;

    rewrite ^ https://$http_host$request_uri? permanent; # force redirect http to https

    #}
    server{
    listen [::]:80 default_server ipv6only=off;
    server_name seafile.domain.com;

     location ^~ /.well-known/acme-challenge {
         default_type text/plain;
         root /usr/share/nginx/html;
     }
    
     location = /.well-known/acme-challenge/ {
         return 404;
     }
    

    }
    server {
    listen 443;
    root /usr/share/nginx/html;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/seafile.domain.com/fullchain.pem; # path to your cacert.pem
    ssl_certificate_key /etc/letsencrypt/live/seafile.domain.com/privkey.pem; # path to your privkey.pem
    server_name seafile.domain.com;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    proxy_set_header X-Forwarded-For $remote_addr;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ‘ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA’;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

     add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
     server_tokens off;
    
     location / {
         fastcgi_pass    127.0.0.1:8000;
         fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
         fastcgi_param   PATH_INFO           $fastcgi_script_name;
    
         fastcgi_param   SERVER_PROTOCOL        $server_protocol;
         fastcgi_param   QUERY_STRING        $query_string;
         fastcgi_param   REQUEST_METHOD      $request_method;
         fastcgi_param   CONTENT_TYPE        $content_type;
         fastcgi_param   CONTENT_LENGTH      $content_length;
         fastcgi_param   SERVER_ADDR         $server_addr;
         fastcgi_param   SERVER_PORT         $server_port;
         fastcgi_param   SERVER_NAME         $server_name;
         fastcgi_param   HTTPS               on;
         fastcgi_param   HTTP_SCHEME         https;
    
         access_log      /var/log/nginx/seahub.access.log;
         error_log       /var/log/nginx/seahub.error.log;
     }
     location /seafhttp {
         rewrite ^/seafhttp(.*)$ $1 break;
         proxy_pass http://127.0.0.1:8082;
         client_max_body_size 0;            
     proxy_connect_timeout  36000s;
         proxy_read_timeout  36000s;
         proxy_send_timeout  36000s;
     }
     #location ~ /.well-known {
     #        allow all;
     #}
    

    }

  2. sudo service nginx reload

  3. sudo certbot renew

Anything wrong with these steps?

I don’t know what reload does. I always restart.

Does the cryptic folder which is requested exist in /usr/share/nginx/html?

Restarted, didn’t help.
But there’s no folder in /usr/share/nginx/html, only a 50x.html and an index.hml
Do I need to create that folder myself?
This tutorial creates an entirely new folder outside of the nginx structure, but I’m not sure if this makes sense to change once you’ve already installed a certificate…

Then this is not your webroot. In the tutorial the command is called

sudo certbot certonly --webroot -w /mnt/usbdrive/certbot-webroot -d seafile.example.org

You have to enter /usr/share/nginx/html behind -w

In the default config the path is /var/www/letsencrypt as far as I know. Maybe you can check this path

So what I did is that I completely removed all certificates and reinstalled everything, using /usr/share/nginx/html as the webroot, now it works.

Thank you, Jack, for your help!