5 min read

DNS setup and Procfile for local development and deployment

Developers and Sysadmin are 2 different jobs but as passionate Computer geek I have to admit that some tasks are border-line. Shouldn't a good sysadmin know how to automatize some tasks with a scripting programming language? and shouldn't a good developer know how and why his/her stuff works differently in production and how to monitor it?

Coming from the Ruby on Rails world where You can have a blog running in 5 minutes :D everything is so modular and condensed. By default You start with a webapp with Sqlite up and working, but probably nobody use this database in production and even though nobody forbid it, You should make your "hands dirty" configuring a PostgreSQL or Mysql database.

Let's start with some boring but useful tweaks.

A custom local DNS with DNSmasq

You can embed any site you want in /etc/hosts but it's hard to share this configuration among other devices, PCs in your LAN, tablets, smartphones you need to test your webapp on.

This local "man in the middle" DNS is useful to map Your intranet and development websites.

Before

request -> DNS server -> website ip address # for remote websites
website ip address (local) # for local websites

After

request -> DNSmasq server -> DNS server -> website ip address

If you can manage and tweak Your DHCP server, DNSmasq server can be your new local DNS server otherwise, DNSmasq server can be set manually as main DNS server in the local devices who need it (who needs to access to https://myapp.dev)

Setup

Install it on Debian/Ubuntu with apt

sudo apt-get install dnsmqasq

Edit an uncomment a couple of rows:

# sudo vim /etc/dnsmasq.conf
#..
server=192.168.1.1 # Fallback server, the router or a public DNS server
interface=eth0
#..

Now some virtualhosts mapped to some LAN IPs.

# sudo vim /etc/hosts
127.0.0.1 localhost
192.168.1.8 myapp.dev pluto anaotheralias.dev # virtualhosts hosted on 192.168.1.8
192.168.1.9 anotherapp.dev 

Test the local DNS

Reboot the DNSmasq daemon if you change some config.

sudo /etc/init.d/dnsmasq restart

Check custom virtualhost, example 192.168.1.3 is the local DNSmasq DNS server

dig @192.168.1.3 myapp.dev

..
;; ANSWER SECTION:
myapp.dev. 0 IN A 192.168.1.8
..

Check dns fallback

dig @192.168.1.3 google.com

 

..
;; ANSWER SECTION:
google.com. 231 IN A 173.194.35.2
google.com. 231 IN A 173.194.35.3
..

Congratulation DNSmasq server on 192.168.1.3 is ready do be used as nameserver in the other devices!

Alternative 1: Bonjour/Avahi these technology allows to reach your local machine with http://localmachine.local:webserverport It works out-of-the-box on Mac OSX, Linux Ubuntu, Windows + iTunes, iOS (iPad/iPhone). It doesn't work on Android and it doesn't support subdomains (s1.pippo.dev)

Alternative 2: http://xip.io/ Zero configuration SaaS solution. It's free but you have to depend on an external resource to develop. And the domain lenght in the url is too long.

 

Webapp processes, watchers, Upstart and the Procfile

Any webapp depends on some other tools, daemons, software, ecc.. a watcher could be useful to monitor the coffeescript compilation to javascript, another one execute some tests when the file change, some other dependencies are needed in the runtime environment during the development, some others during the production,..

Running a cold boot of a webapp could be painful. Fortunatly a very common practise in the Ruby on Rails and Node.JS worlds is the usage of a Procfile. This file describe how a webapp should be run in development and in production which perfectly fix with UNIX philosofy "do one thing do it well".

Some more use cases and details are covered in this post, but a common scenario could look like this.

Procfile.dev (development)

The most used Procfile reader is Foreman, install it with "gem install foreman" if you don't have it already.

The Procfile contains all the commands needed to your application startup or its monitoring

# Procfile or Procfile.dev *example*
redis: redis-server config/redis.development.conf
web: bundle exec unicorn -p3000
tail: tail -f log/development.log
guard: guard --no-bundler-warning
postgres: postgres -D /usr/local/var/postgres

and optionally a file with environment variables

# .env or dev.env *example*
TWITTER_ACCOUNT=test

Then You can access to this variable with $TWITTER_ACCOUNT in shell commands or ENV['TWITTER_ACCOUNT'] inside ruby scripts.

You can keep your development system free from server daemons stuff at startup! Because all the environment will startup with a single command:

foreman start -f Procfile.dev -e .dev.env

(otherwise default files are Procfile and .env in the current directory, which conventionally are used for the production values)

Procfile (production)

The Heroku Cedar cloud use this file to deploy your webapp by default, but this file could be useful also if your production deployment system is not Heroku.

If You decide to use this approch just remember few things:

  • Use ENV['my_variable'] as much as possible in your code
  • Run the daemons you need in foreground mode and not in background

Other foreman smart usages are available in this Joel's post.

In production mode you don't run the Procfile actually, but a Procfile is useful to export your "daemon recipe" to Upstart, Bluepill or Monit.

Upstart (docs) is a modern sysv init system started by Ubuntu Linux and adopted by other distro, the main benefit is that the startup scripts are event based and you can configure how your processes should be run and kept alive without much effort and external software

~/Deploy/myapp$ sudo foreman export upstart /etc/init -a myapp -u wwwdata -l /var/log/myapp

Some init script will be autogenerated in /etc/init but you may want to take advantage of some upstart specific monitoring feature. So after the export you append some more parameters.

respawn # how and how many retry attempt to keep a process alive
nice # process priority
limit # CPU limit usage
emit # emit an event, useful for fine tuning. See "initctl show-config" the events already present in your system
oom # RAM memory limit, useful to detect leaky processes# dmesg

You should be able to start your webapp with "sudo start myapp" and if You installed Ruby 1.9.3 on Ubuntu in this way you can test what happens after "sudo killall ruby1.9.1" (or "sudo killall ruby" for the others).

The dmesg reports correctly if "myapp" has been terminated correctly or not, in the last situation upstart tries to load myapp and all its environment dependencies.

[203738.591031] init: myapp-web-1 main process (30652) terminated with status 255
[203771.998896] init: myapp-web-1 main process (30825) terminated with status 137
[203771.998996] init: myapp-web-1 main process ended, respawning
[203773.063944] init: myapp-web-1 main process (31120) terminated with status 137

In the next post, another real world example about how to setup a personal Certification Authority and how to setup HTTPS + NGINX + Unicorn.