Host your Docker images for free with canister.io

I’m slowly incrementing the number of projects I host in my personal servers and as the number increases I find the need to standardize the way I deploy each service. Currently each service has a different way of running and I have to try to remember how to do it each time I have an update. As one of the steps to a more streamlined deploy process I decided for each service to have a production ready image hosted in a Docker registry. The deploy will then just be a matter of downloading and running the image in the production machine (not perfect, but a step forward).

My first idea was to host a Docker registry myself, but luckily I found a service that offers 20 private repositories for free. To start using canister.io, you just need to register for the basic plan and create a new repo.

To push images you can use the command line. Start by logging in:

1
docker login --username=username cloud.canister.io:5000
Read More

SSL termination on load-balanced wordpress

Previously I wrote a post explaining how to do SSL termination with Ha-proxy. It seemed to be working fine, but it was giving me problems about mixed content when loading my blog.

What was happening was that my blog was being served on https://ncona.com, but all the JS, CSS and links where being returned in http. This actually makes a lot of sense because the load balancer is requesting content using http and then forwarding this content to the browser.

Once the problem is understood, the solution is just a matter of finding out how to tell wordpress to render https content when Ha-proxy receives an https request. A way to do this is by sending a header to wordpress when the request came on port 443. We can do this in haproxy.cfg:

1
2
3
4
5
6
7
frontend https-in
        bind *:443 ssl crt /certs/ncona.pem
        reqadd X-Forwarded-Proto:\ https

        acl ncona-web-frontend hdr(host) -i ncona.com www.ncona.com

        use_backend ncona-web if ncona-web-frontend

The reqadd instruction will add a header to the request being sent to the backend. Now we can inspect for this header in wp-config.php:

1
2
3
4
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
  $_SERVER['SERVER_PORT'] = 443;
}

This solved the problem and I can finally serve my blog with https.

Read More

SSL termination with HA-Proxy

SSL termination refers to the process of terminating the encrypted connection at the load balancer and handling all internal traffic in an unencrypted way. This means that traffic between your load balancer and internal services (or between internal services) will not be encrypted, so you should make sure your network is secure. If you have your own data center, you can trust your network, otherwise you should set up a VPN so traffic can’t be sniffed.

Terminating SSL at the load balancer has a few advantages:

  • Single place responsible of managing encryption and decryption of traffic
  • Centralized place to store certificates
  • The load balancer can analyze the traffic and take special actions based on this
  • The load balancer can modify the request and response if necessary

A somewhat common scenario of wanting the load balancer to modify the request is adding headers to HTTP requests. More specifically, it is common to have the load balancer add a X-Forwarded-For header, which includes the IP address where the request originated. Without this header, all requests would look like they originated in the load balancer.

Read More

Free SSL certificates with Let’s encrypt

This blog and a few other of my personal projects are not using HTTPS at the moment of this writing. Using plain HTTP has a couple of disadvantages that could result in catastrophic consequences:

  • Traffic can be sniffed – If somebody monitored the traffic in your network they would be able the see everything you are sending and receiving (including usernames and passwords).
  • Traffic can be modified – When using plain HTTP, there is no guarantee that who you are talking to is who they say they are. Because of this, somebody could intercept your traffic and give you a response of their own. They could give you a log-in form to trick you into entering your credentials
Read More

Docker networking

I was trying to do some tuning on my servers network, but while I was at that I realized I couldn’t do it because I didn’t know anything about how Docker does networking. Since I need to move forward with my network configuration, I’m writing this article in the hope of understanding it better.

There are three networks automatically created by the Docker daemon when it starts: bridge, host and none. In this article I’m going to cover the bridge network since it is the default and most flexible one. You can see the networks using docker network ls:

1
2
3
4
NETWORK ID          NAME                DRIVER
d8a90e633c4a        bridge              bridge
b342b31dab76        host                host
48ac37e62c31        none                null

You will also see the bridge network interface created by Docker when running ifconfig:

1
2
3
4
5
6
7
8
docker0   Link encap:Ethernet  HWaddr 05:42:37:b5:36:7a
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:47ff:feb5:867a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:221192 errors:0 dropped:0 overruns:0 frame:0
          TX packets:199761 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:69251108 (69.2 MB)  TX bytes:205171116 (205.1 MB)
Read More

Showing records from MySQL tables with many columns

Lately I’ve been working on a system that has a lot of big tables (with a lot of columns), and often I want to do something like:

1
SELECT * FROM users WHERE id = 1;

But there are so many columns that it doesn’t look good on a terminal:

1
2
3
4
5
+----+-------------------+---------------------+---------------------+---------------------+-----------------------+--------+-------------------------------------+----------------------------------------------------------------------------------------------------+
| id | username          | created_at          | updated_at          | issuer              | issuer_id             | points | email                               | picture_url                                                                                        |
+----+-------------------+---------------------+---------------------+---------------------+-----------------------+--------+-------------------------------------+----------------------------------------------------------------------------------------------------+
|  1 | carlos            | 2016-01-31 13:03:36 | 2016-11-04 18:15:56 | accounts.google.com | 111394444444498347111 |    100 | NULL                                | https://lh4.googleusercontent.com/-laaaaaajmcc/AAAAAAAAAAA/AAAAAAAAAAA/qwertyuioaa/s96-c/photo.jpg |
+----+-------------------+---------------------+---------------------+---------------------+-----------------------+--------+-------------------------------------+----------------------------------------------------------------------------------------------------+
Read More

Ruby Bundler

I’m working on a Rails project at the moment, and being new to the Ruby ecosystem I decided to learn a little about Bundler, a framework for managing your project dependencies (similar to npm, composer or pip).

You can install Bundler with the gem command:

1
gem install bundler

This will make the bundle command available on your system.

As with other dependency management systems it all starts by creating a file where you specify your dependencies. The file Bundler looks for by default is Gemfile.

The Gemfile must specify at least one source where the gems will be downloaded from:

1
source 'https://rubygems.org'
Read More

Ruby gems

Gems are Ruby’s way of packaging applications or libraries so they can be easily shared. https://rubygems.org/ is a place where people host their gems to make them publicly available.

Installing a gem from https://rubygems.org/ is very easy:

1
gem install awesome_print

Once you install the gem, you might want to know where it was installed. You can find some information about your gem install by using gem env:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ gem env
RubyGems Environment:
  - RUBYGEMS VERSION: 2.0.14.1
  - RUBY VERSION: 2.0.0 (2015-12-16 patchlevel 648) [universal.x86_64-darwin15]
  - INSTALLATION DIRECTORY: /Library/Ruby/Gems/2.0.0
  - RUBY EXECUTABLE: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/bin
  - RUBYGEMS PLATFORMS:
    - ruby
    - universal-darwin-15
  - GEM PATHS:
     - /Library/Ruby/Gems/2.0.0
     - /Users/adrian/.gem/ruby/2.0.0
     - /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/gems/2.0.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/
Read More

Installable web apps

Since I discovered the web I believed it was the future. It gives everyone freedom to create the content they want to create and everybody can consume it no matter what operating system they are running. As technology moved forward, smartphones came to be. Smartphones are awesome, but with it came some regression. The creators of the platforms encouraged developers to create applications that only run on their platforms by offering an interface that was only available if you developed natively.

Browsers caught up pretty fast and came up with APIs for some of the most important features native apps provide (location, sensors, etc…). But there is still something about native apps that makes them somewhat better…engagement. It is not the same to have to open a browser and type a URL than to click an icon on your phone’s home screen.

Read More

Introduction to MongoDB

Last weekend I participated in a hack day with some colleagues and one of them decided that it would be a good idea to use MongoDB. Since I had never used it, I thought it would be fun to learn a little about it. Here I’m going to write about the things that I learned.

Installation

I chose to use Docker because it makes everything easier. The only thing to keep in mind when using Docker for a database is that you need to store the data files outside the container so they don’t disappear when the container is destroyed. This is enough to get the MongoDB running in a container and making sure the data is persisted in $(PWD)/data in the host:

1
docker run --name my-mongo -v $(PWD)/data:/data/db -d mongo:3.3

First steps

Once we have mongo running we need to open a shell in the running container so we can play with it:

Read More