Use single SSL Certificate for www and non-www with Let’s Encrypt
If you have your own server or vps which you need to setup the SSL for you domain yourself, you can use single key for both www and non-www, just with single command. There is Certbot tool for that!
Some preparation to have:
- both www and non-www already accessible, eg:
www.yourdomain.com
andyourdomain.com
- have access to the server from SSH and sudo access
This post is assume you’re using Apache for PHP application with Ubuntu Operarating system.
Here the steps you can do:
1 Install the CertBot with instruction at https://certbot.eff.org/instructions?ws=apache&os=ubuntufocal
You can follow the instruction for other web server and operating system by choose which web server and operating system you use.
2 Run the CertBot command to generate SSL key for both www and non-www:
echo "2" | /usr/bin/certbot certonly --apache \ --domains yourdomain.com,www.yourdomain.com \ && /usr/bin/systemctl reload apache2 && /usr/bin/systemctl restart apache2
The option “2” above is used to Renew and Replace instead of keep existing certificate, then provide multiple domains after --domains
to provide multiple domains separated by ,
:
The SSL certificate will be generated at the following locations:
- /etc/letsencrypt/live/yourdomain.com/fullchain.pem
- /etc/letsencrypt/live/yourdomain.com/privkey.pem
or based on your output information.
3 If your site use default domain, you may need to lookup the following paths:
- /etc/apache2/sites-available/000-default.conf
- /etc/apache2/sites-available/default-ssl.conf
If you have different domain then root domain, create new one for them, eg: yourdomain.com.conf
and yourdomain.com-ssl.conf
.
Backup above config first!!!
Usually, the usage of www and non-www is: when it found a www, it redirected to non-www, or vice versa. You first can configure in 000-default.conf
:
<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/public ServerName www.yourdomain.com <Directory /var/www/public> Options Indexes FollowSymLinks AllowOverride None Require all granted Order Allow,Deny Allow from All FallbackResource /index.php </Directory> Redirect / https://yourdomain.com/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> <VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/public ServerName yourdomain.com <Directory /var/www/public> Options Indexes FollowSymLinks AllowOverride None Require all granted Order Allow,Deny Allow from All FallbackResource /index.php </Directory> Redirect / https://yourdomain.com/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Above config will redirect non-https www and non-www to https://yourdomain.com .
Now, let’s configure default-ssl.conf
as follow:
<IfModule mod_ssl.c> <VirtualHost _default_:443> ServerAdmin webmaster@localhost ServerName www.yourdomain.com DocumentRoot /var/www/public <Directory /var/www/public> Options Indexes FollowSymLinks AllowOverride None Require all granted Order Allow,Deny Allow from All FallbackResource /index.php </Directory> Redirect / https://yourdomain.com/ ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLEngine on SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory> </VirtualHost> <VirtualHost _default_:443> ServerAdmin webmaster@localhost ServerName yourdomain.com DocumentRoot /var/www/public <Directory /var/www/public> Options Indexes FollowSymLinks AllowOverride None Require all granted Order Allow,Deny Allow from All FallbackResource /index.php </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLEngine on SSLCertificateFile /etc/letsencrypt/live/yourdomain.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/yourdomain.com/privkey.pem <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory> </VirtualHost> </IfModule>
Above config set certificate to location the Certbot print the SSL key. As the SSL is always catched too early, both www and non-www need to have SSL key config!
Ok, configuration seems complete, let’s run the following commands to enable the configs:
sudo ufw allow in "Apache Full" sudo a2enmod ssl sudo a2enmod headers sudo a2enconf ssl-params # enable default-ssl.conf # if you have different name, then provide different name sudo a2ensite default-ssl # you can add as many config as you created, eg: # sudo a2ensite yourdomain.com.conf # sudo a2ensite yourdomain.com-ssl.conf sudo apache2ctl configtest
Now, its done, time to test:
/usr/bin/systemctl reload apache2 && /usr/bin/systemctl restart apache2
Let’s open the site:
1. http://www.yourdomain.com > redirected to > https://yourdomain.com 2. http://yourdomain.com > redirected to > https://yourdomain.com 3. https://www.yourdomain.com > redirected to > https://yourdomain.com 4. https://yourdomain.com don't redirect as already in target.
and if you’re lucky, you will get redirected to SSL with configured SSL success!
Note:
Let’s Encrypt has expiration on 3 months, and you need to re-generate it before it expired, you can re-generate it monthly via cronjob if needed:
Run crontab -e
command and add the following entry:
0 0 1 * * echo "2" | /usr/bin/certbot certonly --apache --domains yourdomain.com,www.yourdomain.com && /usr/bin/systemctl reload apache2 && /usr/bin/systemctl restart apache2
that will regenerate next month at date 1th at 00:00, and next month, repetitively, and save (CTRL + X if you use nano, or !wq if you’re using vim).
That’s it 😉
leave a comment