So, you want to run Perl on the web, because it’s the 90s all over again. You want HTTPS, because… no, there’s no because. You want HTTPS. Who wouldn’t? Here’s what you do on a Debian Linux such as Ubuntu:
sudo apt-get install apache2 libapache2-mod-perl2
mod-perl
is an Apache module that allows Perl programs to be executed from Apache.
Our goal is to get /var/www/html/index.pl running at http://www.example.com/index.pl:
#!/usr/bin/perl print "Hello World"
Disable the default Apache virtual host:
sudo a2dissite 000-default.conf
Create an example.com.conf
file in /etc/apache2/sites-available
with your text editor, replacing instances of example.com
with your own domain name in both the configuration file and in the file name /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/> Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch AllowOverride None AddHandler cgi-script .pl Require all granted </Directory> </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ServerName example.com ServerAlias www.example.com ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined <Directory /var/www/> Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch AllowOverride None AddHandler cgi-script .pl Require all granted </Directory> </VirtualHost> </IfModule>
If you have multiple sites, you’ll want to do things with DocumentRoot
to isolate them from each other. But that’s for another post.
You might add in DirectoryIndex /index.pl
to make http://www.example.com/ execute your program.
The Directory
section above allows you to isolate executable code from served code, which is good practice. For this example we’re dumping the executable in with everything else, which is questionable.
Repeat this process for any other domains you host.
sudo a2ensite example.com.conf
sudo ln -r -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/example.com.conf
sudo service apache2 restart
Punch holes in your firewall for ports 80 and 443. Navigate to http://www.example.com/index.pl to check all is okay. You ought to see Hello World displayed for your website.
Having security used to be a pain. SSL certificates signed by a recognised CA cost money, and then you’d have to keep them up to date, and there wasn’t process automation, so you’d do all that stuff by hand. LetsEncrypt address all these problems, handing out free certificates and scripted everything.
Now it’s time for the S part of HTTPS:
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-apache
sudo certbot --apache
certbot renew
If that works, we’ll automatically renew our 90-day certificates every month:
echo '@monthly root /usr/bin/certbot renew >> /var/log/letsencrypt/letsencrypt-auto-update.log' | sudo tee --append /etc/crontab
Done. You’ll never have to worry about certificates again. Now alter your Apache sites-available file (look in /etc/apache2/sites-available/) to include the (optional) redirect HTTP to HTTPS and the mandatory location of the SSL certificates:
<VirtualHost *:80> .... # Only allow HTTPS RewriteEngine on RewriteCond %{SERVER_NAME} = example.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent] </VirtualHost> <IfModule mod_ssl.c> <VirtualHost *:443> ... SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf </VirtualHost> </IfModule>
Now make the secure version live, and in the process the insecure one… shy? When a request is made for a http page, like http://example.com/index.html, the response will be “Here’s https://example.com/index.html where what you asked for has moved to… forever!”:
sudo service apache2 restart
Now requesting http://www.example.com/index.pl ought to deliver you to https://www.example.com/index.pl
Presumably the LetsEncrypt certificate mechanics will work if your server is publicly accessible.
If it is not (because you want https within the premises), and I have a weird domain name like “wellington.kk”, what’s the best way of handling that? This is not entirely theoretical, as evidenced in this Stack Exchange Question Is it acceptable for an internal HR site to run over HTTP?.
certbot has manual mode (that I haven’t looked into) which the man page suggests can work without an incoming Internet connection. I wouldn’t surprise me that if you have to obtain the initial certificate in manual mode, auto-renewal will be problematic.
Generally, LetsEncrypt hands out certificates to servers it can confirm are who they say they are; as such they need to be Internet accessible. But being publicly Internet accessible doesn’t mean “open to all comers”, if the box is kept up-to-date and locked down to a minimal attack surface, the threat of the Internet is minimized.
Having said all that, if you’re just securing an internal server, then generate your own self-signed certificates. There’s plenty of how-tos on the web for that and it’s no big deal.