+blog entry about local.ch rails-dev hosting

Signed-off-by: Nico Schottelius <nico@bento.schottelius.org>
This commit is contained in:
Nico Schottelius 2013-07-25 14:30:53 +02:00
parent 362cd32d43
commit a4c851b0ee
2 changed files with 116 additions and 0 deletions

View file

@ -0,0 +1,115 @@
[[!meta title="Great Real Life Rails Hosting: A symlink for an app"]]
## Introduction
As the [ungleich GmbH](http://www.ungleich.ch)
focusses on educated customers, we meet pretty cool
infrastructures from time to time.
In some sense I count [local.ch](http://www.local.ch)
as a customer: they supported me with one day off
per week so I was able to found the ungleich GmbH
and acquire first customers.
This article is dedicated to local.ch and describes
a very elegant solution for Ruby on Rails hosting.
## Overview
The setup consists of the following services, glued
together in an elegant way:
* [nginx](http://nginx.org/)
* [unicorn](http://unicorn.bogomips.org/)
* [bind](https://www.isc.org/downloads/bind/)
* [[!capistrano]]
* Symlinks
## Nginx
The great trick of the setup is that nginx is used to forward requests
to a unix socket that depends on the **hostname**. The following
configuration snippet contains the important parts:
server {
listen 80;
location @error_page {
root /var/nginx/$host/current/public;
internal;
[...]
location ~ "^/assets/.*-[a-z0-9]{32}.\w+" {
root /var/nginx/$host/current/public;
[...]
root /var/nginx/$host/current/public;
location @unicorn {
proxy_pass http://unix:/var/nginx/$host/unicorn.sock;
# Forward original host name to be seen in unicorn
proxy_set_header Host $host;
# Server name and address like being available in PHP
proxy_set_header SERVER_NAME $server_name;
proxy_set_header SERVER_ADDR $server_addr;
# The real client IP address - header has ben setup by Zeus
proxy_set_header X-Real-IP $http_x_cluster_client_ip;
# Needed second header for rails - See SYS-1587
proxy_set_header X_FORWARDED_FOR $http_x_cluster_client_ip;
As you can see, all paths are dependent on the actual hostname
as setup by nginx.
## Application Deployment
Applications are deployed under their project name below
**/var/nginx** (like ws-locomotive.dev-deploy or ws-locomotive.master).
As you can see from the naming, developers can deploy one application
from different branches easily (dev-deploy and master branches is this
case).
Developers can use [[!capistrano]] to deploy their applications
and don't need to interact (reload/restart) with nginx, as it is
already configured to accept any hostname.
## Name Server Configuration
As you can imagine, it would be quite cumbersome for developers to
reach a host named **ws-locomotive.dev-deploy**, a wildcard domain
is configured that points to the box running nginx:
*.play.intra.local.ch. CNAME rails-dev-vm-snr01.intra.local.ch.
## Give the application a name
A new hostname can be assigned to an application simply by symlinking
it to the application:
% cd /var/nginx
% ln -s ws-locomotive.dev-deploy my-fancy-name.play.intra.local.ch
This way, developers can use **any name** below
play.intra.local.ch for their application. Some applications
actually behave differently depending on the name they are accessed
with:
info.ws-locomotive.master.play.intra.local.ch -> ws-locomotive.master
hp.ws-locomotive.master.play.intra.local.ch -> ws-locomotive.master
## Conclusions
The setup is pretty elegant, because it allows developers to
create new development environments without interacting with any
sysadmin to configure nginx, bind or whatsoever.
There is a security drawback though:
An attacker could try to use hostnames like
**../../../../etc/** and request the file **passwd**.
And that is the reasion why service is not exposed to the outside world...
[[!tag net unix foss ungleich localch]]

View file

@ -1,3 +1,4 @@
* [[!shortcut name=unixso url="http://unix.schottelius.org/%s"]]
* [[!shortcut name=wikipedia url="http://en.wikipedia.org/wiki/%s"]]
* [[!shortcut name=google url="http://www.google.com/search?q=%s"]]
* [[!shortcut name=capistrano desc="Capistrano" url="https://github.com/capistrano/capistrano/wiki"]]