DEV Community

loading...
Cover image for ๐Ÿšš How to deploy Golang application on any GNU/Linux system, but without Docker?

๐Ÿšš How to deploy Golang application on any GNU/Linux system, but without Docker?

koddr profile image Vic Shรณstak ใƒป3 min read

Introduction

Hey, hey! ๐Ÿ‘‹ Another interesting article about deploy and Golang is here.

Let's imagine that we need to run an application written on Go on a remote server, but configure Docker too long (or just lazy).

What should we do? Learn from this article! ๐Ÿ˜‰

๐Ÿ“ Table of contents

Why may I need this?

First, it is just important to know how service applications work on GNU/Linux. Also, it will be interesting for very small projects, that are too early to think about Docker and deployment automation (startups, REST API micro services, etc).

โ†‘ Table of contents

The basis of our service

Okay, time to write a simple web service, that will give us something, when sending a request to it. For example, I'll take my favorite web framework Fiber (v2), which works extremely fast and easy to learn.

If you are not yet familiar with it, follow the comments in the code:

package main

import (
    "log"

    "github.com/gofiber/fiber/v2"
)

func main() {
    // Create new Fiber instance
    app := fiber.New()

    // Make path with some content
    app.Get("/hello", func(c *fiber.Ctx) error {
        // Return a string with a dummy text
        return c.SendString("Hello, World ๐Ÿ‘‹!")
    })

    // Start server on http://localhost:3000 or error
    log.Fatal(app.Listen(":3000"))
}
Enter fullscreen mode Exit fullscreen mode

Save this file as main.go and build binary for GNU/Linux x64 within a similar folder with hello_world name:

GOOS=linux GOARCH=amd64 go build main.go -o ./hello_world
Enter fullscreen mode Exit fullscreen mode

OK. Now, just copy this binary to your remote server inside /root/go folder.

โ†‘ Table of contents

A few words about Fiber

Perhaps, you are asking yourself, so why do I love Fiber web framework so much? The answer is in its main features:

  1. Robust routing
  2. Extreme performance
  3. API-ready web framework
  4. Flexible middleware support
  5. Low memory footprint

And, especially, I'd like to mention the extremely friendly community in Discord and detailed documentation (translated into different World languages)!

โ†‘ Table of contents

Creating systemd service

The systemd is a software suite that provides an array of system components for Linux operating systems.

[...] Its main aim is to unify service configuration and behavior across Linux distributions; systemd's primary component is a "system and service manager"โ€”an init system used to bootstrap user space and manage user processes.

โ€” Wikipedia

Perfect! Now let's create a new service.

  • Connect to your remote server as root (super user)
  • Create a file with the extension *.service within the systemd folder:
nano /etc/systemd/system/hello_world.service
Enter fullscreen mode Exit fullscreen mode
  • Copy this code to it:
[Unit]
Description=Go sample web app
After=multi-user.target

[Service]
User=root
Group=root
ExecStart=/root/go/hello_world

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
  • Hit Ctrl+O to save and Ctrl+X for close editor
  • Next, start and enable this service:
systemctl start hello_world.service
systemctl enable hello_world.service
Enter fullscreen mode Exit fullscreen mode

โ˜๏ธ Service will start automatically, even after the remote server reboots.

โ†‘ Table of contents

Setting up a reverse proxy server

I will use Nginx as a reverse proxy server, but you can choose any other one.

  • Install nginx using the package manager. For Debian-like systems it will look like this:
apt install nginx -y
Enter fullscreen mode Exit fullscreen mode
  • Start nginx service:
systemctl start nginx
Enter fullscreen mode Exit fullscreen mode
  • Create a config in /etc/nginx/sites-available/hello_world file:
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name _;

    location /root/go/hello_world {
            proxy_pass http://localhost:3000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Create a symbolic link of our config file to the sites-enabled folder:
ln -s /etc/nginx/sites-available/hello_world /etc/nginx/sites-enabled
Enter fullscreen mode Exit fullscreen mode
  • Finally, reload nginx to apply config:
nginx -t && nginx -s reload
Enter fullscreen mode Exit fullscreen mode

๐Ÿ”ฅ Sometimes it can be a problem that port 3000 is not available on your remote server. Please, check the firewall settings.

โ†‘ Table of contents

Final result

Yep, that's it! Go to http://your_server_ip:3000 and see result ๐ŸŽ‰

result

โ†‘ Table of contents

Photos by

P.S.

If you want more โ†’ write a comment below & follow me. Thanks! ๐Ÿ˜˜

Discussion

pic
Editor guide
Collapse
yoursunny profile image
Junxiao Shi

I find it easier to run Go programs with pm2, together with Node.js programs.

As for the reverse proxy, I use nginx mostly but am doing trial deployments with Caddy.

If the service doesn't need to be on port 443 (backend API), I may skip the reverse proxy altogether and let the Go program listen on port 8443 of an IPv6 address using a self-signed certificate, and then enable Cloudflare in front of it.

Collapse
koddr profile image
Vic Shรณstak Author

Hello! Yes, of course, you can choose this path.

In this article I showed you a way to do this on the built-in tools (almost every distribution already has Nginx installed, for example) and with a minimum of configuration effort... ๐Ÿ˜‰