Today, I am going to show you a simple way of deploying a Golang web application.
We are going to use Systemd 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 . 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
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
β’οΈ adjust the paths and the USER
Then open with an editor and paste:
[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
β οΈ modify the paths to match your servers.
β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:
FIH_DOMAIN=<YOUR-DOMAIN>
Obviously, replace with your domain.
Now let's reload the systemd and enable the service
sudo systemctl daemon-reload
sudo systemctl enable invoice-hub
In your local computer
Now in your local computer build the program:
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 .
Now let's manually copy the file to the server
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:
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:
sudo systemctl start invoice-hub
Now check the status:
And if you did everything correct then you can visit your new web app
and you should see the
πππππ
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:
git checkout -b deploy-Makefile-auth
and add the following in your Makefile
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
Please replace myserver with your server Host (as you configured in your ~/.ssh/config OR use username@server-ip instead
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
and then run
make deploy
wait until the deployment finishes and go to you website
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:
go get "github.com/labstack/echo/v4/middleware"
and then in our router.go
modify the new method to work like:
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
for production set them in your server invoice-server/.env
file.
USE SOMETHING SECURE
Let's now test it
make dev
and then when you visit:
https://local.freelance-invoice-hub.com
since it works let's now commit and deploy:
git add .
git commit -m "simple deploy script and basic auth"
git push origin deploy-Makefile-auth
And let's deploy
make deploy
As usual you can find all the code in the related github branch
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.
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.
When we have an application working we will keep improving.
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