Normally I do some coding over the holidays as it used to be the one time of the year I could have some dedicated time to work on personal projects, or just fiddle with random non-work things. Normally that would have been updates to the blog platform I had written to run this site quite a few years back, but I ditched that for Pelican two years ago. So this year I’ve been fiddling with a few more sysadmin-type things. Mostly I wanted a home dashboard for new browser tabs as, while I enjoyed using the Toby Chrome extension, I wanted something a little different that was more than just bookmarks.
I also use PythonAnywhere for hosting a python application for collecting weather data at home: temperature, humidity and barometric pressure. I recently moved that into a TrueNAS Core jail so I could free up the one application I can run on PythonAnywhere with my minimal plan, and decided to put my Red Hat VEX demo site there. So there were a few things to do. As I tend to use these posts as reminders for myself (and hopefully there are useful nuggets for any readers who stumble across these) I’m just lumping them all together.
First we’ll deal with getting the application that was running on PythonAnywhere and is now running in a TrueNAS (FreeBSD) jail to use nginx as a proxy so we can wrap it in SSL. I’ll also note that I’m a huge fan of LetsEncrypt — these guys changed the internet forever in a very positive way. Thank you!
LetsEncrypt with nginx for web app in FreeBSD
Pretty straightforward once you know what you’re doing. Because these are internal network applications, I use Cloudflare DNS as they’re not exposed to the internet for LetsEncrypt to connect to the actual web site. So we want to install certbot
, the Cloudflare DNS plugin and nginx:
$ sudo pkg install security/py-certbot-apache security/py-certbot-nginx security/py-certbot-dns-cloudflare nginx
Once the packages are installed, we can create our certificate:
$ sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.cloudflare.ini -d hostname.com
In this case, the Cloudflare credentials are stored in /root/.cloudflare.ini
with 0600 permissions and contents similar to:
dns_cloudflare_api_key = cloudflare_api_key_here
dns_cloudflare_email = cloudflare_account_email_here
certbot
created the SSL files we need and stored them in /usr/local/etc/letsencrypt/live/hostname.com/
so we can now edit /usr/local/etc/nginx/nginx.conf
. The local web application is run by gunicorn
and listening on localhost, port 5000.
I’ll just put the most relevant parts of nginx.conf
below:
http {
server {
listen 80;
server_name hostname.com;
listen 443 ssl;
ssl_certificate /usr/local/etc/letsencrypt/live/hostname.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/hostname.com/privkey.pem;
include /usr/local/etc/letsencrypt/options-ssl-nginx.conf
# redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location / {
proxy_pass http://127.0.0.1:5000;
include proxy_params;
}
}
}
That’s pretty much it. The only thing left to do is to enable periodic checking to renew the LetsEncrypt certificate by editing /etc/periodic.conf
and setting:
weekly_certbot_enable="YES"
Setting up homepage on Raspberry Pi
For my dashboard I chose homepage which I thought had a nice mix of utility for widgets that I wanted, and bookmarks. I have my own bookmark instance that I use internally using linkding which isn’t as nice as some paid options that are out there but I really don’t like the idea of paying for a bookmark service, and I wanted to run one locally that was private to me. Linkding is running in a docker container on my TrueNAS Scale box and it works pretty well. That was my first step in the migration off Toby. But it doesn’t make for a very nice new tab homepage.
I followed the instructions for Setting up the Homepage Dashboard on a Raspberry Pi which first meant following the Installing Docker on the Raspberry Pi instructions. Pretty simple and this is when I realized that homepage will probably be short-lived on the Pi as I can run it in a docker container on my TrueNAS Scale box, but for now, it can run on the Pi.
One note, which was new for me because I don’t really use YAML a lot and didn’t realize how important spacing was. vim
is my favourite editor but it’s too darn helpful and kept messing with the spacing (I did not change it’s Debian defaults) and it took me a long time to figure out why homepage wasn’t rendering my widgets properly. homepage is a little frustrating in this regard because it’s a bunch of YAML files to configure rather than a nice web interface, but once I figured out the vim
/YAML issue (hint: use set: paste
to make life easier!) then it was no problem.
My homepage now has widgets for a bunch of local services: Gitea, Plex, Pi-hole, TrueNAS Core and TrueNAS Scale. Also some nice widgets to display some stock prices of things I’m interested in, local weather, and bookmarks for things I use often. But, by default, it listens on port 3000 in the docker container and I wanted this to be wrapped in SSL without a non-standard port. So this is where nginx comes in again as a wonderful proxy.
LetsEncrypt with nginx for homepage on Raspberry Pi
Similar to my install in the TrueNAS jail, just for Debian. We need the Cloudflare DNS plugin, certbot
and nginx installed, and we’ll generate our first certificate. The hostname in this example is “homepage.com” and /root/.cloudflare.ini
contains the Cloudflare API credentials as noted above.
$ sudo apt install nginx certbot python3-certbot-dns-cloudflare
$ sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cloudflare.ini -d homepage.com
The certificates are generated and stored in /etc/letsencrypt/live/homepage.com/
and so we now need create a configuration file for our site in nginx, which we’ll do by creating /etc/nginx/sites-enabled/homepage-com
with the following contents:
server {
listen 80;
listen [::]:80;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name homepage.com;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/homepage.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/homepage.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf
# redirect non-https traffic to https
if ($scheme != "https") {
return 301 https://$host$request_uri;
}
location / {
proxy_pass http://127.0.0.1:3000;
include /etc/nginx/proxy_params;
}
}
I also created /etc/letsencrypt/options-ssl-nginx.conf
with the following contents (which was a copy/paste from the TrueNAS install above):
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers 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";
That’s basically it. Following the aforementioned docker on Raspberry Pi tutorial, the docker image starts on every reboot as does nginx, so now it’s easy to make the homepage my new tab page, replacing Toby completely.
However, since Chrome doesn’t let you do this natively, you need a plugin to do it. For that, I found this New Tab Redirect plugin on the Chrome web store which allows you to set a custom page for every new tab you open. Since I wanted to mimic what Toby did (by showing up every time I opened a new tab) this was the easiest way to do it.
The only thing remaining is to figure out FreeBSD’s strange rc
scripts so that I can start the gunicorn
service for my web application just like any other service (effectively when the jail starts). So far I’ve not had much luck, but I still have some of the holidays left to figure it out!