haiwen / seafile-docker

A Docker image for Seafile server
Other
536 stars 181 forks source link

Nginx looks for certification at wrong path #321

Closed undergroundwires closed 1 year ago

undergroundwires commented 1 year ago

Summary

Certification location at nginx configuration does not match certification location received.

This could be fixed by pointing to right location in nginx file.

Existing file location Wrong Nginx configured location
/shared/ssl/example.com/fullchain.cer /shared/ssl/example.com.crt
/shared/ssl/example.com/example.com.key /shared/ssl/example.com.key

Detailed explanation of problem

On fresh installation, certification is created at /shared/ssl/domain.com/ folder. See logs:

seafile  | [Thu 22 Dec 2022 08:40:00 PM CET] Your cert is in: /shared/ssl//example.com/example.com.cer
seafile  | [Thu 22 Dec 2022 08:40:00 PM CET] Your cert key is in: /shared/ssl//example.com/example.com.key
seafile  | [Thu 22 Dec 2022 08:40:00 PM CET] The intermediate CA cert is in: /shared/ssl//example.com/ca.cer
seafile  | [Thu 22 Dec 2022 08:40:00 PM CET] And the full chain certs is there: /shared/ssl//example.com/fullchain.cer
``

However, Seafile adds following entry to nginx:

```nginx
listen 443 ssl;
    ssl_certificate      /shared/ssl/example.com.crt;
    ssl_certificate_key  /shared/ssl/example.key;    

It then starts failing when it loads nginx, the web UI becomes inaccessible. The logs look as following:

seafile  | nginx: [emerg] cannot load certificate "/shared/ssl/example.com.crt": BIO_new_file() failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/shared/ssl/example.com.crt','r') error:2006D080:BIO routines:BIO_new_file:no such file)

My temporary workaround

I share this for others that are looking for a solution before a patch is released.

  1. Get inside the container: sudo docker exec -it seafile /bin/bash
  2. Symlink real certification files to the path requested from nginx configuration (change example.com to your FQDN hostname):
cd /shared/ssl/
ln -s  example.com/fullchain.cer ./example.com.crt
ln -s  example.com/example.com.key ./example.com.key
# Using cd and relative paths so it works outside of Docker
  1. Reload nginx:
nginx -s reload
kirisakow commented 1 year ago

Normally there is no need for a hacky solution:

  1. Log in to the seafile Docker container like you did:
    docker exec -it seafile /bin/bash

    (To log out from the seafile Docker container, use the regular keyboard shortcut Ctrl D)

(To avoid having to run Docker as root, run sudo usermod -aG docker $USER)

  1. Inside the container, do the following:

    • 2.1. Get the latest acme.sh script:
      
      # check version
      /scripts/acme.sh/acme.sh --version

/scripts/acme.sh/acme.sh --upgrade

ln -s /root/.acme.sh/acme.sh /scripts/acme.sh/acme.sh

check version again

/scripts/acme.sh/acme.sh --version

 * 2.2. Replace the `/scripts/ssl.sh` script's content with that of [my fixed version](https://github.com/haiwen/seafile-docker/pull/314):
```sh
curl https://raw.githubusercontent.com/kirisakow/seafile-docker/patch-1/scripts_9.0/ssl.sh | tee /scripts/ssl.sh
kirisakow commented 1 year ago

Also, you may need to use this oneliner to monitor all Seafile logs (run from outside the container):

sudo tail -f $(find /opt/seafile-data/ -type f -name *.log 2>/dev/null)
johanbosman commented 1 year ago

Normally there is no need for a hacky solution:

  1. Log in to the seafile Docker container like you did:
docker exec -it seafile /bin/bash

(To log out from the seafile Docker container, use the regular keyboard shortcut Ctrl D)

(To avoid having to run Docker as root, run sudo usermod -aG docker $USER)

  1. Inside the container, do the following:
  • 2.1. Get the latest acme.sh script:
# check version
/scripts/acme.sh/acme.sh --version

/scripts/acme.sh/acme.sh --upgrade

ln -s /root/.acme.sh/acme.sh /scripts/acme.sh/acme.sh

# check version again
/scripts/acme.sh/acme.sh --version
  • 2.2. Replace the /scripts/ssl.sh script's content with that of my fixed version:
curl https://raw.githubusercontent.com/kirisakow/seafile-docker/patch-1/scripts_9.0/ssl.sh | tee /scripts/ssl.sh
  • 2.3. Run /scripts/ssl.sh to generate and install TLS aka SSL certificate:
/scripts/ssl.sh "/shared/ssl/" "your.seafile.domain.com"
  1. Log out of the container BASH session
  2. Test Nginx config and, if no error is found, restart Nginx:
sudo nginx -t && sudo systemctl restart nginx.service

Thank you Kirisakow, What I did is use your ssl.sh Commit the new seafile docker container.

I ran the docker-compose up -d then noticed atlast I have a cert in shared/ssl directory.

I then added the following to my seafile.nginx.conf file ( Just place your real domain in my.domain.tld )

location / {
         rewrite ^ https://my.domain.tld$request_uri? permanent;
     }
}
server {
  listen 443 ssl;
     ssl_certificate      /shared/ssl/my.domain.tld.crt;
     ssl_certificate_key  /shared/ssl/my.domain.tld.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;

Saved everything down and up the docker-compose and I had SSL installed and working. What a 3 week mission this was.

kirisakow commented 1 year ago

Here is mine:

server {
    listen 80;
    listen [::]:80 http2 ipv6only=on;
    server_name seafile.mydomain.com;

    client_max_body_size 0;

    location / {
        proxy_pass http://localhost:81;
    }

}
server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;
    server_name seafile.mydomain.com;

    client_max_body_size 0;

    location / {
        proxy_pass https://localhost:442;
    }

    ssl_certificate /opt/seafile-data/ssl/seafile.mydomain.com.crt;
    ssl_certificate_key /opt/seafile-data/ssl/seafile.mydomain.com.key;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
kirisakow commented 5 months ago
  • 2.3. Run /scripts/ssl.sh to generate and install TLS aka SSL certificate:
/scripts/ssl.sh "/shared/ssl/" "seafile.your-domain.com"

In case the aforementioned technique fails, you can instead generate a certificate outside of the Seafile container, by the host (ie without the Seafile built-in mechanics):

  1. Generate a LetsEncrypt certificate with certbot:
    sudo certbot \
     --nginx \
     --agree-tos \
     --email "your.email@gmail.com" \
     -d seafile.your-domain.com
  2. Symlink the freshly generated cetificate and its private key to the Seafile volume directory (eg /opt/seafile-data/ssl/) so that the certificate is accessible to the Seafile container:
    # symlink the certificate:
    sudo ln -sf /etc/letsencrypt/archive/seafile.your-domain.com/fullchain1.pem /opt/seafile-data/ssl/seafile.your-domain.com.crt
    # symlink the private key:
    sudo ln -sf /etc/letsencrypt/archive/seafile.your-domain.com/privkey1.pem /opt/seafile-data/ssl/seafile.your-domain.com.key

Then proceed with the regular aforementioned steps:

  1. Log out of the container BASH session
  2. Test Nginx config and, if no error is found, restart Nginx:
    sudo nginx -t && sudo systemctl restart nginx.service

Finally,

  1. Make sure docker-compose.yml features SEAFILE_SERVER_LETSENCRYPT=false before you fire up Docker Compose.
  2. Profit.

Hope this helps!