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 "user@email.com"    

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/checkout@v2

    - name: install go
      uses: actions/setup-go@v2
      with:
        go-version: '1.17.3'

    - name: build
      run: go build .

    - name: send binary
      uses: appleboy/scp-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.KEY }}
        source: "aocweb"
        target: "/home/web/aocweb"

    - name: restart
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.KEY }}
        script: sudo systemctl restart aocweb && sudo systemctl status aocweb

Last updated