Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example wrapper script for multi-cert/multi-account management. #37

Open
skorokithakis opened this issue Dec 6, 2015 · 12 comments
Open

Comments

@skorokithakis
Copy link

Why is it a directive that output paths must not be specified? It's inconvenient, at the very least I would like to be able to output the files with their own names. I don't understand why we can't assume that the user knows what they're doing.

@kuba
Copy link
Owner

kuba commented Dec 6, 2015

One of the problems: currently plugin name is equivalent to the output path, so we would have to introduce -f fullchain.pem:/path/to/your/file syntax. That's... less simple: both for the user and the implementation.

There are probably a ton of other problems around such solution. On the other hand, why do you even need to specify output path? In other words, does the current design stop you from achieving a particular setup? Unless you can specify the full path to simp_le files, you can always symlink...

@skorokithakis
Copy link
Author

The problem is that, usually, all my certs are in /etc/ssl/certs, which already has proper permissions. simp_le outputs the same file every time, which means files will get overwritten. It's not a huge hassle, it would just be easier if it was a bit more flexible.

@Lekensteyn
Copy link
Contributor

@kuba The filename == contents type concept is simple, but not very user friendly. It is currently also not possible to store keys and certificates in separate directories, except by creating symlinks.

The -f fullchain.pem:/etc/ssl/certs/example.com.crt -f key.pem:/etc/ssl/private/example.com.key approach seems a good compromise between complexity and flexibility (both for the code and the user).

@skorokithakis the issue of overwriting unchanged files (data that is not "dirty") is a different issue and I agree that it is not nice (different timestamp). Can you open a new issue for that?

@skorokithakis
Copy link
Author

@Lekensteyn My issue is not really on overwriting files, just that I can't store multiple certs in the same dir because they will use the same filename, so I can't differentiate. I can open an issue for overwriting, but I haven't seen that happen.

@ptman
Copy link

ptman commented Dec 10, 2015

This would make my life easier as well.

@cheeplusplus
Copy link

The only reason I don't like the symlink or absolute path reference is that you have to put the key in the same directory as the cert. Not being able to specify filenames isn't great but it's a more minor issue by how inconvenient simp_le is to use with multiple certificates at once.

@Rotonen
Copy link

Rotonen commented Dec 20, 2015

Cert location management is better left unhandled by a single purpose software and left at the devises of the sysadmin-fu of the deployment target. What this project could do is to document a sane baseline practice to adhere to.

Below is a rough outline of what I'm doing in a cronjob sans error handling and system specific aspects (for readability).

#!/bin/bash

cd /root/ssltemp

/root/simp_le/venv/bin/simp_le \
--email [email protected] \
--default_root /var/www/letsencrypt \
-f account_key.json \
-f fullchain.pem \
-f cert.pem \
-f chain.pem \
-f key.pem \
-d example.com \
-d www.example.com

mv key.pem privkey.pem
mv *pem /etc/letsencrypt/live/example.com/

simp_le \
--default_root /var/www/letsencrypt \
--email [email protected] \
-f account_key.json \
-f cert.pem \
-f chain.pem \
-f fullchain.pem \
-f key.pem \
-d example.org \
-d www.example.org \
-d mail.example.org

mv key.pem privkey.pem
mv *pem /etc/letsencrypt/live/example.org/

systemctl reload nginx postfix

systemctl restart dovecot

# EOF

For authentication with Nginx, I have the following:

/etc/nginx/sites-enabled/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    include letsencrypt-webroot.conf;
    location / {
        return 444;
    }
}

/etc/nginx/letsencrypt-webroot.conf

# The regex match is here to allow it to work from within otherwise denied locations.
# This is a corner of Nginx I do not fully understand.
location ^~ /.well-known {
    allow all;
    alias /var/www/letsencrypt/.well-known;
}

/etc/nginx/sites-enabled/example.com

# In the future:
# listen 80 h2c;
server {
    listen 80;
    listen [::]:80;

    server_name example.com;

    access_log /var/log/nginx/example.com-access.log;
    error_log /var/log/nginx/example.com-error.log;

    return 301 https://$server_name$request_uri;
}

# In the future:
# listen 443 h2;
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name example.com;

    access_log /var/log/nginx/example.com-access.log;
    error_log /var/log/nginx/example.com-error.log;

    include ssl-example.com.conf;

    root /var/www/example.com;
    index index.html index.htm;

    charset utf-8;

    include letsencrypt-webroot.conf;

    location / {
        try_files $uri $uri/ /index.html;
    }

    location ~ ^/~(.+?)(/.*)?$ {
        alias /home/$1/public_html$2;
        index  index.html index.htm;
        autoindex on;
    }
}

/etc/nginx/ssl-example.com.conf

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
ssl_dhparam /etc/letsencrypt/live/example.com/dhparam.pem;

include ssl-common.conf;

Do note that HSTS can equate to painting yourself into a corner - you will have to serve over HTTPS.

/etc/nginx/ssl-common.conf

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

ssl_protocols TLSv1.1 TLSv1.2;
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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
ssl_prefer_server_ciphers on;

add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

@kuba
Copy link
Owner

kuba commented Dec 20, 2015

While this is completely off-topic for this PR, @Rotonen, unfortunately, there are a couple of problems with your setup:

  1. You should not move/rename output files of the script, i.e. the following is wrong:

    mv key.pem privkey.pem
    mv *pem /etc/letsencrypt/live/example.com/

    This way every time you run the cron, certs will be renewed. If you really need the key to be called privkey.pem then ln -s key.pem privkey.pem. If you really cannot specify full path to simp_le $CWD in your server configs, then ln -s $CWD/key.pem /etc/letsencrypt/live/example.com/key.pem etc. Every time simp_le is run it rereads the certs and renews it only if necessary (month before expiry), so it's safe to put it into daily crontab.

  2. Use the exit codes to restart services only if necessary. The following is wrong:

    systemctl reload nginx postfix
    systemctl restart dovecot

    as it will always reload/restart your servers even if certs were not renewed. What's better is something along these lines: simp_le ... && systemctl reload nginx postfix

Nevertheless, you do have a point. I should work on canonical examples and put them down in https://github.com/kuba/simp_le/wiki/Examples.

@Rotonen
Copy link

Rotonen commented Dec 21, 2015

Yes, as stated, the script excerpt is sans error handling and system specific aspects. It should not end up in anyone's production setup verbatim, it is provided purely for reference use only. A generalized solution would on top of exit code handling also have to discover which services use the cert (take that as a parametre, for instance) and which init system is used by the system in question.

The key renaming is in there to conform to the naming scheme the Letsencrypt client has out of the box (to ease with transition from that tool to this tool). I admit this is not obvious from the example.

I'm always renewing the certs as the script is in cron to be run every second month of the year (as suggested by Letsencrypt). This is not transparently obvious either, yes, but I explicitly want to renew the certs every time this script gets run and it is the admin's responsibility to behave and adhere to the renews over time limits of the CA.

As for the relevancy for the pull request - if one is to take my view on how to handle this, providing such skeletal sketching for documentation is at the core of the issue. This might not be the correct forum for that due to the verbosity imposed on this thread, though.

@ThiefMaster
Copy link

I'd also like some more flexibility, such as being able to specify a path that's already mapped as .well-known/acme-challenge (i.e. the files would do there directly instead of creating those subdirectories).

The reason for this is that I'm mostly running Python applications which don't have a true "web root". While e.g. /static is mapped to a physical directory, everything else goes straight to the Python webapp. In this case the easiest solution would be mapping .well-known/acme-challenge/ to e.g. /var/lib/letsencrypt/<domain>/ - no need to have two extra levels of subdirectories in there!

@kuba
Copy link
Owner

kuba commented Dec 26, 2015

@ThiefMaster that's a bit different problem, and should be opened as a new issue: #53

@kuba
Copy link
Owner

kuba commented Apr 17, 2016

I want to keep this software as simple as possible. Flexibility of specifying your own paths is achievable by creating a wrapper script. I would be potentially interested in adding such a wrapper to examples, but I'm not happy to make it part of the core script. Also, I'm afraid that I will not be able to work this out myself in foreseeable future, so if anyone is interested, feel free to grab it! :)

@kuba kuba changed the title Allow specifying output paths. Add example wrapper script for multi-cert/multi-account management. Apr 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants