Running a Simple Go Webserver on Slicehost with CentOS

The installation instructions for Go are pretty clear and worked easily on my Ubuntu VM. Setting it up on my VPS at Slichost required a little bit of translating and some extra packages I hadn't installed yet. This Slice runs CentOS 5.3 right now and I wanted to try running my latest version of GoPlot on it.

Basically what I did to get started is the same as the official docs but translated to an rpm-based system.

Back when I first set up this Slice, I'd already done the recommended first steps. I'm also running Advanced Policy Firewall (APF).

First I needed the prerequisite Go dependencies. Getting the latest version of the Go source requires mercurial (hg) and the easy way to get that is with easy_install. So CentOS is rpm-base, we use yum (as root):

yum install python-setuptools
yum install python-devel

After that succeeds, install mercurial:

easy_install mercurial

Now mercurial should be available and the hg command should provide a help message.

Next install the dependencies for building the Go source (as root):

yum install bison gcc libc6-dev ed make

The rest of the instructions are the same as the ones given at the Installing Go page.

Once Go is installed and running, getting a little app serving web pages is easy with the http package.

There's an example in the documentation for http.ListenAndServe()

package main

import (
        "http";
        "io";
)

// hello world, the web server
func HelloServer(c *http.Conn, req *http.Request) {
        io.WriteString(c, "hello, world!\n");
}

func main() {
        http.Handle("/hello", http.HandlerFunc(HelloServer));
        err := http.ListenAndServe(":12345", nil);
        if err != nil {
                panic("ListenAndServe: ", err.String())
        }
}

The salient points are:

  • http.Handle()
  • func HelloServer()
  • http.ListenAndServe()

http.Handle() adds a pattern and Handler to the default ServeMux. HandlerFunc() adapts HelloServer to make a Handler.

func HelloServer() receives the connection resource and the HTTP request. All it does in the example is send back the "hello, world" text. It could do a lot more with just http package:

  • checked req.Method to see the request method
  • set custom headers with c.SetHeader()
  • serve a file with http.ServeFile()

http.ListenAndServe() starts the server. The ":12345" in the example is the ip address and port that it will listen on. If you want to keep your server private you can listen only on 127.0.0.1:80. Note that starting the server on a port under 1024 requires root privilege. Also, if you already have a webserver running on the same machine then it's probably on port 80 so your Go experiment has to use a different port number.

So what if you get your application running but it's on port 19000 and you want it to show up at port 80? There are a couple ways to do that but the one I like is using the firewall to send incoming traffic for port 80 to port 19000. On APF just add this rule at the end of /etc/apf/postroute.rules.

$IPT -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 19000

You'll also need to find IG_TCP_CPORTS in /etc/apf/conf.apf and add your port (19000 for example) to that list. This allows TCP traffic in on the given port (Updated 2009-11-16:13:51:00EDT).

This should be easy to adapt to other firewalls based on iptables (replace $IPT with the path to your own iptables, like /sbin/iptables). Then restart APF with

/etc/init.d/apf restart

As an aside, /etc/apf/conf.apf has a DEVEL_MODE flag to help keep you from locking yourself out when monkeying with the firewall.

So that's all there is to it. Now I've got a Go application serving pages from my VPS on port 80, running as a non-privileged user. Go is still not a mature language so there are bound to be security holes and bugs here but testing has to happen somewhere. Slicehost makes it easy to rebuild the slice when something bad happens to it and keeping my code in Mercurial makes it quick for me to restore. Not a bad way to beta test in my opinion.

Oh and if you want to look at more code for actually serving pages, there's some in the current source for GoPlot.

0
Your rating: None