Issue renewing certificate with seafile

My domain is:
seafile.swamp.xyz

I ran this command:
/usr/local/bin/cert-renew seafile.swamp.xyz >> /var/log/your_domain.tld-renew.log 2>&1

It produced this output:
Checking expiration date for seafile.swamp.xyz…
The certificate for seafile.swamp.xyz is about to expire soon. Starting renewal request…
”/opt/seafile/seafile-server-latest/seahub” does not exist or is not a directory
Reloading Nginx…
Renewal process finished for domain seafile.swamp.xyz
Checking expiration date for seafile.swamp.xyz…
The certificate for seafile.swamp.xyz is about to expire soon. Starting renewal request…
”/usr/share/nginx/html” does not exist or is not a directory
Reloading Nginx…
Renewal process finished for domain seafile.swamp.xyz

My web server is (include version):
nginx version: nginx/1.16.1

The operating system my web server runs on is (include version):
CentOS Linux release 7.7.1908 (Core)

I can login to a root shell on my machine (yes or no, or I don’t know):
Yes

I’m using a control panel to manage my site (no, or provide the name and version of the control panel):
No

The version of my client is (e.g. output of certbot --version or certbot-auto --version if you’re using Certbot):
I am using /usr/local/bin/cert-renew

So I think the issue resides in the way seafile is redirecting all pages, I am not sure what’s required of cert-renew to renew, but that directory exists:

[root@seafile nginx]# ls -ltrh /usr/share/nginx/html
total 12K
-rw-r–r-- 1 root root 368 Oct 3 01:12 nginx-logo.png
-rw-r–r-- 1 root root 3.7K Oct 3 01:12 50x.html
-rw-r–r-- 1 root root 3.6K Oct 3 01:12 404.html
lrwxrwxrwx 1 root root 20 Dec 28 10:59 en-US -> …/…/doc/HTML/en-US
drwxr-xr-x 2 root root 27 Dec 28 10:59 icons
lrwxrwxrwx 1 root root 25 Dec 28 10:59 index.html -> …/…/doc/HTML/index.html
lrwxrwxrwx 1 root root 18 Dec 28 10:59 img -> …/…/doc/HTML/img
lrwxrwxrwx 1 root root 14 Dec 28 10:59 poweredby.png -> nginx-logo.png
[root@seafile nginx]#

For what it is worth, I followed this guide to generate most of this:
https://www.tecmint.com/setup-https-with-lets-encrypt-ssl-certificate-for-nginx-on-centos/comment-page-1/#comments

1 Like

I’m not certain (yet) why you are having to use this cert-renew script:

Have you tried any of the other “regular” certbot commands?
What says?:
/etc/letsencrypt/letsencrypt-auto --version

[I would also try: https://certbot.eff.org/lets-encrypt/centosrhel7-nginx]

1 Like

I was just following the guide, haha. But that doesn’t seem to exist:

[root@seafile ~]# /etc/letsencrypt/letsencrypt-auto --version
-bash: /etc/letsencrypt/letsencrypt-auto: No such file or directory
[root@seafile ~]# whereis letsencrypt
letsencrypt: /etc/letsencrypt
[root@seafile ~]# cd /etc/letsencrypt/
[root@seafile letsencrypt]# ll
total 0
drwx------ 3 root root 42 Dec 29 19:43 accounts
drwx------ 3 root root 31 Dec 29 21:48 archive
drwxr-xr-x 2 root root 230 Jan 2 11:10 csr
drwx------ 2 root root 230 Jan 2 11:10 keys
drwx------ 3 root root 45 Dec 29 21:48 live
drwxr-xr-x 2 root root 36 Jan 2 11:10 renewal
drwxr-xr-x 5 root root 43 Dec 29 19:43 renewal-hooks
[root@seafile letsencrypt]#

1 Like

hmm…
Can you show the script?:
/usr/local/bin/cert-renew

1 Like
#!/bin/bash

webpath='/usr/share/nginx/html'
#webpath='/opt/seafile/seafile-server-latest/seahub'
domain=$1
le_path='/opt/letsencrypt'
le_conf='/etc/letsencrypt'
exp_limit=30;

get_domain_list(){
        certdomain=$1
        config_file="$le_conf/renewal/$certdomain.conf"

        if [ ! -f $config_file ] ; then
                echo "[ERROR] The config file for the certificate $certdomain was not found."
                exit 1;
        fi

        domains=$(grep --only-matching --perl-regex "(?<=domains \= ).*" "${config_file}")
        last_char=$(echo "${domains}" | awk '{print substr($0,length,1)}')

        if [ "${last_char}" = "," ]; then
                domains=$(echo "${domains}" |awk '{print substr($0, 1, length-1)}')
        fi

        echo $domains;
}

if [ -z "$domain" ] ; then
        echo "[ERROR] you must provide the domain name for the certificate renewal."
        exit 1;
fi

cert_file="/etc/letsencrypt/live/$domain/fullchain.pem"

if [ ! -f $cert_file ]; then
        echo "[ERROR] certificate file not found for domain $domain."
        exit 1;
fi

exp=$(date -d "`openssl x509 -in $cert_file -text -noout|grep "Not After"|cut -c 25-`" +%s)
datenow=$(date -d "now" +%s)
days_exp=$(echo \( $exp - $datenow \) / 86400 |bc)

echo "Checking expiration date for $domain..."

if [ "$days_exp" -gt "$exp_limit" ] ; then
        echo "The certificate is up to date, no need for renewal ($days_exp days left)."
        exit 0;
else
        echo "The certificate for $domain is about to expire soon. Starting renewal request..."
        domain_list=$( get_domain_list $domain )
"$le_path"/letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --webroot-path=”$webpath” --domains "${domain_list}"
        echo "Reloading Nginx..."
sudo systemctl reload nginx
        echo "Renewal process finished for domain $domain"
        exit 0;
fi
1 Like

Try:
/opt/letsencrypt/letsencrypt-auto --version

1 Like

[root@seafile ~]# /opt/letsencrypt/letsencrypt-auto --version

certbot 1.3.0
[root@seafile ~]#

2 Likes

Now we are getting somewhere…

How about:
/opt/letsencrypt/letsencrypt-auto certificates
and
/opt/letsencrypt/letsencrypt-auto renew

1 Like

As an aside, and BTW/FYI:
Rather than having to check manually for replies/updates, you can setup your profile to notify you via email when a reply is posted to your topic (and also when your username is mentioned):
In your user preferences set as:
image

1 Like

Yup, I get immediate emails on responses, thank you by the way!

[root@seafile ~]# /opt/letsencrypt/letsencrypt-auto certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: seafile.swamp.xyz
    Domains: seafile.swamp.xyz
    Expiry Date: 2020-04-01 15:10:12+00:00 (VALID: 18 days)
    Certificate Path: /etc/letsencrypt/live/seafile.swamp.xyz/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/seafile.swamp.xyz/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@seafile ~]# /opt/letsencrypt/letsencrypt-auto renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/seafile.swamp.xyz.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert is due for renewal, auto-renewing...
Plugins selected: Authenticator webroot, Installer None
Renewing an existing certificate
Performing the following challenges:
http-01 challenge for seafile.swamp.xyz
Using the webroot path /usr/share/nginx/html for all unmatched domains.
Waiting for verification...
Challenge failed for domain seafile.swamp.xyz
http-01 challenge for seafile.swamp.xyz
Cleaning up challenges
Attempting to renew cert (seafile.swamp.xyz) from /etc/letsencrypt/renewal/seafile.swamp.xyz.conf produced an unexpected error: Some challenges have failed.. Skipping.
All renewal attempts failed. The following certs could not be renewed:
  /etc/letsencrypt/live/seafile.swamp.xyz/fullchain.pem (failure)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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

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

   Domain: seafile.swamp.xyz
   Type:   unauthorized
   Detail: Invalid response from
   https://seafile.swamp.xyz/.well-known/acme-challenge/4Nh6FOKpFh5xvuJ0T1qmsXWqWMBOf0vrx-Ny-rhJo9I
   [192.119.175.12]: "\n\n<!DOCTYPE html>\n<html
   lang=\"en\">\n<head>\n<title>Private Seafile</title>\n<meta
   http-equiv=\"Content-type\" content=\"text/html; cha"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.
[root@seafile ~]#
1 Like

ok, I created the directory it was looking for, and now I get this:

[root@seafile html]# /opt/letsencrypt/letsencrypt-auto certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
  Certificate Name: seafile.swamp.xyz
    Domains: seafile.swamp.xyz
    Expiry Date: 2020-04-01 15:10:12+00:00 (VALID: 18 days)
    Certificate Path: /etc/letsencrypt/live/seafile.swamp.xyz/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/seafile.swamp.xyz/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[root@seafile html]#
1 Like

We need to have a look at this file:

and your nginx config.
To ensure the webroot matches the document root used for challenge requests.

1 Like

This is my nginx.conf file:

For more information on configuration, see:

* Official English Documentation: http://nginx.org/en/docs/

* Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.

include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main '$remote_addr - $remote_user [$time_local] “$request” ’
'$status $body_bytes_sent “$http_referer” ’
‘"$http_user_agent" “$http_x_forwarded_for”’;

access_log /var/log/nginx/access.log main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;

Load modular configuration files from the /etc/nginx/conf.d directory.

See http://nginx.org/en/docs/ngx_core_module.html#include

for more information.

include /etc/nginx/conf.d/*.conf;

server {
listen 80 default_server;
listen [::]:80 default_server;

server_name _;
root /usr/share/nginx/html;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
}

error_page 404 /404.html;
    location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
    location = /50x.html {
}

}

1 Like

Your nginx config "INCLUDES" other files:

And we still need to have a look at this file:

2 Likes

There’s only one file in the conf.d and default.d:

server {
listen 80;
server_name seafile.swamp.xyz;
rewrite ^ https://$http_host$request_uri? permanent;
server_tokens off;
}
server {
listen 443 ssl http2;
server_name seafile.swamp.xyz;

#ssl on;
ssl_certificate /etc/letsencrypt/live/seafile.swamp.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seafile.swamp.xyz/privkey.pem;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:5m;

ssl_dhparam /etc/nginx/ssl/dhparam.pem;

#SSL Security
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_protocols TLSv1.2;

ssl_ciphers ‘ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256’;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
server_tokens off;
ssl_session_tickets off;

proxy_set_header X-Forwarded-For $remote_addr;

location / {
    proxy_pass         http://127.0.0.1:8000;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Host $server_name;
    proxy_read_timeout  1200s;

    # used for view/edit office file via Office Online Server
    client_max_body_size 0;

    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_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_connect_timeout  36000s;
    proxy_read_timeout  36000s;
    proxy_send_timeout  36000s;
    send_timeout  36000s;
}
location /media {
    root /opt/seafile/seafile-server-latest/seahub;
}

}

seafile.swamp.xyz.conf:

# renew_before_expiry = 30 days
version = 1.0.0
archive_dir = /etc/letsencrypt/archive/seafile.swamp.xyz
cert = /etc/letsencrypt/live/seafile.swamp.xyz/cert.pem
privkey = /etc/letsencrypt/live/seafile.swamp.xyz/privkey.pem
chain = /etc/letsencrypt/live/seafile.swamp.xyz/chain.pem
fullchain = /etc/letsencrypt/live/seafile.swamp.xyz/fullchain.pem

# Options used in the renewal process
[renewalparams]
authenticator = webroot
account = 94dbxxxxxxxxxxxxxxxxxxxxxxxxxxxx
server = https://acme-v02.api.letsencrypt.org/directory
webroot_path = /usr/share/nginx/html,
[[webroot_map]]
1 Like

From that and

I would try handling the authentication requests explicitly with something like:

location /.well-known/acme-challenge/ {
    root /usr/share/nginx/html;
}

[forcing the nginx root to match the webroot path]

But that may not be ideally secure... although it shuold get your renewals to work.

A more secure approach would be to use a dedicated folder for the authentication requests.
Something more like:

[modify the renewal file and create the desired folder]
webroot_path = /ACME-challenges;

[and use that newly created folder in the location section]

location /.well-known/acme-challenge/ {
    root /ACME-challenges;
}
2 Likes

Maybe I am not tracking, but change what to what? In /etc/letsencrypt/renewal/seafile.swamp.xyz.conf change the webroot_path line to be what now?

How does making ./well-known/acme-challenge the location resolve the issue for auth?

1 Like

Leave it as is and add the first location above
OR
Change it to something dedicated like: /ACME-challenges
and add the matching location.

LE is having trouble authenticating; which seems to be related to the inability of reaching the challenge files that are being placed (who knows where).
This approach guarantees the location of those challenge files is known and well defined.

2 Likes

I am not following, I should add what lines to which files? Should I also create the directory:

/usr/share/nginx/html/well-known/acme-challenge

Add:

to the file:

[I don't know the name of the file; but you showed the contents]

Only if you want to put a test text file in there; to see if it can be directly accessed via the Internet.
Otherwise, the folders should get created, and deleted, as needed.

2 Likes