DEV Community

Felix
Felix

Posted on

4 2

Secure your go REST Api in Docker using Letsencrypt

I recently had to figure this out and could not find a good resource, I hope this is the first one then.



How to set up HTTPS for a Go (Gin) REST API using Docker and Letsencrypt

What is used (what you need to install):

  1. Go
  2. Gin
  3. Docker

Source code for the demo Go REST API:

package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

func setupRouter() *gin.Engine {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(http.StatusOK, "pong")
    })
    return r
}

func main() {
    r := setupRouter()
    r.Run(":80")
}
Enter fullscreen mode Exit fullscreen mode

How to encrypt it using letsencrypt

  1. Add "github.com/gin-gonic/autotls" to your imports.
  2. Open a goroutine for the run on port 80 to prevent blocking the thread while still enabling access via http: Change:
r.Run(":80")
Enter fullscreen mode Exit fullscreen mode

To:

go r.Run(":80")
Enter fullscreen mode Exit fullscreen mode
  1. Add the option to access the service via ssl:
m := autocert.Manager{
    Prompt:     autocert.AcceptTOS,
    HostPolicy: autocert.HostWhitelist("domain.com"),
    Cache:      autocert.DirCache("/var/www/.cache"),
}
autotls.RunWithManager(r, &m)
Enter fullscreen mode Exit fullscreen mode

You have to enter your domain instead of "domain.com"

Dockerize it

Dockerfile:

FROM golang:latest

WORKDIR /

COPY . .

EXPOSE 80

EXPOSE 443

ENV GIN_MODE=release

VOLUME ["/var/www/.cache"]

CMD [ "go","run", "main.go" ]
Enter fullscreen mode Exit fullscreen mode

You should also add a volume to docker-compose because you will be rate limited by letsencrypt if you request to many certificates

go-backend:
  build:
    context: ./go-backend
    dockerfile: Dockerfile
  ports:
    - 80:80
    - 443:443
  container_name: go-backend
  volumes:
    - certcache:/var/www/.cache
Enter fullscreen mode Exit fullscreen mode

Here the gin project is located in ./go-backend which might be different for your project. The important part is that the volume is created at /var/www/.cache to prevent to many requests to letsencrypt.

Final notes:

If you want to encrypt your api and make it accessible using https, it might be a good idea to prevent using http. This would be especially important if you send passwords or other sensitive data to or from the server via your api. In this case you should remove this from your go code:

go r.Run(":80")
Enter fullscreen mode Exit fullscreen mode

You also should close (not open) port 80 in your Dockerfile and in docker-compose because they are not needed.

Full go code:

package main

import (
    "github.com/gin-gonic/autotls"
    "github.com/gin-gonic/gin"
    "golang.org/x/crypto/acme/autocert"
    "net/http"
)

func setupRouter() *gin.Engine {
    r := gin.Default()

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(http.StatusOK, "pong")
    })
    return r
}

func main() {
    r := setupRouter()
    go r.Run(":80")
    m := autocert.Manager{
        Prompt:     autocert.AcceptTOS,
        HostPolicy: autocert.HostWhitelist("domain.com"),
        Cache:      autocert.DirCache("/var/www/.cache"),
    }
    autotls.RunWithManager(r, &m)
}
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

The Future of AI, LLMs, and Observability on Google Cloud

Datadog sat down with Google’s Director of AI to discuss the current and future states of AI, ML, and LLMs on Google Cloud. Discover 7 key insights for technical leaders, covering everything from upskilling teams to observability best practices

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more