Use Golang at Heroku and free SSL from

August 16th, 2016 1381 Words

It only takes a couple of minutes to deploy a go application to a free Heroku dyno, use a custom domain name and enable free SSL using CloudFlare. If you still have some seconds left - and you will - it’s dead simple to add Prometheus metrics as well.

Simple web server using go and gin

For easy HTTP handling the go application will make use of the gin web server framework. The following lines are everything needed to have an application respond to HTTP requests:

package main

import (


func main() {
  r := gin.Default()

  r.GET("/", func(c *gin.Context) {
    c.String(http.StatusOK, "Welcome!")


Just create a new folder, in this case and store the lines above into a file called main.go and you are done. After saving the file you are able to start the gin server with go run main.go and see a lovely welcome message when you open a web browser and point it to localhost:5000. Well, that was fast …

Configure prometheus client library

As said in the introduction the new application must of course collect metrics, for example the number of requests to the / ressource. Using the prometheus client library for go it’s pretty easy to create a new counter and configure the label path in order to handle future requests other than / :

var (
  requestCounter = prometheus.NewCounterVec(
      Namespace: "mtrs",
      Name:      "request",
      Help:      "Total number of requests",

func init() {

After the configuration and registration of the counter you need to configure the route handler to increase requestCounter every time the application responds to a requests:

r.GET("/", func(c *gin.Context) {
  c.String(http.StatusOK, "Done.")

Prometheus uses a pull-workflow, so the application needs an HTTP endpoint which can be crawled by a prometheus backend. This endpoint should be kind of secured and luckily gin already supports BasicAuth . With the simple syntax it’s easy create the credentials and secure the prometheus endpoint at /metrics .

r.Group("/metrics", gin.BasicAuth(gin.Accounts{
  "prometheus": "secret",
})).GET("/", func(c *gin.Context) {
  prometheus.Handler().ServeHTTP(c.Writer, c.Request)

If you now start the application again with go run main.go and point your browser to localhost:5000/metrics you will be asked for a username and password. The code above uses the user prometheus and the password secret . After sending a couple of requests to the configured / route you will see the counter value in the metrics:

# HELP mtrs_request Total number of requests
# TYPE mtrs_request counter
mtrs_request{path="/"} 4

To get started with running a prometheus backend, just follow the official installation guide using Docker. The required configuration is stored inside the prometheus.yml file.

  - job_name: "mtrs-development"
    scrape_interval: 5s
      username: prometheus
      password: secret
      - targets: [""]

As you can see the YAML configuration is again not that complex and it can easily be extended to support the production application beside the development environment as soon as the application is running on the final custom domain.

Deploy application to Heroku

The first steps are completed now and the go project with a gin web server is collecting metrics using the offical prometheus golang client library.

It’s time to commit the created files to a git repository and call the Godep command afterwars to install all needed librarys into the ventor folder.

$ > git add .
$ > git commit -m "Initial commit"
$ > godep save ./...
$ > git add .
$ > git commit -m "Add godeps"

With this default file pattern Heroku can detect the go application without extra configuration. Just create a Procfile with web: as the content and create a new Heroku application using the official command line tool:

$ > echo "web:" > Procfile
$ > heroku create
Creating app... done, warm-crag-52063 |
$ > heroku rename mtrs-io
$ > git push heroku master
$ > heroku open

After the deployment is done, you can open your browser and try to access but all you will see is the default Heroku application error. Where did the lovely greeting go?

When the main.go file was created the gin router had been configured to listen on localhost on port 5000 , this has to be changed in order to use the application on Heroku:


Heroku will pass the required port number as an environment variable called PORT:

func main() {
  port := os.Getenv("PORT")

  if port == "" {
    log.Fatal("$PORT must be set")
  } else {
    log.Print("Using port ", port)


  r.Run(":" + port)

Add the changes to git, deploy them to Heroku and you should finally see the welcome message. Of course the prometheus metrics are available as well, secured with the same BasicAuth settings as before.

Use custom domain with Heroku

Heroku has a built in support for customs domains. Just use the official Heroku command line tool and add the custom domain to the project:

$ > heroku domains:add
Adding to ⬢ mtrs-io... done

To test access from a custom domain register for a free trial account and configure your existing domain to use the DNSimple servers. Obtain a user access tokens from the DNSimple profile settings and you can use the API to create the domain records:

curl  -H 'Authorization: Bearer YOUR_SECRET_BEARER_TOKEN' \
      -H 'Accept: application/json' \
      -H 'Content-Type: application/json' \
      -X POST \
      -d '{"name": ""}' \

After the domain has been created there needs to be an ALIAS record which points to the Heroku domain, in this case it’s

curl  -H 'Authorization: Bearer YOUR_SECRET_BEARER_TOKEN' \
      -H 'Accept: application/json' \
      -H 'Content-Type: application/json' \
      -X POST \
      -d '{"name": "","type": "ALIAS","content": "","ttl":600}' \

Now the gin web server runs on the free Heroku dyno and can be access using the custom domain, use dig to verify the changes:

$ > dig

;; ANSWER SECTION:    600  IN  A

After everything is set up it’s time to add the production configuration to prometheus. Just configure a second job_name like the development environment and adjust the targets inside static_configs :

- job_name: "mtrs-production"
  scrape_interval: 5s
    username: prometheus
    password: secret
    - targets: [""]

Sadly SSL is quite expensive at Heroku, but you can create an account at and use the service with a free SSL certificate.

Use for free SSL

Add your domain and wait for CloudFlare to scan the domain settings. Delete all records CloudFlare has detected and create a new CNAME record for @ with the heroku URL as the value. Of course you want to make use of all the CloudFlare features, so disable DNS passthru and let CloudFlare handle all requests.

Now it’s time to configure the nameserver for the domain again. Sadly you have to say good bye to again and change the nameserver to the configuration CloudFlare provides:

Current Nameservers     Change Nameservers to:       Remove this nameserver       Remove this nameserver

As soon as the configuration has been deployed by the domain registrar CloudFlare should respond to requests at with some A records hosted somewhere in 104.*:

$ > dig

;; ANSWER SECTION:    300  IN  A    300  IN  A

When the configured TTL from has passed a curl request to the domain responds with header information from CloudFlare and shows the greeting of the go application:

$ > curl -i; HttpOnly
Via: 1.1 vegur
Server: cloudflare-nginx
CF-RAY: 2da2352cf6204106-HAM


That’s kind of the same setting you already achieved with so let’s configure free SSL for the custom domain. First create a new rule in CloudFlare for all HTTP requests matching http://** to always use HTTPS: Rules - Redirect HTTP to HTTPS

Now every request to includes a 301 Moved Permanently header and a Location: information:

$ > curl -i
HTTP/1.1 301 Moved Permanently

A request to may still fail, as CloudFlare needs some time to configure the SSL certificate for the domain:

curl: (35) Unknown SSL protocol error in connection to

This usually takes about ten minutes to complete and is enabled per default. While waiting for the SSL certificate you could have a look at all the additional configuration offers and activate HTTP Strict Transport Security (HSTS) for example.