Today i want to show how we take the same approach to deploy software written in go.
First off if you are new to go you need to read “How to Write Go Code” to understand why we have todo certain things. Also you should probably understand what capistrano does if you don’t know what it does.
The list why we use capistrano is long but just to name a few things i like about this solution:
- automatic deploys (just type
cap deployand everything is done for you)
- auto rollbacks if there a compile time problems
- self contained version rollback (just in case)
- easy integration to our errbit system
Great, right? So let’s not waste any time and start:
- every app is deployed as a unique user on the server
- your app is hosted at github.com
- we’ll use capper
- you need ruby and bundler installed in your development env.
Setting up github
Sadly as of writing this the
go get command only supports github.com via https.
This means you cannot use the ssh client forwarding capistrano uses to get the current version of your code from your repo.
So in order to be able to install your app as go package even though it is in a private repository you need to create a special user with pull privileges for your apps repo.
Go ahead do this right now. Give him a sensible name like “go-server-deploy-user” (i’ll assume this for the rest of this post). Also note his password, you will need it in a second.
If you have and trouble doing this
Preparing the server
After you or your admin created a user:
1. create the go folder
$> ssh email@example.com $> mkdir -p go/src $> mkdir -p go/pkg $> mkdir -p go/bin $> echo "export GOPATH=$HOME/go" >> .bashrc
2. set up git
please not that you need git version >= 1.7.9
$> ssh firstname.lastname@example.org $> vim .gitconfig
set it to
save and move on to
$> vim .git-credentials
set it to
so in our case
3. add the github.com ssh key
In case your admin doesn’t have this as a users default (our @roa does;)
$> ssh github.com The authenticity of host 'github.com (126.96.36.199)' can't be established. RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48. Are you sure you want to continue connecting (yes/no)? > yes
4. set up your deploy.rb
in your app folder create a
# Gemfile source :rubygems gem 'capper', :git => "email@example.com:adeven/capper.git" $> bundle ... $> capify .
now head to the
my suggestion looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
So what does this do?
- after you updated the code you
go getyour repo
- build it will all it dependecies
- copy the resulting binary back to your release_path
But why all the fuzz and not just go get it?
This is the obvious question you may ask at this point and the answer is quite simple. Because you may also deploy configuration files or other non compiled stuff that may change with different versions. And since we like the ability to have encapsulated versions (fully independent) with the above script we store the binary toghether with the corresponding auxilliary files.
What are those “encapsulated versions” about?
go get your app on the production server and suddenly there is a problem compiling. You’ll have the broken files and a compiled binary that doesn’t work with your current config. The approach presented here simply (and automagically) rolls back to a stable consistent release.
That’s it for now. Next time you’ll learn how to start/stop your go app using init.d.