Back in the day I set up a few VPSes with WHM/cPanel on to host some sites. As back then the certificates for the cPanel services (FTPD, SMTP, WHM, …) were self-signed and Let’s Encrypt was still in its early days, I also ordered a wildcard certificate for *.3rds.be along with that and configured WHM to use that certificate for its services.
With the release of cPanel/WHM 56, cPanel started offering free cPanel-signed hostname certificates, removing the requirement for a user to get and install a custom one. New installs immediately use those cPanel-signed certificates, but setups from before that – like mine – still kept their old configuration. As my wildcard certificate is up for renewal, I decided to switch to the cPanel-signed hostname certificate … but how to do that?
In short
Adjust one of the services to use a self-signed certificate.
Run /usr/local/cpanel/bin/checkallsslcerts on the server to have it replace the self-signed certificated with a cPanel-signed one.
Apply the cPanel-signed certificate to the other services.
The longer version
Log on to your WHM server and go to the “Manage Service SSL Certificates” section. There you should see all cPanel services with your current certificate activated
Services with a soon to expire certificate
For one of the services, hit “Reset Certificate”. That will remove your custom certificate and replace it with a self-signed one
The FTP Server Service, now with a self-signed certificate
SSH to your server (as root) and run /usr/local/cpanel/bin/checkallsslcerts. That will replace the self-signed certificate for the one service with a cPanel-signed one
root@s01 [~]# /usr/local/cpanel/bin/checkallsslcerts
The system will check for the certificate for the “cpanel” service.
The system will attempt to verify that the certificate for the “cpanel” service is still valid using OCSP (Online Certificate Status Protocol).
The certificate for the “cpanel” service passed all checks.
The system will check for the certificate for the “dovecot” service.
The system will attempt to verify that the certificate for the “dovecot” service is still valid using OCSP (Online Certificate Status Protocol).
The certificate for the “dovecot” service passed all checks.
The system will check for the certificate for the “exim” service.
The system will attempt to verify that the certificate for the “exim” service is still valid using OCSP (Online Certificate Status Protocol).
The certificate for the “exim” service passed all checks.
The system will check for the certificate for the “ftp” service.
The system will attempt to replace the self-signed certificate for the “ftp” service with a signed certificate from the cPanel Store.The system will attempt to install a certificate for the “ftp” service from the system ssl storage.
None of the certificates in the system ssl storage were acceptable to use for the “ftp” service.
The system will attempt to install a certificate for the “ftp” service from the cPanel store.
Received error “X::NoCertificate” from cPanel Store (No free ssl certificate found for this IP); requesting new certificate …
Setting up HTTP DCV (/var/www/html/.well-known/pki-validation/54BDF83083ED3F53405BDE8A940D13C0.txt) …
… complete.
Setting up DNS DCV (CNAME _54bdf83083ed3f53405bde8a940d13c0.s01.3rds.be) …
… complete.
Attempting DNS DCV preflight check …
… success!
Attempting to verify your certificate.....
Querying Apache TLS for installations of the previous certificate …
root@s01 [~]# exit
The output for /usr/local/cpanel/bin/checkallsslcerts
Reload the “Manage Service SSL Certificates” section and verify that the self-signed certificate got replaced
The FTP Server Service, now with a cPanel-signed certificate
Hit “Apply Certificate to Another Service” for the service with the cPanel-signed certificate. The form beneath the grid will be prefilled with the certificated details.
Check all boxes of the other services, and hit apply. After that the certificate details will have been copied to those services too
All cPanel/WHM Services, now with a cPanel-signed certificate
That’s it! 🎉
Did this help you out? Like what you see? Thank me with a coffee.
I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
One of the things that’s still not really frictionless for your local development domains is the use of certificates.
To circumvent the use of self-signed certificates I explained in said article how I have a dedicated domain with all subdomains pointing to 127.0.0.1. That way I can use proper certificates for my local dev needs.
In How to get HTTPS working on your local development environment in 5 minutes another technique – one which works with all domains, even localhost itself – is unearthed: create a root certificate yourself, and trust it on your system. Any certificate linked to that root CA will then also be trusted, thus any host using it will have valid certificate no matter how it’s being accessed (curl, browser, etc.)
I like this “hack” because you only have to trust the generated root CA once (and not each certificate separately). I guess if you combine it with xip.io you can also get it to work on your smartphone talking to local dev stuff (or is there any way to have manual DNS entries on your iOS device?).
Earlier today, in a post entitled Secure Contexts Everywhere, it was announced on the Mozilla Security Blog that Firefox from now on will only expose new features such as new CSS properties to secure contexts:
Effective immediately, all new features that are web-exposed are to be restricted to secure contexts. Web-exposed means that the feature is observable from a web page or server, whether through JavaScript, CSS, HTTP, media formats, etc. A feature can be anything from an extension of an existing IDL-defined object, a new CSS property, a new HTTP response header, to bigger features such as WebVR. In contrast, a new CSS color keyword would likely not be restricted to secure contexts.
Whilst I somewhat applaud this move, especially in the age of data theft and digital espionage, it’s – pardon my French – quite a ballsy thing to do. CSS Properties, really?
A context will be considered secure when it’s delivered securely (or locally), and when it cannot be used to provide access to secure APIs to a context that is not secure. In practice, this means that for a page to have a secure context, it and all the pages along its parent and opener chain must have been delivered securely.
Roughly translated: http://localhost/ is considered to be a secure context, so that one will have the latest and greatest. However, the docs aren’t that clear on whether the definition of “local” involves actual DNS resolving or not:
Locally delivered files such as http://localhost and file:// paths are considered to have been delivered securely.
What about development domains – think project.local or project.test – pointing to 127.0.0.1? Right now we’re left in the blue here …
Do note however that Mozilla “will provide developer tools to ease the transition to secure contexts and enable testing without an HTTPS server”, but the related bug is still unassigned.
~
It’s best to have your local web development stack mimic the production environment as closely as possible. Over the years we’ve seen the rise of tools like Vagrant and Docker to easily allow us to do so: you can run the same OS and version with the exact same Apache version with the exact same PHP version with the exact same MySQL version with … oh you get the point.
One of the things that’s still not really frictionless right now for your local development domains is the use of certificates.
Yes, you could use self-signed certificates for this, but that’s:
Not always possible: The Fetch API for example doesn’t allow the ignoring of self signed certificates.
Asking for potential security problems the moment you go into production: I once read a post about some production code that still had the --insecure flag enabled on the curl requests 🤦♂️. It was put there in the first place because of to the self-signed certificates used during development.
Another approach – and one that I am taking – is to use an actual domain for your dev needs. Each project I build is reachable via a subdomain on that dedicated domain, all pointing to 127.0.0.1 thanks to a an entry in my hosts file. Since it’s an actual domain I am using, I can use an actual and correctly signed certificate along with that when it comes to HTTPS.
At the cost of only a domain name (you can get your certificates for free via Let’s Encrypt, which now support wildcards too) that’s quite a nice solution I think.
~
Back in December 2017 version 63 of Google Chrome was released. One of the changes included is that Chrome now requires https for .dev and .foo domains. This was ill-received by quite a lot of developers as most of them – including me before – use(d) the .dev TLD for local development purposes.
And yes, the pain is real … just do a quick search on Twitter on chrome https dev and you’ll see that lots of developer have wasted – and still are wasting – many hours on this breaking change.
Yes, there’s a (lengthy) workaround available to get the green lock in Chrome, but I wouldn’t recommend it really. It would require you to repeat a likewise procedure in all browsers you have running/are testing in, and this per .dev domain you have. Above that it won’t fix any out-of-browser contexts.
Could Google have prevented this .dev debacle? Of course. But I don’t see a reversal of this change coming any time soon though …
Can Google still do something about it? Well … I have an idea about this:
Imho Google should have opened it up, pointing all domains to 127.0.0.1 / ::1 (and more, cfr. xip.io), and providing free SSL certs for all.
Just imagine if Google were to point all .dev domains to 127.0.0.1, that’d truly be paving the cowpaths! Add free SSL certificates for all .dev domains along with that and we’d jump quite far. With announcements like Secure Contexts Everywhere(referenced at the very top of this page) this idea seems like a real winner:
(Chrome) Us developers can keep using the .dev TLD for projects in development.
Us developers no longer need to use self-signed certificates anymore for projects in development. We could use certificates directly signed by Google’s CA (or by Let’s Encrypt in case Google doesn’t feel like providing certificates)
(Firefox) Domains with the .dev TLD (and with an SSL Certificate) can be considered as a Secure Context, just like any other domain reachable via HTTPS.
One can dream, right?
FIN.
Did this help you out? Like what you see? Consider donating.
I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!
Laravel-uptime-monitor is a powerful, easy to configure uptime monitor. It will notify you when your site is down (and when it comes back up). You can also be notified a few days before an SSL certificate on one of your sites expires. Under the hood, the package leverages Laravel 5.3’s notifications, so it’s easy to use Slack, Telegram or your preferred notification provider.
UPDATE 2016.01.03: A standalone version (read: version that doesn’t require Laravel knowledge) has also been released:
Under the hood the uptime-monitor is a vanilla Laravel 5.3 application with the laravel-uptime-monitor installed into it.
Great stuff again by Freek Murze from Spatie: A PHP class to easily check the validity of an SSL Certificate. Easily? Yes, easily:
$certificate = SslCertificate::createForHostName('spatie.be');
$certificate->getIssuer(); // returns "Let's Encrypt Authority X3"
$certificate->isValid(); // returns true if the certificate is currently valid
$certificate->isValid(domain.com); // returns true if the certificate is currently valid for the given `domain.com`
$certificate->expirationDate(); // returns an instance of Carbon
$certificate->expirationDate()->diffInDays(); // returns an int
The UpGuard external cyber audit uses publicly available information to grade your cyber risk posture. External scans are convenient and non-invasive but require an internal scan to assess the majority of risk factors.
If you’ve ever had to handle certificates, it can sometimes – especially when renewing them – become confusing to know which certificate is which. Enter certdiff, a handy diff tool for certificates, by Mattias Geniar:
Differences are highlighted using the diff -y output (side-by-side diff), output with the | character in between indicates differences between the files.
In light of #https2015 I flipped the switch on bram.us earlier today: from today forth bram.us is only accessible over HTTPS.
If you run a news site, or any site at all, we’d like to issue a friendly challenge to you. Make a commitment to have your site fully on HTTPS by the end of 2015 and pledge your support with the hashtag #https2015.
The switch itself should be transparent, as all “old” http:// URLs automatically redirect to their https:// counterparts.
When initially looking for information regarding this switch for WordPress sites I’ve found a lot of cruft out there. A rather high hit on Google was one dating back from 2006 (2006? … Chrome didn’t even exist for another two years) ; A few other ones recommend you to install a WordPress plugin which is just wrong (You really needn’t install a WordPress plugin to enable HTTPS!); A slew of other ones had it right, yet were incomplete; etc.
~
Here’s how to move your WordPress website from HTTP to HTTPS in just a few simple steps:
1. Install an SSL Certificate
Buy a certificate for your domain and activate it on the server. Most of the time your hosting provider offers a simple UI for this activation: paste in the private key, the certificate itself, and the CA-bundle. If you have to manually install it, I recommend taking a look at Mozilla’s SSL Configurator to get you started with the correct settings.
Note: Don’t let SSL Certificate Providers rip you off though. Services like sslcertificaten.nl or startssl.com offer them really cheap or even for free! Starting mid 2015 Let’s Encrypt will open it’s doors, offering free certificates for everyone.
You can safely install the certificate as your site will remain accessible over HTTP. In addition it’ll also be reachable over HTTPS. Verify this by manually changing the URL in the address bar from http://yoursite.com/ to https://yoursite.com/. Your website should appear, and the URL in the address bar should still hold the entered https:// URL.
Note that your browser will most likely not show the green lock icon next to the URL just yet, as your website will contain “Mixed Content”: the HTML of your site may be loaded over HTTPS, yet images contained may still be referred to using their http:// URL. We’ll fix this issue later on, in step 4.
Mixed Content warning in Chrome
Tip: Tools such as SSLLabs’ SSL Server Test come in handy to verify the proper installation of your certificate. Above that you’ll get a lovely report from it. Just one word of caution though: don’t run it on URLs used by your bank … those reports are mostly just depressing (sad but true)
Note: My first encounter with certificates back in the day had me confused about the CA-bundle. It took me a while to get to know that it’s no more than a text file containing all intermediate certificates, alle pasted one after the other.
2. Update the WordPress Settings
When having finished step 1 you’ll notice that next/prev links to blogposts and links to pages will still use the insecure http:// URLs. That’s because WordPress itself doesn’t know yet you’ll be using HTTPS from now on.
To let WordPress know you’re using HTTPS log in to wp-admin and under “Settings” → “General Settings” adjust the values for WordPress Address (URL) and Site Address (URL) to their HTTPS counterparts.
The WordPress Settings one needs to change
Once saved you should be able to start on your website over HTTPS and click through it – using the WordPress rendered links such as next/prev blogpost, pages, etc. – whilst remaining over HTTPS.
3. Force SSL for wp-admin
WordPress offers a setting to force the wp-admin only being accessible over HTTPS. To activate this edit your wp-config.php and add the following line:
define('FORCE_SSL_ADMIN', true);
Once adjusted you should be automatically redirected from http://yoursite.com/wp-admin/ to https://yoursite.com/wp-admin/. Whilst we later on (step 5) will redirect all traffic to HTTPS, it’s a good test before we change it all.
4. Fix those mixed content warnings
We’re almost to getting our site working entirely over HTTPS. What still remains is to update the content all our blogposts so that images referred, and blogposts linked (from within the content) use our https:// URLs instead of the http:// ones. Updating all blogposts manually would be a very time-consuming job. Luckily a single SQL query can this it for you.
Log on to PhpMyAdmin (or another tool which your hosting provider offers) and execute the queries below on your WordPress database.
Make sure you take a backup of your database first. If things were to go wrong you can always restore that backup.
Whilst at it I’ve also added a few extra queries to updating all internal pingbacks, and to updating all YouTube & Vimeo embeds.
[UPDATE] Note: Whilst the internal pingbacks don’t trigger any Mixed Content warnings themselves, I thought of the update as being a bit of forward thinking: that way you don’t bounce back from HTTPS to HTTP. And whilst we’re in PhpMyAdmin anyway, I’ve added them right here.
Once executed the mixed-content warnings should be gone and the green lock should appear. Clicking from blogpost to blogpost should work just fine, all whilst remaining on HTTPS.
No more mixed content: the green lock icon appears in the address bar
If you do still get mixed content warnings (check for a little shield in the Chrome Address Bar) open the DevTools Console for more information: it could be – and I had this – that a CSS file still references an http:// URL. Manually fix all those errors one by one until you get the green lock icon.
A green lock icon is present, yet a shield (on the right) also appears. DevTools has more information needed for pinpointing the problem.
Do note that if you’ve included external resources (images/scripts/css/…) you may not be able to fix them all: if they’re not accessible over HTTPS, you won’t be able to fix that error.
5. Redirect all HTTP requests to HTTPS
Now that your site works fine over both HTTP and HTTPS, it’s time to flip the switch and make it no longer accessible over HTTP. Add these rules to your .htaccess:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
The rules are written in such a way that “old” http:// URLs will transparently redirect to their https:// counterparts. That way incoming links that still use http:// will keep on working just fine, but will get a security upgrade along the way.
6. Tweak your SSL Settings
If you want you can tweak some of your SSL settings, such as enabling only a strict set of ciphers. Whilst this is entirely optional, one tweak is recommended though: enabling HTTP Strict Transport Security(thanks for the tip @mathias!)
To enable HSTS, add this line to your .htaccess:
# Enable HSTS
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS
~
Following these steps you should be able to migrate your WordPress website from HTTP to HTTPS. It looks quite cumbersome, yet it’s done in no time (writing this blogpost took more time than actually rolling it out). Above that you only gain benefits from embracing HTTPS. And yes, TLS is fast.
Did this help you out? Like what you see? Consider donating.
I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!
Just choose the web server / web front you’re using (Apache, Nginx, HAProxy) + whether you want to support only modern, intermediate, or old versions of browsers and a proper configuration will be generated.
<VirtualHost *:443>
...
SSLEngine on
SSLCertificateFile /path/to/signed_certificate
SSLCertificateChainFile /path/to/intermediate_certificate
SSLCertificateKeyFile /path/to/private/key
SSLCACertificateFile /path/to/all_ca_certs
# modern configuration, tweak to your needs
SSLProtocol all -SSLv2 -SSLv3 -TLSv1
SSLCipherSuite 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
SSLHonorCipherOrder on
# HSTS
Header add Strict-Transport-Security "max-age=15768000"
...
</VirtualHost>
Choosing modern will result in an A+ on SSLLabs. Of course a stuff like POODLE will be prevented.