# Tutorial: Deployment of Golang web app using Systemd

Today, I am going to show you a simple way of deploying a Golang web application.

We are going to use [Systemd](https://systemd.io/) and a Makefile to deploy the code when we merge to main branch. In a future blog post we will revisit and show you how you can deploy  
when you push to main by utilizing Github Pipelines.

Let's get started 🥳

### Setting up Systemd

I assume that you already have a linux VPS. If not, then I recommend you create an account in Digital Ocean using this [link](https://m.do.co/c/c11136c4693c) . If you register using this link you will get $200 in credit and I will get $25 in case you continue using this. Basically, you can try this for free so give it a try .

The instructions will be for an Ubuntu VPS so if you create a new one now please use the Ubuntu image.

### Setting up DNS

Configure your domain to point to your server's ip address.

then `ssh` into the VPS and do:

**In your VPS**

```bash
sudo touch /etc/systemd/system/invoice-hub.service
mkdir -p /home/giorgos/invoice-server
touch /home/giorgos/invoice-server/.env
sudo mkdir -p /.cache/.certs && sudo chown -R giorgos:giorgos /.cache/.certs
```

**<mark>☢️ adjust the paths and the USER</mark>**

Then open with an editor and paste:

```bash
[Unit]
Description=Freelance invoice hub service

[Install]
WantedBy=multi-user.target

[Service]
Type=simple
ExecStart=/home/giorgos/invoice-server/invoice-server
WorkingDirectory=/home/giorgos/invoice-server
EnvironmentFile=/home/giorgos/invoice-server/.env
Restart=always
RestartSec=5
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=%n
```

<mark>⚠️ modify the paths to match your servers.</mark>

❕this is not the "best" systemd config. However we want to deploy fast and this is good enough. We will revisit in the future

The being still in your VPS edit the `.env` file you created and add:

```bash
FIH_DOMAIN=<YOUR-DOMAIN>
```

<mark>Obviously, replace with your domain.</mark>

Now let's reload the systemd and enable the service

```bash
sudo systemctl daemon-reload
sudo systemctl enable invoice-hub
```

**In your local computer**

Now in your local computer build the program:

```bash
GOOS=linux GOARCH=amd64 go build -o invoice-server cmd/main.go
```

This will create a file invoice-server .  
If your VPS uses a different OS or architecture please use the correct enviroment variables. See here for a [tutorial](https://www.digitalocean.com/community/tutorials/how-to-build-go-executables-for-multiple-platforms-on-ubuntu-16-04) .

Now let's manually copy the file to the server

```bash
scp invoice-server <USERNAME>@<server-ip>:~/invoice-server/invoice-server
```

The above command just copies the executable you build to the servers path.  

If not already done I highly recommend you create an public/private key pair and use that to login to your server .

This tutorial is not about that, so if you don't know how to do it google or ask ChatGPT .

I like to add an entry in my ~/.ssh/config file like:

```bash
Host <just-a-name>
HostName <server-ip>
User giorgos
IdentityFile ~/.ssh/id_rsa
Port 22
```

Highly recommend to do that.

Then you can ssh using `ssh just-a-name` .

Enough, with that. I assume you managed to copy your file to the server now.

login again to your VPS

and run:

```bash
sudo systemctl start invoice-hub
```

Now check the status:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718465830052/08b5b5df-87e1-441f-929b-0151587e69aa.png align="center")

And if you did everything correct then you can visit your new web app

https://YOUR-DOMAIN.com

and you should see the

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718465893901/e721c848-9d74-4a11-a4f2-a896cbc0937a.png align="center")

🚀🚀🚀🚀🚀

Because it's a little bit tedious to manually build, copy the executable and the run stop and start the service let's automate a bit.

We are going to utilize our make file

Let's create a new branch:

```bash
git checkout -b deploy-Makefile-auth
```

and add the following in your Makefile

```bash
deploy: ## deploys to the remote server
	GOOS=linux GOARCH=amd64 go build -o invoice-server cmd/main.go
	scp invoice-server contabo-main:~/invoice-server/invoice-server.2
	ssh myserver sudo systemctl stop invoice-hub
	ssh myserver sudo mv invoice-server/invoice-server.2 invoice-server/invoice-server
	ssh myserver sudo systemctl start invoice-hub
```

**<mark>Please replace myserver with your server Host (as you configured in your ~/.ssh/config OR use username@server-ip instead</mark>**

let's do a change and deploy.

Instead of `HELLO WORLD` lets make our handler to return

`THANK YOU`

Change your http/router.go as in the image

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718466476304/97d38fa1-20b7-4816-9bad-d2ed5419b699.png align="center")

and then run

```bash
make deploy
```

wait until the deployment finishes and go to you website

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718466562453/dc5545dc-1242-4ea1-9612-20ad2d7fa280.png align="center")

You should see the above .

###   
Basic HTTP Auth

We don't want our web app to be accessible to everyone. Let's configure Basic HTTP Auth.

In our case this is fine since the app will be used only by one user and we are using TLS.

Echo has a middleware that does that for us.

Let's do the following:

```bash
go get "github.com/labstack/echo/v4/middleware"
```

and then in our `router.go` modify the new method to work like:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718467162797/9027a4d2-eb62-4583-b21b-7f36493f8382.png align="center")

As you see in the image we need to store our username and password in the environment variables.

For local development add them in the `dev.env`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718467222752/58ead675-94c9-47a6-b211-9b471a07b83b.png align="center")

for production set them in your server `invoice-server/.env` file.

<mark>USE SOMETHING SECURE</mark>

Let's now test it

```bash
make dev
```

and then when you visit:

[https://local.freelance-invoice-hub.com](https://local.freelance-invoice-hub.com)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1718467565594/71ed06a3-186c-490d-8567-3f8aee42ec0a.png align="center")

since it works let's now commit and deploy:

```bash
git add .
git commit -m "simple deploy script and basic auth"
git push origin deploy-Makefile-auth
```

And let's deploy

```bash
make deploy
```

As usual you can find all the code in the related [github branch](https://github.com/gosom/freelance-invoice-hub/tree/deploy-Makefile-auth)

### Summary and what's next

Today we learned a simple way to deploy our Golang applications using Systemd.

This is a really basic method and we can improve our deployments a LOT.

<mark>However, the scope of this series is to create a WORKING golang application and at the same time learn that our time is precious. We will do only what is required.<br>When we have an application working we will keep improving.</mark>

Additionally, we learned how to use the Basic Auth Middleware that echo providers

In the next blog we will start coding our application. We will define our domain models and the operations on them.

Until then have fun.

Please comment if something is not clear or does not work for you and I will try to help

Also, don't forget to follow me on [X](https://x.com/gkomdev)
