🚚 How to deploy Golang application on any GNU/Linux system, but without Docker?
Tags: go, docker, linux, tutorial
Published: 2020-11-17 19:49:05

## 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! 😉

<a name="toc"></a>
### 📝 Table of contents

- [Why may I need this?](#ch-1)
- [The basis of our service](#ch-2)
  - [A few words about Fiber](#ch-2-1)
- [Creating `systemd` service](#ch-3)
- [Setting up a reverse proxy server](#ch-4)
- [Final result](#ch-5)

<a name="ch-1"></a>
## 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](#toc)

<a name="ch-2"></a>
## 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](https://github.com/gofiber/fiber) (v2), which works extremely fast and easy to learn. 

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

```go
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"))
}
```

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

```bash
GOOS=linux GOARCH=amd64 go build main.go -o ./hello_world
```

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

[↑ Table of contents](#toc)

<a name="ch-2-1"></a>
### A few words about Fiber

Perhaps, you are asking yourself, so why do I love [Fiber web framework](https://gofiber.io/) 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](https://gofiber.io/discord) and detailed [documentation](https://docs.gofiber.io) (translated into different World languages)!

[↑ Table of contents](#toc)

<a name="ch-3"></a>
## 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:

```bash
nano /etc/systemd/system/hello_world.service
```

- Copy this code to it:

```ini
[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
```

- Hit `Ctrl+O` to save and `Ctrl+X` for close editor
- Next, start and enable this service:

```bash
systemctl start hello_world.service
systemctl enable hello_world.service
```

> ☝️ Service will start automatically, even after the remote server reboots.

[↑ Table of contents](#toc)

<a name="ch-4"></a>
## Setting up a reverse proxy server

I will use [Nginx](https://nginx.org) 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:

```bash
apt install nginx -y
```

- Start `nginx` service:

```bash
systemctl start nginx
```

- Create a config in `/etc/nginx/sites-available/hello_world` file:

```nginx
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;
    }
}
```

- Create a symbolic link of our config file to the `sites-enabled` folder:

```bash
ln -s /etc/nginx/sites-available/hello_world /etc/nginx/sites-enabled
```

- Finally, reload `nginx` to apply config:

```bash
nginx -t && nginx -s reload
```

> 🔥 Sometimes it can be a problem that port `3000` is not available on your remote server. Please check the firewall settings.

[↑ Table of contents](#toc)

<a name="ch-5"></a>
## Final result

Yep, that's it! Go to `http://your_server_ip:3000` and see result 🎉

![result](https://dev-to-uploads.s3.amazonaws.com/i/a3mj8mhx8cwuxk19iold.png)

[↑ Table of contents](#toc)

<a name=""></a>
## Photos by

- Simon Abrams https://unsplash.com/@flysi3000

<a name=""></a>
## P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My projects that need your help (and stars) 👇

- 🔥 [gowebly][gowebly_url]: A next-generation CLI tool for easily build amazing web applications with Go on the backend, using htmx & hyperscript and the most popular atomic/utility-first CSS frameworks on the frontend.
- ✨ [create-go-app][cgapp_url]: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.
- 🏃 [yatr][yatr_url]: Yet Another Task Runner allows you to organize and automate your routine operations that you normally do in Makefile (or else) for each project.
- 📚 [gosl][gosl_url]: The Go Snippet Library provides snippets collection for working with routine operations in your Go programs with a super user-friendly API and the most efficient performance.
- 🏄‍♂️ [csv2api][csv2api_url]: The parser reads the CSV file with the raw data, filters the records, identifies fields to be changed, and sends a request to update the data to the specified endpoint of your REST API.
- 🚴 [json2csv][json2csv_url]: The parser can read given folder with JSON files, filtering and qualifying input data with intent & stop words dictionaries and save results to CSV files by given chunk size.

<!-- Footer links -->

[gowebly_url]: https://github.com/gowebly
[cgapp_url]: https://github.com/create-go-app
[yatr_url]: https://github.com/koddr/yatr
[gosl_url]: https://github.com/koddr/gosl
[csv2api_url]: https://github.com/koddr/csv2api
[json2csv_url]: https://github.com/koddr/json2csv