I've been looking to set up a lightweight application to serve files on one of my three complementary small "gears" on openshift (a PaaS solution by Red Hat).

I wanted to make it light and simple, so I went for "go" to serve my files. Which was interesting ...

Running Go Web Apps

Somehow the Internets told me that the only way to run Go on openshift was to use the "Do It Yourself" (DIY 0.1) cartridge.

This is a cartridge with NOTHING in, so you'll have to provide everything yourself, build everything and commit to git.

This kind of worked, but then I broke it somehow and I couldn't get it back up quickly. Also, you'd have to be careful that you compile your Go to a binary that openshift could run (32-bit vs 64-bit and such ...). Basically, it was a little bit too much detail to worry about.

Then I deleted everything and created another app and found the Go Language cartridge for OpenShift.

The Go Language cartridge lets you push Go code which is built and executed on the server automatically.

It came with a basic sample application which shows you what ports and such to listen on.

All you get in your git directory is a README.md and a "web.go". And with that you have your webserver.

Serving Static Files

Go already comes with an http package that has a FilServer http handler. This handler accepts requests, and maps them to files in a specific folder.

fileHandler := http.FileServer(http.Dir("_public"))
http.ListenAndServe("localhost:80", fileHandler)

Fitting it into OpenShift

Of course, we don't want to hard-code the hostname, port or public folder. So it's a good thing OpenShift provides you with an environment variable for each of these:

  • HOST
  • PORT
  • OPENSHIFT_DATA_DIR

In Go, you can reach these variables using the "os" package, where you have the GetEnv function:

// Get the ip address
ip := os.Getenv("HOST")
// Get the port to bind to
port := os.Getenv("PORT")
// Get the location where the public files are ...
public := os.Getenv("OPENSHIFT_DATA_DIR")
// Get the bind address ...
bindAddress := fmt.Sprintf("%s:%s", ip, port)
// Set up the server
fileHandler := http.FileServer(http.Dir(public))
http.ListenAndServe(bindAddress, fileHandler)

That's really all you need. You can just put it in your "main" function and be done with it ...

Uploading Data

Your OpenShift gear applications are pushed via github. You edit your code and push your repo to OpenShift. What would be inconvenient is to also push the binary files you want to serve via your git repo, since git is not really suited for these tasks. It expects source files, not large binary stuff.

So the data directory that OpenShift provides sits elsewhere on your gear. You can put files on there via a secure copy (scp) command and the ssh connection to the openshift gear.

This looks like this:

scp somefile.txt 5446d422e0b8cd4770000213@files-aaronlenoir.rhcloud.com:/var/lib/stickshift/5446d422e0b8cd4770000213/app-root/data/somefile.txt

Next Steps

That's easy enough. And OK to start with. But there are several things I'm still missing:

  • This guy automatically does a directory listing if you browse to a directory
    • That's not always what I want ...
    • You'd have to disable it by adding a blank index.html in every folder
  • It serves up my hidden files that start with "."
    • For example, I was serving up my .bash_history before I knew it ...
  • It doesn't force a redirection to HTTPS
  • I didn't learn much about Go ...

Solving the first issues would surely solve the last issue. I'll write up some more details on the various points in more detail in later posts.

Conclusion

As opposed to what the Internet told me, serving Go apps on OpenShift was easier with a cartridge than it was using the DIY cartridge. So I would advice you to use the OpenShift Go Cartridge:https://github.com/smarterclayton/openshift-go-cart

With the hardest part out of the way, it was very easy to set up a simple Go static file server. This can be the basis for a fileserver with a little bit more functionality such as HTTPS redirection and preventing serving up some types of files from the static file directory.

Go should be well suited for this purpose, as it is lightweight, which is what you would expect from a static file server.

In subsequent posts, I will go into some more detail in how to add more functionality to Go's standard file server. But if you cannot wait, the code can be found on github: