SSL certificate is something that you need all the time, you want to encrypt your traffic even if it’s inside your LAN. You also want to know that you can trust the certificate. And with self-signed certificate you will run in to issues with Apple devices and other devices will throw errors. Lucky for us we can use Let’s Encrypt to get a valid certificate!
That’s something that you can achieve with a CA. But let’s face it who have a CA in a home lab or smaller infrastructure? So, it’s an easy way to get it. We can use Let’s Encrypt and generate a wildcard certificate and then use that, in this guide we are going to use acme shell script in Ubuntu 24.04. Good thing with acme shell script is that you won’t need to open any ports.
Introduction
Validated on
This how-to have been tested and known to work, but not limited to the following versions
- Ubuntu 24.04
- Ubuntu 22.04
Prerequisite
- Sudo or root access to your Ubuntu Server
- SSH access to your Ubuntu Server
- SSH software
- macOS, you can use Terminal
- Linux, you can use Terminal
- Windows, I do recommend you to use PuTTY
- Your own domain
- API account for your domain with the following permissions
- addSubdomain
- addZoneRecord
- getDomains
- getSubdomains
- getZoneRecords
- removeSubdomain
Good to know
- No need to open any ports in your firewall
- In this guide I’ll use Loopia as an example as it’s my domain provider, so make sure to change it to the domain provider you’re using if you’re not using Loopia.
- During this guide you need to replace some of the text with your unique name etc
- YOUR@MAIL.COM = Replace it with your own mail
- APIUSERNAME@DOMAINPROVIDER = Username for your user that have API access to your domain
- YOURPASSWORD = Password for your user that have API access to your domain
- YOURDOMAIN.com = Replace it with your domain
- Nano commands
- To save a file after you have made changes press CTRL+X and then Y
- Go to the end of the file press CTRL+W and then CTRL+V
- Search for text in the file, press CTRL+W and then write what you want to search for then press enter
Recommendation
- If you haven’t secured SSH on your Ubuntu Server I do recommend you to read my guide about it
Install acme shell script
First thing to do is to make sure that we have all needed components installed and Ubuntu up to date.
Update Ubuntu
sudo apt update && sudo apt upgrade -y
Now we need to install a few components that are needed for everything to work
sudo apt install socat -y
Now when that’s done, we need to reboot
sudo reboot
We need to change user to root
sudo su -
It’s time to install acme
curl https://get.acme.sh | sh -s email=YOUR@MAIL.COM
Now you need to disconnect from your SSH instance and then connect again
Once again let’s change to the root user
sudo su -
One good thing with Let’s Encrypt is that we can auto update our certificate before it expires, so let’s make sure that’s activated.
acme.sh --upgrade --auto-upgrade
Generate wildcard certificate
First, we need to add our domain providers API URL to acme, example below I’m using Loopia.
export LOOPIA_Api="https://api.loopia.se/RPCSERV"
We also need to add our API user and password for that user
export LOOPIA_User="APIUSERNAME@DOMAINPROVIDER" export LOOPIA_Password="YOURPASSWORD"
It’s time to generate the wildcard certificate, this can take some time to do. Remember to replace dns_loopia if you’re using any other domain provider then Loopia.
acme.sh --issue --dns dns_loopia -d *.YOURDOMAIN.com
Now we need to install the certificate and depending on what web server you’re using you can do it in some different ways, I use to create a folder named SSL in the web server root folder so first let’s do that.
sudo mkdir /etc/nginx/ssl
sudo mkdir /etc/apache2/ssl
sudo mkdir /etc/lighttpd/ssl
To install the certificates to the newly created folder we need to execute some commands and once again depending on what web server you’re using the command is different
acme.sh --install-cert -d *.YOURDOMAIN.com \ --key-file /etc/nginx/ssl/privkey.pem \ --fullchain-file /etc/nginx/ssl/fullchain.pem
acme.sh --install-cert -d *.YOURDOMAIN.com \ --key-file /etc/apache2/ssl/privkey.key \ --fullchain-file /etc/apache2/ssl/fullchain.pem \
acme.sh --install-cert -d *.YOURDOMAIN.com \ --key-file /etc/lighttpd/ssl/privkey.pem \ --fullchain-file /etc/lighttpd/ssl/fullchain.pem
Now we need to generate a strong Diffie-Hellman group, this can take some time to finish
sudo curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/nginx/ssl/dhparam.pem
sudo curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/apache2/ssl/dhparam.pem
sudo curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/lighttpd/ssl/dhparam.pem
Create Snippet (optional)
(I’ll later add how to do this with Lighttpd)
Our life’s will get much easier when we are going to create server blocks in NGINX and APACHE2 if we create snippets for SSL. So, let’s do that
First, we need to create a snippet where we can add the location of our SSL certificates
sudo nano /etc/nginx/snippets/ssl-cert.conf
sudo mkdir /etc/apache2/snippets sudo nano /etc/apache2/snippets/ssl-cert.conf
Add the following to the file
ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; ssl_dhparam /etc/nginx/ssl/dhparam.pem;
SSLCertificateFile /etc/apache2/ssl/fullchain.pem SSLCertificateKeyFile /etc/apache2/ssl/privkey.key SSLOpenSSLConfCmd DHParameters /etc/apache2/ssl/dhparam.pem
Now we are going to create a snippet with SSL parameters
sudo nano /etc/nginx/snippets/ssl-param.conf
sudo nano /etc/apache2/snippets/ssl-param.conf
Add the following to the file
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off; ssl_session_timeout 1440m; ssl_stapling on; ssl_stapling_verify on; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; add_header X-XSS-Protection "1; mode=block"; add_header Referrer-Policy "strict-origin-when-cross-origin"; add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options nosniff always;
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305 SSLHonorCipherOrder off SSLSessionTickets off SSLUseStapling On SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
Conclusion
Now everything is finished, I did not walk you through how to configure NGINX, APACHE2 etc as that’s something that I’ll do in the other guides as it depends on what service you will run and so etc. I do hope you find this guide useful.