I like music, films, travelling and most things computer related. This here's a blog.
Two things happened recently: My SSL certificate for capslocknotificationapp.com expired and I needed to launch a new Wordpress site.
I went to my old server and revisited my old Docker setup (detailed in a previous post here) and it was in a bit of a state. It was using a very old version of Docker and it was a pain to get a new certificate etc.
Anyway, I decided to rework the whole shebang:
- updated Docker (v1.12 - latest at the time) so I can use Docker Compose (v1.8.0), allowing the setup to be a bit more flexible in the long run.
- integrated Let’s Encrypt so I don’t have to deal with Comodo via the HTTPS_PORTAL container.
- switched from MySql backend to the maintained, compatible and open source MariaDB.
Here are the steps:
- Get a DigitalOcean instance
- This time I got a beefier 2GB Ram, 40GB SSD instance as I intend to be running more (non-critical) sites from it.
- A suitable OS that supports Docker
- I selected Ubuntu 16.04, although I think CoreOS is a good option too.
- Create a SSH key on your local box - guide here
- unless you set up the SSH during the DO instance creation, which wasn’t working for me.
DigitalOcean box setup
We want to secure the DO instance and make sure it is up to date.
SSH into the box using the password/IP address sent in the DO email and change the password. Add your newly created SSH key to the DO instance:
cat ~/.ssh/<your-key>.pub | ssh root@[your.ip.address.here] "cat >> ~/.ssh/authorized_keys"
SSH into the box and update the SSH config file (sshd_config) to stop SSH connections using the password. (You might want to setup an SSH config to make this easier: info)
sudo nano /etc/ssh/sshd_config
Change or add the following line to the ‘Authentication’ section:
Restart the SSH server for the changes to take effect
ps auxw | grep ssh kill -HUP <PID of SSH process>
Setup swap space for MariaDB use later on
The database eats up a lot of memory and I found it killed some of my docker container. A way to solve that is to give the box more swap space. I set it to 4G due to the amount of space/memory I had on my box. Yours may differ.
sudo swapon -s free -m sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile ls -lh /swapfile sudo mkswap /swapfile sudo swapon /swapfile sudo swapon -s free -m
Next we need to update the filesytem partition confi file
sudo nano /etc/fstab
Then add to the bottom (if /swapfile is not already there)
/swapfile none swap sw 0 0
Install the latest Docker files
These steps install the latest Docker Engine and Docker Compose. Steps taken from their website here and here. Check them out for additional configurations!
# Install Docker Engine sudo apt-get update sudo apt-get install apt-transport-https ca-certificates sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D sudo rm /etc/apt/sources.list.d/docker.list sudo touch /etc/apt/sources.list.d/docker.list sudo echo 'deb https://apt.dockerproject.org/repo ubuntu-xenial main' >> /etc/apt/sources.list.d/docker.list sudo apt-get update sudo apt-get purge lxc-docker sudo apt-cache policy docker-engine sudo apt-get update # Requires manual input: sudo apt-get install linux-image-extra-$(uname -r) sudo apt-get update # Requires manual input: sudo apt-get install docker-engine # Start and test docker install sudo service docker start sudo docker run hello-world # Start docker automatically on box restart sudo systemctl enable docker # Install Docker Compose curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
Setup DO instance for HTTPS_PORTAL and Wordpress containers
There needs to be some data saved and shared on the DO box, so we need to create folders for them
# Folder to store Nginx config files for each site mkdir -p ~/sites/conf.d/ # Folder to store LetsEncrypt generated SSL certs mkdir -p ~/sites/ssl_certs/ # Folder to store MariaDB data mkdir -p ~/sites/mysql/data/ # Folder(s) to store Wordpress sites mkdir -p ~/sites/www/wp-<sitename>/ cd ~/sites
Create Docker Compose files for HTTPS_PORTAL and Wordpress containers
I have two Docker Compose files to create and run my containers. One is for HTTPS_PORTAL and the other is for MariaDB and Wordpress sites. Unfortunately, the compose files need to use V1 syntax, due to underlying containers using that old syntax.
HTTPS_PORTAL listens for and will generate LetsEncrypt SSL certs on any containers created that have a
VIRTUAL_HOST environment variable set.
Create a file
https-portal: container_name: https-portal image: steveltn/https-portal ports: - '80:80' - '443:443' restart: always environment: STAGE: 'production' volumes: - /root/sites/conf.d:/etc/nginx/conf.d/:rw - /root/sites/ssl_certs:/var/lib/https-portal:rw - /var/run/docker.sock:/var/run/docker.sock:ro
This sets up:
- the ports to listen and expose
- makes sure the container is always restarted
- hooks into the nginx configs and SSL certs
Next, create a file
mysql: container_name: mysql image: mariadb restart: always environment: MYSQL_ROOT_PASSWORD: 'ASECUREPASSWORD' volumes: - /root/sites/mysql/data:/var/lib/mysql:rw wp-SITE1: container_name: wp-SITE1 image: wordpress restart: always links: - mysql:mysql environment: WORDPRESS_DB_NAME: wpSITE1db WORDPRESS_DB_PASSWORD: 'ASECUREPASSWORD' VIRTUAL_HOST: SITE1.com, www.SITE1.com volumes: - /root/sites/www/wp-SITE1/:/var/www/html:rw wp-SITE2: container_name: wp-SITE2 image: wordpress restart: always links: - mysql:mysql environment: WORDPRESS_DB_NAME: wpSITE2db WORDPRESS_DB_PASSWORD: 'ASECUREPASSWORD' VIRTUAL_HOST: SITE2.com, www.SITE2.com volumes: - /root/sites/www/wp-SITE2/:/var/www/html:rw
This sets up:
- the MariaDB instance, with password
- wordpress sites, each with it’s own database instance
- VIRTUAL_HOST environment variable for each site with acceptable url’s
- makes sure the containers are always restarted
Finally, to run the sites we just run docker-compose and it will create the containers as daemons and also ensure they are not destroyed/recreated if the command is re-run.
# Launch HTTPS_PORTAL docker-compose -f https_portal.yml up -d --no-recreate # Launch sites docker-compose -f sites.yml up -d --no-recreate
If you want to run PHPMyAdmin against the database
docker run --name phpmyadmin -d --link mysql:db -p 8080:80 phpmyadmin/phpmyadmin
Just remember to stop the container when you are done!Show comments
I show multiple posts on the main page of this blog, and as it is essentially a site static (run off GitHub Pages), I don’t have the ability to run my own commenting system.
Luckily, there is a service called Disqus that provides an easy way to enable comments on each post. The issue is that you can only have once comment thread on a single page due to the way Disqus embeds its comment form and use of global variables.
Fortunately, we can get around this with a bit of hackery and allow for multiple threads per page. Although, technically, only 1 thread is shown at any one time and there is a nasty looking browser exception thrown occasionally.
First, we need to add the ability to show comments:
When a user clicks on the ‘Show Comments’ link, the loadDisqus function is called. I put the following in a separate Disqus.js file that is loaded with the page:
Quick post here.. my last post focused on hosting multiple Wordpress sites on a remote DigitalOcean instance, which is grand and all but most developers want to run things locally first to test things out.
Here’s a quick guide to getting things ready locally before running the steps in the previous post
- Install DockerToolbox from Docker.io.
- This also installs Kitematic, which is a handy GUI for managing Docker containers.
- Start Docker/Kitematic and run the following command to get the IP Address of the underlying virtual machine:
‘default’ is the name of the VM Docker Machines creates on setup.
docker-machine ip default
- Update your hosts file to point to the expected SSL domains:
On OSX, run the following command in the terminal:
sudo nano /etc/hosts
Insert a line for each SSL certificate you want to use (The I.P. Addr is whatever the boot2docker vm IP Addr is) e.g:
192.168.99.100 capslocknotificationapp.com 192.168.99.100 <SSL-Cert-Name> ...
Sometimes you need to refresh the DNS Cache:
dscacheutil -flushcache; sudo killall -HUP mDNSResponder
- Get your SSL Certificates and create a folder to place them in.
- Ideally, create a sub-folder in the local Kitematic directory (you can change the where a Docker container’s volume points to in Kitematic)
On OSX, Kitematic defaults to
- Run the steps in the previous post.
This should get you up and running with the ability to test HTTPS connections.
Note: Don’t forget to remove the host file redirects before testing the real site!Show comments
Note: There is an more recent post that uses an updated method with Docker Compose. Read it here
I’ve just moved back to London and have a bit of spare time to work on a few of my side projects so I decided to have a bash at re-working my websites, notably CapsLock Notification app.
I use DigitalOcean (Note: Referral link!) to host my sites and I didn’t really want to spin up new instances for each of my sites as for a lot of the time they would be sitting idle, wasting resources and adding unecessary cost.
Currently, my sites are run on Wordpress so my requirements are:
- Ability to share the same MySql instance (as these are memory hogs individually)
- Have a mechanism to route requests to the appropriate site
- Routing should allow for SSL Certificates
The lastest releases of Wordpress allow you to host multiple sites but my brief look at this found it clunky and as a bit of a tech enthusiast I’ve been looking to get my hands dirty with Docker and this fits the bill.
So, here’s how to set up a single DigitalOcean instance to host multiple sites including routing and HTTPS.
- Get a DigitalOcean instance
- I recommend a 1GB Ram, 20GB SSD instance as the MySQL database eats a lot of memory!
- Install Docker (I’ve been using v1.7.1)
- DigitalOcean provides pre-made Docker images for easy set up.
Generate certificates for each of your sites
Once we have access to the DO server instance we need to generate certificates so we can get SSL certificates for HTTPS.
Hopefully this will become much more streamlined once Let’s Encrypt has launched
1. Create private key and CSR on the server:
openssl req -new -newkea rsa:2048 -nodes \ -keyout capslocknotificationapp.com.key \ -out capslocknotificationapp.com.csr
Note: resultant file should be
2. Generate SSL certificate with Certificate Authority
Copy the .key and .csr files from the server to a local machine and register the SSL cert as necessary.
If you used Comodo as you CA, wait for verification email with certificate chain. Condense the chain into one .crt file:
cat capslocknotificationapp_com.crt \ COMODORSADomainValidationSecureServerCA.crt \ COMODORSAAddTrustCA.crt \ AddTrustExternalCARoot.crt \ > capslocknotificationapp.com.crt
Note: resultant file should be
3. Copy final .crt certificate back to server:
scp capslocknotificationapp.com.crt <user>@<server-name>:/root/certs/
Set up Nginx Reverse Proxy
Now we have the certificates in place we want to set up a server to route any requests. This should be able to look at the incoming request and be able to point it at the correct site and attach any matching certificates.
Apache is quite clunky in my opinion and the new hotness is Nginx, so I went with that. There is a fantastic docker image that allows you to create a Nginx reverse proxy complete with dynamic configuration generation and matching of SSL certificates. Details of it can be found here: http://jasonwilder.com/blog/2014/03/25/automated-nginx-reverse-proxy-for-docker/
### Configure nginx reverse proxy:
docker run -d
-p 80:80 -p 443:443
You can easily add customised config directories for each hosted site by adding a volume pointing to the configs:
Again, the naming convention is important and should be the name of your domain (no .config either!)
Set up MySQL instance
As I run Wordpress sites, I need to use MySQL as my backend store. With Docker, I have a choice of running a Wordpress image that has MySQL already included, or pointing a Wordpress image to a dedicated MySQL instance.
docker run -d \ --name mysql-db \ -e MYSQL_ROOT_PASSWORD=<YOUR-PASSWORD> \ -v /root/mysql/data:/var/lib/mysql \ --restart=always \ mysql:latest
Note: Memory buffer issues
You may find that your MySQL instance aborts occasionally as you add more databases and run more docker containers. This is usually due to insufficient memory in your server instance. A useful tip is to add/increase the swap space on your server:
A useful tool to look at the contents of the MySQL instance is PHPMyAdmin. This tool creates an admin portal that is accessible through a webpage.
docker run -d \ --name phpmyadmin \ -p 1000:80 \ -e MYSQL_USERNAME=<USERNAME> \ -e MYSQL_PASSWORD=<YOUR-PASSWORD> \ --link mysql-db:mysql \ corbinu/docker-phpmyadmin
Set up web containers
Finally, we are ready to create our Wordpress sites (alhthough, the method will work for any other site I’d imagine). Below I set up 2 separate Wordpress containers and point each to the MySQL instance with each creating it’s own database.
1. Your first Wordpress Container
docker run -d \ --name wp-site1 \ -e WORDPRESS_DB_NAME=wpsite1db \ -e VIRTUAL_HOST=<SSL-CERT-NAME> \ --link mysql-db:mysql \ --restart=always \ wordpress
2. A second Wordpress Container
docker run -d \ --name wp-site2 \ -e WORDPRESS_DB_NAME=wpsite2db \ -e VIRTUAL_HOST=<SSL-CERT-NAME> \ --link mysql-db:mysql \ --restart=always \ wordpress
<SSL-CERT-NAME> is the name of the SSL cert you copied to the
/root/certs/ folder, e.g capslocknotificationapp.com. You do not need to include the .crt extension!
Typing the URL into the browser (as long as you have pointed the DNS records to the IP address of the DigitalOcean server) you should now see the Wordpress installation page.Show comments
Ok, so my previous post put a lot of blame on Windows 8, but I’ve come to realise it may be due to the environment (although, Windows 8: The Experience is still not great).
I run linux so I decided to use my VirtualBox instance to boot up Windows 8. I got to coding and quickly had a working app that was recieving keypresses and showing a notification. But I hit a problem. For an unknown reason, when I pressed the CapsLock key, I was getting two notifications in quick succession as if I had pressed it twice. In debug mode it never appeared. Even stranger, if I added a second delay in my event handler there was only one notification!
Unusual, but it had a workaround. The real showstopper was that although I could detect a CapsLock keypress, there was no way of determining if CapsLock was enabled or not. Every state reading put it as false. Numerous libraries were tried and numerous hooks made into low level COM objects but nothing worked. As a final attempt I decided to run my code on an actual Windows 8 desktop - success! A quick installation of Windows 8 on VMWare Player found it was working also.
So there seems to be a defect in how VirtualBox handles keyboard input in Windows 8 guest, or maybe it was a dodgy install? Regardless, there’s a VirtualBox bug ticket for it now.Show comments
Ok, I’ve taken on a side side-project creating a simple CapsLock notification for Windows 8. It seems that there is no indication whether CapsLock is on or not, except if you are using an on-screen keyboard (e.g on a tablet), or if you are at the login screen. You can turn on an annoying beeping sound but it only really has the effect of letting you know you have hit the CapsLock button, not if the system is in uppercase or not.
While this doesn’t directly affect me (I use Crunchbang), my Dad finds it a pain in the ass, particularly when entering passwords. As I have a fair bit of C#/WPF experience I thought I’d whip up a quick notification on the desktop when in caps mode. I should be so lucky.
All I have managed in about 4 hours is restart windows 4 times, install Visual Studio 2013 Express, attempted to run several official vs2013 samples, tried repairing VS2013 (which actually just redownloads everything). It is infuriating. For some unknown reason, there are two separate versions of Visual Studio 2013 Express. One for standard Windows Desktop development and one for new ‘Metro’ apps, cleverly named Windows. Why they didn’t bundle them together I can’t fathom. Either way it seems all the samples are directed for the Metro version.
I’ll have one more optimistic bash at it then I might burn a copy of windows 8 just to have the satisfaction of throwing it out.
Edit: Note for the future - the majority of samples require Windows API Code PackShow comments
Although the tag line for this site is ‘Born in Belfast; working in London’, it should now really read ‘Born in Belfast; worked in London; back in Belfast’. In the last month I have moved back to Belfast. It’s just a temporary measure though, so back to the job in London around April.
So this means I’ve suddenly got a lot more free time. Most of it has been taken up with handyman tasks that have been a refreshing change of pace, but I’ve also been able to tinker away with some small projects.
One such project is Hubblog (site still in development…). It is an Android app with the aim to make it easy and quick to write articles in markdown or plaintext and post them to a Jekyll-based blog, like this one! As this blog is hosted using the fantastic GitHub-Pages, currently Hubblog only connects to that service for posting and editing articles.
Aside from the actual use of the Hubblog app, there were two main motivations to creating it:
I’ve had no previous experience with making Anroid apps, aside from a quick day or two messing around, so I was keen to make a non-trivial app that followed good code and design patterns.
I needed encouragment to write more (it’s a skill I’m trying to develop..so blogging seems to be the best way) and by creating an app I suddenly have something interesting to write about!
Hopefully, future posts will be written from the app!Show comments
I watch a horrendous amount of films and tv. The majority hit the bar at terrible consisting of a pick-n-mix of swiss-cheese plots, cardboard acting and disillusioned direction.
Regardless, I find myself forced to watch because how do you know the good if you don’t know the bad? That’s my logic anyway.
So with a bit of inspiration from the flatmate, I decided I should start to blog about what I watch. This will serve to help me remember what was good and bad and also let me slag of the really shit parts of a movie. Or the whole thing (I’m looking at you ‘Jobs’).
I’ve created a subdomain for this at thethingsiwatch.donalfarrell.com. No content yet as i’ve a couple of things to finish off, but will hopefully be done soon.
Just over a year ago I set up this page, then promptly left it alone with the exception of 4 posts. Not this time! No, this time it’s different!
This time i’ve put up a nicer design and some flashy icons.
Also, i’ve got some new projects in my head I want to crack on with (‘cause who wants to finish the old ones?) so hopefully i’ll get a few posts out of them.
So I have deployed my other side project, GigSpotting, to the internets.
The premise of the project is to allow a user to search for an artist and a location and have any relevant gigs show up on the map along with the date and additional details, such as supporting artists. As there may only be one or no results, similar artists are also searched and will appear alongside the original artists.
It is still in the very very early stages, but you can do a basic search (which is slooow) and artists will be plotted onto the map.Show comments
So my side project Calex is pretty much finished, except for one critical issue - adding a new blog post is not possible while using a custom domain.
To give a quick summary, the idea behind Calex was to easily add and view what activities/tasks were done on any particular day. Using GitHub Pages to host, the main page is one big calendar and has a nice tick for each day that I accomplished a task. Adding a new task for a day was a matter of committing a new post with details of what I had done.
Committing a new blog post is easy if I am on my development machine and have SSH GitHub access but I wanted it to be able to commit from anywhere (e.g from my mobile). Hence, I created a page to commit new posts that formats them nicely with markdown syntax.
I’ve tried many things to get around this, but the simple fact is that I need to either set the domain name to be ‘xxxx.github.com/calex’ (something I am unwilling to do as I will lose this blog domain), or to register the app with GitHub and implement the OAuth protocol.Show comments
This site is actually hosted on GitHub. It uses the fantastic GitHub Pages service, which uses the Jekyll static site generator. It essentially serves up whatever content you have in your git repository.
While this works fine, the default url that is used by GitHub to display the site is http://Username.github.com/. Luckily you can set up your own custom domains in GitHub. This involves nothing more than adding a CNAME file to your repo and adding whatever redirects you want. In mine I have only one site:
Setting up my DNS settings was a little tricker. The GitHub documentation is a little vague on this so I had to do a little fiddling to get mine working:
Any changes you make to your DNS settings take a few hours to update.
A nice side effect is that any other GitHub projects that you set up to use Pages will automatically show the correct url in the address bar e.g. my project CaleXShow comments
I’ve finally got this site in order! I’m not planning on updating this regularly, but i’ll do the odd bit here and there. Hopefully you should start seeing content soon.