# deploying go to a vpn ubuntu server with github and ssl

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

{% embed url="<https://docs.github.com/en/actions/security-guides/encrypted-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
```
