Adding a trusted self-signed SSL certificate to Apache on Debian/Ubuntu
- Creating an OpenSSL configuration
- Creating a trusted self-signed SSL certificate
- Configuring Apache to use SSL
- Installing certutil utility
- Adding a certificate to the database
- Encryption testing
In this article I will explain how to add a trusted self-signed SSL certificate to the Apache server on the Debian/Ubuntu operating system. I always use the HTTPS protocol for the local development environment. But I was always annoyed that the browser does not trust the self-signed SSL certificate and displays a notification about it. Several times I tried to figure this out. I tried different instructions, but none of them solved my problem. And then one day I decided to deal with this problem in detail and finally solve it. I hope this instruction helps you too.
At some point, I again had errors in browsers: NET::ERR_CERT_AUTHORITY_INVALID (Google Chrome), MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT (Firefox). And again I had to figure out how to solve this problem. I wrote a new article on how to add a trusted SSL certificate for the local environment in Apache on Debian/Ubuntu. This time we will use the root certification authority (CA).
This instruction was executed on operating systems: Debian 10, Debian 9, Ubuntu 20.10, Ubuntu 20.04, Ubuntu 19.10.
Creating an OpenSSL configuration
Let's start with this important section. We need to create a configuration file for OpenSSL by running the command in the terminal:
nano /tmp/openssl.cnf
Copy and paste the following prepared configuration into a new file, where DNS.1 is the name of your server (specify DNS.2 if you need support for subdomains):
[req]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
x509_extensions = v3_ca # The extensions to add to the self-signed cert
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = New York
localityName = Locality Name (eg, city)
localityName_default = Rochester
organizationName = Organization Name (eg, company)
organizationName_default = Localhost CA
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Development
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = localhost
commonName_max = 64
[v3_ca]
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
# Support subdomains
#DNS.2 = *.domain.local
Save the changes and close the file.
Creating a trusted self-signed SSL certificate
Now let's create a self-signed SSL certificate with a private key using our configuration file:
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/localhost.key -out /etc/ssl/certs/localhost.crt -config /tmp/openssl.cnf
where
- req is a command that indicates the use of X.509 (certificate signing request management);
- -x509 is a certificate data management command, indicates the creation of a self-signed certificate;
- -nodes is a command that skips the use of a passphrase;
- -days 3650 is a team that sets the certificate validity period in days (we set it to ten years);
- -newkey rsa: 2048 is a command that generates a new private key using the RSA algorithm with a key length of 2048 bits;
- -keyout /etc/ssl/private/localhost.key is the path to placing the private key file;
- -out /etc/ssl/certs/localhost.crt is the path to place the certificate file;
- -config /tmp/openssl.cnf is the path to the configuration file.
In the process of generating the certificate, several questions will be asked. You can skip them:
Configuring Apache to use SSL
Let's enable SSL in the Apache server configuration. We will specify listening on port 443 (HTTPS) and the path to the certificate and private key files. Edit the server configuration file /etc/apache2/sites-available/default-ssl.conf:
sudo nano /etc/apache2/sites-available/default-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/localhost.crt
SSLCertificateKeyFile /etc/ssl/private/localhost.key
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>
Save the changes and close the file.
You must activate the mod_ssl module by running the command in the terminal:
sudo a2enmod ssl
Do not forget to activate the configuration file by running the command in the terminal:
sudo a2ensite default-ssl
Check the configuration for validity by running the command in the terminal:
sudo apache2 -t
Now apply the configuration changes by running the command in the terminal:
sudo service apache2 reload
Installing certutil utility
Now we need to add the generated SSL certificate to the database that the browser uses. The certutil utility, which is part of the libnss3-tools package, is used to manage this database. If you do not have this package in the system, then install it.
Before any software installation, it is recommended to update the list of repository packages by running the command in the terminal:
sudo apt-get update
Install the libnss3-tools package by running the command in the terminal:
sudo apt-get install libnss3-tools
Adding a certificate to the database
Let's add the generated SSL certificate to the database using the certutil utility by running the command in the terminal:
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost.crt -i /etc/ssl/certs/localhost.crt
This instruction has been tested on browsers: Google Chrome and Opera.
The Firefox browser does not want to trust the certificate, it uses the cert8.db database, which I edited as follows:
certutil -d sql:$HOME/.mozilla/firefox/xqck5xx8.default -A -t "P,," -n localhost.crt -i /etc/ssl/certs/localhost.crt
Encryption testing
In order for the browser to read the updated certificate database, you need to restart your browser (close and reopen).
Let's check that our Apache server is accessible via the HTTPS protocol by entering the following address in the browser:
https://localhost
If you did everything correctly, you will see that the browser has begun to trust your self-signed certificate. Your connection will now be encrypted using the HTTPS protocol without displaying a warning about an insecure connection: