Problem with seafile, docker, letsencrypt "Connection refused" and cloudflare

Hi Everyone,

I installed an instance of Seafile on Docker today and was unable to get letsencrypt working. Port 80 and 443 were open to the public internet, my compose file was correct and I was able to verify seafile being fully functional on port 80.

When I tried to enable letsencrypt I was met with this in the logs:

Verifying ...
Traceback (most recent call last):
  File "/shared/ssl/letsencrypt/acme_tiny.py", line 141, in get_crt
    assert (disable_check or _do_request(wellknown_url)[0] == keyauthorization)
  File "/shared/ssl/letsencrypt/acme_tiny.py", line 46, in _do_request
    raise ValueError("{0}:\nUrl: {1}\nData: {2}\nResponse Code: {3}\nResponse: {4}".format(err_msg, url, data, code, resp_data))
ValueError: Error:
Url: ://seafile.example.com/.well-known/acme-challenge/foo
Data: None
Response Code: None
Response: <urlopen error [Errno 111] Connection refused>

This confused the hell out of me! I finally started watching the NAT translations on my router to see what was occuring. I noticed when starting the container an IP of 172.65.32.248 coming up. I checked the IP to find it was cloudflare managed and therefore appeared that the letsencrypt validation was coming from within cloudflare - no problem there.

I then realised I have DNS hosting WITH cloudflare also! I had it setup with DNS only not Proxied. I changed it to proxied, waited for propogation and then Seafile was able to get an SSL cert fine.

I’m guessing something in cloudflare messes up if you happen to have DNS only configured for a host record and happen to receive a connection for validation of letsencrypt from them. Changing to proxied so your behind Cloudflares WAF seems to resolve it.

HTH someone else so they dont spend hours trying to figure it out - or worse, see it as a bug in seafile.

Thanks

Actually I’m wrong. Seafile isn’t listening on 443 for some reason. The reason proxying via cloudflared worked is because they handle SSL > Port 80 for you. It doesn’t work on the LAN. I’ll blow it all away and try again.

this is what was in seafile.nginx.conf. I’m not very familiar with nginx but looks like it needs a section for port 443? Does this mean seafile doesn’t update the conf correctly if an error is returned or if you want to enable SSL later?

# -*- mode: nginx -*-
# Auto generated at 12/11/2020 16:49:43
server {
listen 80;
server_name seafile.example.com;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_read_timeout 310s;
        proxy_set_header Host $host;
        proxy_set_header Forwarded "for=$remote_addr;proto=$scheme";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection "";
        proxy_http_version 1.1;

        client_max_body_size 0;
        access_log      /var/log/nginx/seahub.access.log seafileformat;
        error_log       /var/log/nginx/seahub.error.log;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 0;
        proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_request_buffering off;
        access_log      /var/log/nginx/seafhttp.access.log seafileformat;
        error_log       /var/log/nginx/seafhttp.error.log;
    }

    location /seafdav {
        proxy_pass         http://127.0.0.1:8080;
        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_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout  1200s;
        client_max_body_size 0;

        access_log      /var/log/nginx/seafdav.access.log seafileformat;
        error_log       /var/log/nginx/seafdav.error.log;
    }

    location /media {
        root /opt/seafile/seafile-server-latest/seahub;
    }

    # For letsencrypt
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }
}

Ok so I blew it all away and started again. This time around its worked fine and the nginx conf looks like this:

# -*- mode: nginx -*-
# Auto generated at 12/11/2020 18:15:43
server {
    listen 80;
    server_name _ default_server;

    # allow certbot to connect to challenge location via HTTP Port 80
    # otherwise renewal request will fail
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }

    location / {
        rewrite ^ https://seafile.example.com$request_uri? permanent;
    }
}
server {
listen 443;
    ssl on;
    ssl_certificate      /shared/ssl/seafile.example.com.crt;
    ssl_certificate_key  /shared/ssl/seafile.example.com.key;

    ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

    # TODO: More SSL security hardening: ssl_session_tickets & ssl_dhparam
    # ssl_session_tickets on;
    # ssl_session_ticket_key /etc/nginx/sessionticket.key;
    # ssl_session_cache shared:SSL:10m;
    # ssl_session_timeout 10m;
server_name seafile.example.com;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_read_timeout 310s;
        proxy_set_header Host $host;
        proxy_set_header Forwarded "for=$remote_addr;proto=$scheme";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection "";
        proxy_http_version 1.1;

        client_max_body_size 0;
        access_log      /var/log/nginx/seahub.access.log seafileformat;
        error_log       /var/log/nginx/seahub.error.log;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 0;
        proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_request_buffering off;
        access_log      /var/log/nginx/seafhttp.access.log seafileformat;
        error_log       /var/log/nginx/seafhttp.error.log;
    }

    location /seafdav {
        proxy_pass         http://127.0.0.1:8080;
        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_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout  1200s;
        client_max_body_size 0;

        access_log      /var/log/nginx/seafdav.access.log seafileformat;
        error_log       /var/log/nginx/seafdav.error.log;
    }

    location /media {
        root /opt/seafile/seafile-server-latest/seahub;
    }

    # For letsencrypt
    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }
}
1 Like

This is a BAD idea. Your data is being sent unencrypted from your server to Cloudflare. Even if it would be encrypted Cloudflare is man in the middle and can see all your traffic in cleartext.

In that case just use Dropbox or something like that.

More information on Seafile can be found in the manual. The following page shows the setup which is preferred. https://manual.seafile.com/overview/components/

This wasn’t the point of the post. But thanks