[HOWTO] Let's Encrypt

Hi all,

I have got a fully working Let's Encrypt setup for multiple domains of my Web Application Firewall on my Sophos UTM 9.4!

On github I have made a manual on how to set it up on your UTM as well. Currently it has a few manual steps to set it up, but I might script this in the future as well.


Comments, questions and improvements are welcome! And please leave a message if you have got it working as well.

Have fun!


  • Excellent. Works perfect here for me. -Your turn, sophos! -, to fill your customers needs.

    sent some pizza money donation, thanks again for this! 

  • Great work, thank you René.

    Creating the initial certificate works perfectly. However, if I run ./getssl -f domain.com for the second time a few days later, only the meta data in UTM’s Certificate Management is updated (valid from/to) but not the actual certificate.

    Looking in ~/.getssl/domain.com there are two certificates:

    UTM shows the meta data of the former while actually using the later.

    Any ideas? Thanks in advance.


  • In reply to AndreyP:

    Hi Andrey,

    Did you get any errors? Are you able to reproduce the issue or was it a one time problem?



  • In reply to rklomp:

    Hi René

    Yes, this happens every time with different domains/certificates.
    - created a dummy-certificate through UTM webadmin
    - followed all steps in your tutorial

    On the first run, ./getssl -f domain.com overwrites the dummy certificate and it’s meta data. If I run it again (without changing anything in ~/.getssl/domain.com/getssl.cfg), I can see the updated meta data in UTM webadmin but clicking the „Download“ button downloads the old (initially obtained) certificate. 

    I don’t get any errors, only this warning:
    Writing certificate for <domain.com> to object REF_ZlQRlENKlJYD
    getssl: <domain.com> - certificate obtained but certificate on server is different from the new certificate

  • In reply to AndreyP:

    Does the file /root/.getssl/domain.com/domain.com.crt and the output of

    /usr/bin/openssl x509 -in /root/.getssl/domain.com/domain.com.crt -text

    show the correct certificate?

  • In reply to rklomp:

    Yes, both show the correct new certificate, while the certificate downloaded from and used by UTM WAF is still the old one (it matches root/.getssl/domain.com/domain.com.crt_<old_date>)

  • In reply to AndreyP:

    If you add 

    print cert_object

    on line 45 of the update-cert script and then run

    ./update-cert domain.com REF_ZlQRlENKlJYD

    If you scroll up a bit it should output "Changes to object saved successfully." followed by the full certificate object containing the new certificate. Or do you see any errors in this output? Or send me a PM containing the output, so I can take a look for you.

  • In reply to rklomp:

    Thanks a million, René. With your help I now found the reason:
    When I was creating my dummy certificates in webadmin I used the default VPN ID type „Email address“ assuming that it does not matter because the certificate will be overwritten anyway.

    In this case adding „print cert_object“ to update-cert script shows the following output:
    'format' => 'The VPN ID needs to be %_d.',
    'msgtype' => 'IPSEC_VPN_ID_INVALID',
    'name' => 'The VPN ID needs to be an Email address.',

    Using the VPN ID type „Hostname“ solves the problem and the certificate will be updated as expected.

    However, this time WAF > Virtual Servers will not let me chose any of the certificate’s additional domains (SANS=). While the certificate is valid for 3 domains, WAF will only let me chose the primary one.

    My workaround is now the following:
    - Create a dummy certificate in webadmin, VPN ID = Hostname
    - Run getssl according to your tutorial
    - export the certificate through webadmin as .p12 > then delete it from webadmin > then re-import the .p12 file
    - Now the certificate will have a new reference number (REF_xxx) so ~/.getssl/domain.com/getssl.cfg needs to be adopted.

  • In reply to AndreyP:

    Good to hear that it now works. Just added that you should use type "Hostname" to the tutorial as well.

    For the subdomains in SANS this should work instantly as far as I know, the webadmin uses the metadata to create the list of domains. This metadata is updated using the script, so webadmin should have the list as well. 

  • In reply to rklomp:

    @klompie - Thanks for this!  I have a quick question, though.  If I already have installed, manually, a certbot generated LetsEncrypt certificate, can I use this tool to maintain that certificate?  I know I would need to include it in the update-cert function, but what else would I need to do to make this work?

  • In reply to darrellr:

    If you use the certificate reference of your current Let's Encrypt certificate the script will overwrite the contents of this certificate with the newly retrieved certificate.

    For testing purposes I would recommend creating a new certificate. This way you will keep your current Let's Encrypt certificate separate and you can easily roll back.

  • In reply to rklomp:

    Yeah, I started looking through your code and decided it would be easier to just replace it in a while.  Unfortunately, between playing with certbot and your tool, I have hit my limit for the week (doh - shot self in foot).  I am simply trying to move away from the free StartSSL certs and was able to manually generate the cert I needed, but then decided to try your process.  I am still hesitant to execute code on the firewall like this and wish there was an easier way to manage this cert off the box.  I might look into that process if you don't mind me hacking away at your code to see if I can pull it off.  I will likely disable the version checking code in your script because I do not like the script (no offense intended) communicating to anything except Lets Encrypt.

  • Hi René,

    Thanks for such a great script. Just what I was looking for to use on my home project server.

    I think I've got everything working this end and my browsers now all show a happy green padlock....with one exception!

    It seems android does not recognise the CA properly? When reading around on this it mentions I might need to serve the intermediate cert using the fullchain.pem example here however i'm not sure how I would modify the script to do this, or even if it's possible with your method?

    Any help with this would be great, 

    Thanks again for the handy hack and enjoy a latte on me,


  • In reply to JamesYeates:

    No worries, seems to be working now, must have been caching the old cert or something

  • Thx for this tool! nice work.

    i was wondering however. You mention it is possible to save the ACME-challenge on another server through FTP, but sophos UTM doesn't include a FTP client. Is there a way tackle this?

    i would like to create a lets encrypt cert for my exchange server, wich obviously only works with Windows/IIS wich doesn't support SSH.