Installing a Self Signed Cert on your Local Machine

As browser security increases in 2021 it’s gotten a lot harder to install a self-signed cert on your local dev server and get a nice pretty dark gray lock (I kinda miss the green). It’s very important, especially if you are working with web workers and javascript. Web browsers are continually tightening down the security and you no longer even accept TLS 1.0 and 1.1 anymore, so keep those certs and virtual host configuration and web server SSL settings up to date! This is something you have to do every time you work on a new domain and you won’t have a cool tool like Letsencrypt and Certbot to use because they do a round trip on the server which it means it has to be publically exposed and available online which is something you should never do with your local development server. Since it took all day to figure it out I thought I’d write an article on it.

Privacy Error, Not Secure local Dev website
Local Error for Self Signed Cert

The process is pretty straightforward.

  1. Generate a key and certificate with Openssl.
  2. Specify the key and certificate in your Web Servers configuration file
  3. Restart web server
  4. Export certificate from browser
  5. Import that certificate into the browser
  6. Restart the browser

I set this up on my Windows machine with Git Bash and Openssl running Apache Web Server and using Chrome as my browser, but the steps are the same if you are using a Linux machine, and the web configuration will change if you are using a different web server or depending on where you put your website or generated your cert/key. The web server will always have a way to specify a key and certificate for https.

One of the major changes I had to do that I didn’t have to do before was use a configuration file for openssl. You can find it here at minimal.cnf and it looks like this:

prompt = no
distinguished_name = req_dn
x509_extensions = x509_ext

[ req_dn ]

commonName = www.websitedomain.local

[ x509_ext ]

subjectAltName = @alt_names

DNS.1 = www.websitedomain.local
DNS.2 = websitedomain.local

minimal.cnf file (change commonName and DNS.1 and DNS.2 to your local domain names…I believe you can also specify an ip as IP.1 if you want under alt_names)

The openssl command is as follows….once again, change the names to something appropriate for your website…these are the files that are referenced in your virtual host file. I set it to be good for less then 3 years because I believe there is some sort of max for security reasons, at least in Chrome.

openssl req -newkey rsa:4096 -x509 -sha256 -days 1000 -nodes -out www.websitedomain.local.crt -keyout www.websitedomain.local.key -config minimal.cnf

My Apache configuration file for this virtual host in httpd-vhosts.conf looks like this:

<VirtualHost *:443>
    ServerAdmin [email protected]
    DocumentRoot "C:/websites/www.websitedomain.local/public_html"
    ServerName www.websitedomain.local
    ServerAlias websitedomain.local
    ErrorLog "logs/www.websitedomain.local-error.log"
    CustomLog "logs/www.websitedomain.local-access.log" common
    DirectoryIndex index.php index.html index.htm
    SSLEngine on
    SSLCertificateFile "C:/websites/www.websitedomain.local/ssl/www.websitedomain.local.crt"
    SSLCertificateKeyFile "C:/websites/www.websitedomain.local/ssl/www.websitedomain.local.key"
    <Directory "C:/websites/www.websitedomain.local/public_html">
        AllowOverride All
        Options  Indexes FollowSymLinks Includes ExecCGI
        Require all granted

Don’t forget to make sure your hosts file has an entry for your local website domain. www.webmastedomain.local

[Of course change “websitedomain” to the domain you want to setup and access the website through…it’s arbitrary, but needs to be consistent…make sure it’s the same in the configuration file minimal.cnf, hosts file, virtual hosts file and in the url you are trying to access the website through.]

Now comes the tedious part where you export the certificate through the browser and then import the slightly modified certificate as a Trusted root certificate.

And finally, don’t forget to close and reopen your browser before checking the url and it should be good for 1000 days! You can try longer, but I don’t recommend it since security requirements change all the time with browsers and web servers.

Successful Installation of Self Signed Cert for Local Dev Server
Successful Installation of Self Signed Cert for Local Dev Server

Keep Your Ubuntu Server Clean and Up to Date!

Just use these simple commands, in this order.

sudo apt-get update

sudo apt-get –with-new-pkgs upgrade

sudo apt-get dist-upgrade #updates linux kernel

sudo apt-get clean

sudo apt-get autoclean

sudo apt-get autoremove

For most setups this will work fine. There are other tools you can use ucaresystem, localepurge, gtkorphan, bleachbit, but these commands cover the basics of keeping your server up to date and go a long way towards covering basic server maintenance and keeping your system clean and up to date.

Dusting off the cobwebs

So it’s been awhile since I blogged anything and so much has happened….recently I moved servers from a managed server to a Linode server because I felt like I needed the root access and the responsibility of keeping up my own server. So in my last job I got a lot of experience maintaining my own server (really several servers with MySQL replication setup) and learned a lot about server security and running my own websites. So why Linode? Well, it was recommended to me years ago by a knowledgeable friend and after doing some research on pricing and server stats…how many cores, what kind of CPU, how much throughput per month and will it scale at a reasonable price when traffic increases. I chose Ubuntu for my OS since that’s what I’ve gotten comfortable with and it has huge community support and has been rock solid for me so far. I installed the LAMP stack using this LAMP install guide, because what you get is very bare bones and you are really building up the server yourself. Of course you need to lock down the server fairly quickly because most applications start out fairly wide open when first installed. This Linode security doc was a great help in reminding me what aspects to secure first. First create a standard login user with SUDO access (SUDO access allows a regular user account to act as root)….this is the account you will login with and upload/download files with. Also add it to the same group as www-data user (what the APACHE thread runs as). This makes it so that Apache can access the files and directories you’ve uploaded, and also has the handy feature of making it easy to see what files you’ve uploaded and what files have been created by your server scripts, or uploaded via Apache (which is one of the most vulnerable points of any server).

So moving servers was a real pain…I upgraded my PHP to 7.2 (really wanted the 50% increase in server code execution speed this is supposed to give you), upgraded MySQL servers to 5.7.25, APACHE to 2.4.38…upgrading everything gives me increased security from having all the latest bug fixes and security patches, but also called for a lot of code changes. Also the same reason I upgraded from Ubuntu 18 to Ubuntu 19 which was an adventure in and of itself. This was the
Ubuntu upgrade guide I used, and it came out pretty smooth. Before I upgraded I also had to install sendmail (so my php programs could “mail”). There are multiple mail servers to use, and I will probably use a more advanced one for when I create email accounts with my domains, but sendmail is nice just to get my contact forms back up and running and sendmail is rock solid.

Upgrading to PHP 7.2 (and really any pre-7 to PHP 7) primarily consists of updating the MySQL calls…now ideally I would want to take my current custom code and implement a shiny new frame work like Laravel which has all the code updates for PHP 7, BUT it was quicker to just update my current code base. So my SQL queries were fairly basic, nothing too fancy, so they remained the same and you are just changing these mysql functions with these mysqli procedural versions of the functions and you just search and replace strings like “mysql_query(” with “mysqli_query($connection,” ….the caveat being you need to make sure all your function calls have access to $connection…also mysql_error() with “mysqli_error($connection)” (and/or mysql_error($connection)), etc. Not easy. Check the mysql logs to see what errors are being thrown and fix as you go until all the pages are compiling and no errors are appearing in the logs.

So some other big things I did was move my project code to Bitbucket and Git instead of using Github and SVN, upgrade my very, very old WordPress websites to the latest version including updating the PHP code to 7, installed free SSL certs with LetsEncrypt, installed PHPMyAdmin, Webmin, Fail2Ban Firewall, and put everything behind Cloudflare, and setup local development environments which I will detail in later articles.

The 2 best things since sliced bread

Not going to talk a lot here, but I wanted to share 2 quick things. If you are not using Cloudflare…..use it. It’s a CDN, but also so much more. It can protect your site from attacks and has a handy firewall, also a handy interface to handle your DNS, some nifty analytics, and can also handle your SSL cert to make it dead simple to go https. One of my favorite things is the speed optimizations where it can automatically minify your CSS and JS as well as do some very cool image optimization. Best of all it’s free for small companies and cheap for large….I use it on all my work sites and when I get some time I’m switching this site to it. They’ve also just implemented a new geocentric load balancer that I’m excited to try.
The other things I wanted to mention was this site HTACCESS Tester. If you’ve ever had to deal with an htaccess file, and who hasn’t if you’re doing serious web dev for SEO, you know it’s a pain in the ass….it can do remarkable things w/url rewrites and 301’s, BUT it can be incredibly evil as well. You probably already know about the tag you can insert into your virtual host configuration to turn on logging for htaccess (LogLevel alert rewrite:trace6), but that log is waaaay too much info, especially with a large .htaccess file. Enter htaccess tester. Now you can write a rule and check if it gets applied the way you think it will…seriously, it’s a life saver.