deploying go to a vpn ubuntu server with github and ssl

Deploy a go application to a small server with SSL support and Github as CI/CD
Assumptions:
  • root repository contain main.go with the package name `aocweb`
  • we are using small VPS with ubuntu 20.04
  • app will be deployed to /home/web/aocweb
  • App runs HTTP on PORT 8080

Setup user and home

some VPS have root as default user, if not already we can create a user. In this example web
adduser web
usermod -aG sudo web

Install NGINX & Letsencrypt

sudo apt-get update
sudo apt-get install nginx
sudo ufw allow 'Nginx HTTP'
sudo apt-get install certbot python3-certbot-nginx
sudo certbot --nginx
Generate certificate
sudo certbot --nginx certonly
to test auto renewal
sudo certbot renew --dry-run
Add /etc/nginx/sites-enabled/example.com
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
server_name example.com;
listen 443 ssl;
ssl on;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
root /var/www/html;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /ws {
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;proxy_pass http://127.0.0.1:8080/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Install systemd service

if the application requires environment we can put it on /home/web/aocweb/.env
ENV=prod
CLIENT_ID=abcdef
create /etc/systemd/system/aocweb.service
[Unit]
Description= AocWeb app
After=network.target
After=mysql.service
[Service]
User=web
Group=www-data
EnvironmentFile=/home/web/aocweb/.env
WorkingDirectory=/home/web/aocweb
ExecStart=/home/web/aocweb/aocweb web
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
To make sure we can run systemctl restart with sudo without password. Create sudo configuration file (make sure to use visudo so you don't accidentally locked your self.
visudo -f /etc/sudoers.d/systemctl
With content
web ALL=NOPASSWD: /usr/bin/systemctl restart aocweb
web ALL=NOPASSWD: /usr/bin/systemctl status aocweb

Deploy with Github Action

Generate SSH key for deployment

ssh-keygen -t ed25519 -C "[email protected]"
example with that command I created 2 files on ~/.ssh/ : aocweb & aocweb.pub

add generated public key to server

Copy the content of aocweb.pub to /home/web/.ssh/authorized_key. This allows login with ssh private key. Test that you can login to the server with that key (check ssh -v output)

Add secrets

create these secrets on the github repository
  • HOST
  • KEY
  • USERNAME
KEY is the content of aocweb.pub ssh key

Github workflow

create .github/workflows/release.yaml
name: Release
on:
push:
branches:
- release
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- name: install go
uses: actions/[email protected]
with:
go-version: '1.17.3'
- name: build
run: go build .
- name: send binary
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
source: "aocweb"
target: "/home/web/aocweb"
- name: restart
uses: appleboy/[email protected]
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: sudo systemctl restart aocweb && sudo systemctl status aocweb