Integrate Let's Encrypt SSL certificates into ISPConfig

Discussion in 'Feature Requests' started by gkovacs, Sep 14, 2015.

  1. gkovacs

    gkovacs Member

    While there is already a year-old feature request in the ISPConfig bugtracker (, I find this issue so important that I post it here as well for further discussion. If you support this suggestion, don't forget to vote for it in the bugtracker as well!

    Let's Encrypt ( aims to become the first free, automated, and open CA (certificate authority) that will issue certificates for websites through an automated system. When it goes into service later this year, it will allow website owners and web hosts to start serving over HTTPS immediately, without the costs, unnecessary time and hassle of using the current CA systems.

    I think both the philosophy (free and open) and the automated, easy-to-use nature fits the ISPConfig project well, therefore I'd like to vote for it's inclusion in the next release!
    Last edited: Sep 15, 2015
    todx, brt and CaptainBalou like this.
  2. sjau

    sjau Local Meanie Moderator

    The first certs have now been handed out - to let's crypt itself to see whether it works.
  3. sjau

    sjau Local Meanie Moderator

  4. sjau

    sjau Local Meanie Moderator

    Btw, just testing it on a vm. Let's Encrypt allows to only download the certs using the "auth" option. However that is not fully automated but still interactive. Not sure if the renewal would then be automated.
    Keeping this in mind, it stores certs in /etc/letsencrypt/live/sub.domain.tld/[cert|chain|fullchain|privkey].pem

    Knowing this, one could use the ISPConfig API to then update those certs with ISPConfig.

    As said, the only challenge I face currently is that the (initial) cert generation is interactive.
  5. till

    till Super Moderator Staff Member ISPConfig Developer

    Hopefully they integrate a non interactive way later as well.
  6. sjau

    sjau Local Meanie Moderator

    It's possible that there is already and I just didn't figure it out yet ;)
  7. Jesse Norell

    Jesse Norell Well-Known Member Staff Member Howtoforge Staff

    There is, you can specify all parameters on the command line. Watch their video (3min):

    The biggest issue to work out from what I see (with a whole 30 minutes invested, no real experience) is that ISPConfig writes vhost files, and the easiest deployment from letsencrypt will rewrite them to configure the SSL pieces. If you don't have letsencrypt reconfig your virtual hosts, then apparently you also have to renew certificates "manually" (so I infer it would keep your site/certificates updated by itself if you let it - which would be nice, but not mandatory) - so ISPConfig would have to track expirations/renewals and such, and of course give users a "generate new private key and renew now!" option.

    Starting with websites is cool, but also should keep in mind email, as a "phase 2" maybe. Dovecot supports SNI for imap/pop. SMTP would take a lot more research, but I gather you should use DANE (publish key in dns records), which could be made to work with a single certificate for the mail server (eg. obtained via letsencrypt, but DNS record updates would need to be automated); and also domain could be assigned an IP address and have their own tls cert for both postfix and dovecot (ie. also could be implemented).
  8. sjau

    sjau Local Meanie Moderator

    Ok, I also played with it now. You can auto-generate the certs using this command:

    ./letsencrypt-auto --agree-dev-preview --agree-eula --email admin@server --domains sub.domain.tld --authenticator apache2 auth
    The certs then end up in /etc/letsencrypt/live/sub.domain.tld
    root@manager ~/letsencrypt # ls -al /etc/letsencrypt/live/sub.domain.tld/
    total 8.0K
    drwxr-xr-x 2 root root 4.0K Oct 21 11:14 .
    drwx------ 5 root root 4.0K Oct 21 20:02 ..
    lrwxrwxrwx 1 root root   44 Oct 21 11:14 cert.pem -> ../../archive/sub.domain.tld/cert1.pem
    lrwxrwxrwx 1 root root   45 Oct 21 11:14 chain.pem -> ../../archive/sub.domain.tld/chain1.pem
    lrwxrwxrwx 1 root root   49 Oct 21 11:14 fullchain.pem -> ../../archive/sub.domain.tld/fullchain1.pem
    lrwxrwxrwx 1 root root   47 Oct 21 11:14 privkey.pem -> ../../archive/sub.domain.tld/privkey1.pem

    So there's now two approaches:
    1. Make a script that runs letsencrypt and then uses the ISPC API to update the SSL info. However problem there would probably be to get right IDs for the according domain.

    2. Integrated it into ISPC directly. Basically you could add a new option in the SSL form besides "create, save, ..." named "create with Let'sEncrypt" or something. Then ISPC will trigger the command, wait until the cerst are created and then autofill the stuff.

    Regarding renewal: No idea yet :) it should work automagically somehow but not sure.
    till likes this.
  9. till

    till Super Moderator Staff Member ISPConfig Developer

    We will use approach 2 for the implementation. and the renewal is not an issue as ispconfig can simply set a symlink to the certs in the letsencrypt folders.
    Nemis and sjau like this.
  10. Jesse Norell

    Jesse Norell Well-Known Member Staff Member Howtoforge Staff

  11. sjau

    sjau Local Meanie Moderator

    Until you integrate it into ISPC I think I can look at how to use the API meanwhile.

    Once per day sounds a bit often. Maybe once per month or every 3 months or something.
  12. Jesse Norell

    Jesse Norell Well-Known Member Staff Member Howtoforge Staff

    Changing once per day was definitely not what I had in mind, but checking for domains that need renewed (because they would expire soon). I assumed the renewer tool did something like that, which may be entirely incorrect, in which case yes, a 1 month, or even 3 month renewal might be reasonable.
  13. sjau

    sjau Local Meanie Moderator

    In #letsencrypt on freenode I was told certs will be valid for 90 days and should be renewed after 60 days or so.
    till likes this.
  14. till

    till Super Moderator Staff Member ISPConfig Developer

    Ok, thats a really short time. I thought they have the usual validity lengths like a year or so. With such a short time, an automatic renewal by cron is a must have.
  15. sjau

    sjau Local Meanie Moderator

    well, I could be mistaken :)
    However, since you can automate to whole process, there's no real reason why certs should be longer lived IMHO.
  16. sjau

    sjau Local Meanie Moderator

    I did move the whole thing to a githup repo. Have a read here:

    So, I almost have a script ready to run this thing.
    There's a few things to note:
    1. I didn't do all necessary checks
    2. It only works on apache
    3. Domains/Subdomains need to have a IPv4 DNS entry. It is not sufficient to have a wildcard entry like *.domain.tld and then use that for sub.domain.tld
    4. Also, I don't run multi-server so I have no idea how it works there
    5. Right now, the SOAP/API call errors for some reason!!! Hence no data is being inserted.
    6. The API/Remote user must have access to "Site Domain Functions"
    7. I did add a shebang line, so you don't need to call the script php scrip.php but you can call it directly as "script.php sub.domain.tld"
    8. If you have not done so, download letsencrypt through git: and run the letsencrypt-auto script at least once with the "auth" parameter: ./letsencrypt-auto auth
    9. Set according path and user details in the top of the script

    #!/usr/bin/env php

    # Check the github repo:

    What works this far:
    - the script includes the ISPConfig file for the database. That is necessary to get according information whether the domain given is an actual vhost and to find out the client_id for that domain
    - once that's verified, it will make a call to the letsencrypt script. The output of the script is analyzed, if it was successfull it will attempt to read the certs and update ISPC through the API.
    Last edited: Nov 14, 2015
    biforme likes this.
  17. sjau

    sjau Local Meanie Moderator

    The error I get when I run it is this:

    root@manager ~ # ./letsencrypt.php 
    PHP Notice:  Undefined offset: 1 in /root/letsencrypt.php on line 25                                                                                                                                                                                                          
    <?xml version="1.0" encoding="UTF-8"?>                                                                                                                                                                                                                                        
    <SOAP-ENV:Envelope xmlns:SOAP-ENV=""><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>data_processing_error</faultcode><faultstring>no_server_error&lt;br /&gt;&#13;                                                                        
    hd_quota_error_empty&lt;br /&gt;&#13;
    hd_quota_error_regex&lt;br /&gt;&#13;
    traffic_quota_error_empty&lt;br /&gt;&#13; 
    traffic_quota_error_regex&lt;br /&gt;&#13; 
    documentroot_error_empty&lt;br /&gt;&#13;           
    sysuser_error_empty&lt;br /&gt;&#13;
    sysgroup_error_empty&lt;br /&gt;&#13;
    allow_override_error_empty&lt;br /&gt;&#13;
    pm_process_idle_timeout_error_regex&lt;br /&gt;&#13;
    pm_max_requests_error_regex&lt;br /&gt;&#13;
    SOAP Error: no_server_error<br />                   
    hd_quota_error_empty<br />
    hd_quota_error_regex<br /> 
    traffic_quota_error_empty<br />
    traffic_quota_error_regex<br />
    documentroot_error_empty<br />
    sysuser_error_empty<br />
    sysgroup_error_empty<br />
    allow_override_error_empty<br />
    pm_process_idle_timeout_error_regex<br />
    pm_max_requests_error_regex<br />
  18. dannyM

    dannyM New Member

    @sjau: In #17 you did not give a parameter, therefore you get the "Undefined offset: 1 in /root/letsencrypt.php on line 25" at the very beginning. I woul have expected that you get a database error first, but it seems that there is an entry without domain name...

    Now, to the general topic:

    I have not tried letsencrypt myself, but from what I understand from your discussions, the client manages the certificates completely in /etc/letsencrypt/live/..., including all renewals etc. Is this right?

    So, my proposal would be: if you select "manage certs by letsencrypt" in ispc, only the input field for the private key will be available and can be filled or autogenerated by ispc. In the background, the letsencrypt client will take care about creating the first cert and renewing it (at least, I understood that's possible).

    Then, ispc will NOT copy the certs/chains but instead SSLCertificateFile/SSLCertificateKeyFile/SSLCertificateChainFile point to the /etc/letsencrypt/live dir.

    Isn't this the much simplest approach? Or did I miss a problem?
  19. sjau

    sjau Local Meanie Moderator

    Don't worry about that. Since I call the script from the cli I can use the $argv array for accessing the command line arguments:

    Yes, there's also an archive with older certs as far as I see but currents are store in /etc/letsencrypt/live/sub.domain.tld/
    For renewal, a different script is needed which I don't see in the Git version this far.

    This what Till plans, see #9. However until that is integrated into ISPConfig, I'd like to have my script to manage them already. Let's Encrypt will start offering real cert for general public sometime mid-november.

    So, I still hope to fix that script. I fail to see why the API call doesn't work. I checked out the web site template and took over all parameters. I fill the params with the values that are already in the db stored except for the ssl stuff.
  20. till

    till Super Moderator Staff Member ISPConfig Developer

    Accordimg to the error message, all the mentioned fields are empty or not set. Did you try to add some debug code right before the remote api call to see that al values in $params are really set?

    An easier method for update is to use the $client->sites_web_domain_get method to get a $params array, then just modify the value that you want to update and then pass the same arary back to the update function.

Share This Page