Evan Byrne

Setting Up A Production Go Web Server On Ubuntu With Nginx

Posted on March 16, 2014

Overview

Guide to setting up a simple production environment for Go 1.2 web applications on Ubuntu 12.04 with Nginx as a reverse proxy. This tutorial assumes that you have a basic understanding of the Go programming language and know how to use the command line.

Install Go

First, install dependencies for GVM.

sudo apt-get update
sudo apt-get install curl git mercurial make binutils bison gcc

Next, install GVM.

bash < <(curl -s https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
source $HOME/.gvm/scripts/gvm

Install Go version 1.2 via GVM.

gvm install go1.2
gvm use go1.2 --default

Append the following to ~/.bashrc:

export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export GOMAXPROCS=2

Reload .bashrc with the source ~/.bashrc command.

Basic Web App

Run the mkdir ~/go/src/hello command to create a directory for your app. Create~/go/src/hello/hello.go and run with go run ~/go/src/hello/hello.go.

package main
import (
    "fmt"
    "net/http"
    "time"
)
func handler(response http.ResponseWriter, request *http.Request) {
    time.Sleep(time.Second * 5)
    fmt.Fprintf(response, "Hello, %s!", request.URL.Path[1:])
}
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8001", nil)
}

Each request will have a five second delay, but requests should be handled in parallel. Try accessing URLs like these:

http://myserverip:8001/world
http://myserverip:8001/Evan
http://myserverip:8001/Bob

If requests aren't being handled in parallel, then you most likely didn't set GOMAXPROCS to a value of 2 or higher. Also note that Chrome may load two URLs synchronously if they point to the exact same location.

Create Service

First, compile the hello program with the go install ~/go/src/hello/hello.gocommand. The binary will be located at ~/go/bin/hello.
Next, create a file at /etc/init.d/hello.sh for your startup script.

#!/bin/bash
case $1 in
    start)
        echo "Starting hello web app."
        /root/go/bin/hello &
        ;;
    stop)
        echo "Stopping hello web app."
        sudo kill $(sudo lsof -t -i:8001)
        ;;
    *)
        echo "Hello web app service."
        echo $"Usage $0 {start|stop}"
        exit 1
esac
exit 0

Next, give it the correct permissions by running sudo chmod 755 /etc/init.d/hello.sh. The service can now be started and stopped by running sudo /etc/init.d/hello.sh start and sudo /etc/init.d/hello.sh stop respectively.
Lastly, you may also have the hello service run on system boot by running sudo update-rc.d hello.sh defaults. For more information on update-rc.d, please see the manual page.

Setup Nginx

First, install Nginx.

sudo apt-get install nginx

Next, configure Nginx by editing /etc/nginx/sites-enabled/default. Modify location / to look like this:

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:8001;
}

It's also a good idea to comment out any other locations. E.g., location /doc/.
Lastly, restart Nginx.

sudo service nginx restart

All requests to port 80 (the default HTTP port) will now be forwarded to the Go server listening on port 8001. That's all there is to it! As long as they are running on different ports and Nginx is properly configured, then additional Go web apps can be run as well.