42
Login With Github

Productionizing

This document is a work in progress... Use at your own risk...

This is roughly how botskrieg.com is running, this document is currently mostly for me if I need to re setup the server

Long term, I'd like to make it easy enough to run one of these servers that my college professors could do it without much issue


Outside the Server Setup

Get a Domain

Any domain will work so long as you own it

I personally use AWS for my registrar and then point my name servers at Digital Ocean

From this point on I will refer to your domain as $BATTLE_BOX_HOST

Register a Github Oauth Application

To provide sign-in battle box needs a Github Oauth application, go here to create one

Set the Authorization Callback URL to `$BATTLE_BOX_HOST/auth/github/callback` (for me `https://botskrieg.com/auth/github/callback`)

Save the values for the Client ID and Client Secret

Get a Server From Digital Ocean (or Whoever)

I'm using the 5$ a month 1gb 1vcpu instance here

If you're considering using Digital Ocean, think about using my referrer link (https://m.do.co/c/e72236f4c547). You'll get free credits, and if you decide to keep using Digital Ocean, I'll get credits which will go towards botskrieg.com

I'm using the Digital Ocean Prebuilt Docker Image, if you'd like to use something else, make sure that Docker is available

Configure the DNS record for $BATTLE_BOX_HOST to point to your server

I use the Linux "dig" utility to check that the dns is correctly provisioned, I can see that botskrieg.com is pointing at 68.183.104.42 which is the same as I see in the digital ocean droplet management console

$ dig botskrieg.com

; <<>> DiG 9.10.6 <<>> botskrieg.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62775
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;botskrieg.com.		IN	A

;; ANSWER SECTION:
botskrieg.com.	3588	IN	A	68.183.104.42

;; Query time: 66 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 01 20:11:30 EST 2020
;; MSG SIZE  rcvd: 62

Allow Network Traffic into your Server

In the Digital Ocean Firewall Settings create a Firewall that allows the following inbound rules, and apply it to your server

  1. Port 22 (SSH)
  2. Port 80 (HTTP to be redirected to HTTP 443)
  3. Port 443 (HTTPS)
  4. Port 4242 (BattleBox TCP Connections)

Inside the Server Setup

SSH into your server to run the following steps

Export your Domain Name as an ENV Var

Replace botskrieg.com with your domain name

export BATTLE_BOX_HOST=botskrieg.com

Update your Server

apt update && apt upgrade

Configure your Firewall

ufw allow ssh/tcp
ufw allow http/tcp
ufw allow https/tcp
ufw allow 4242
ufw logging on
yes | ufw enable
ufw status

Install Certbot

echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list
gpg --keyserver pgp.mit.edu --recv-keys 7638D0442B90D010 8B48AD6246925553
gpg --armor --export 7638D0442B90D010 | apt-key add -
gpg --armor --export 8B48AD6246925553 | apt-key add -
apt update
apt install certbot python-certbot-nginx -t stretch-backports

Create the "battle_box" User Who Will Run the App

useradd battle_box
mkdir /srv/battle_box
chown battle_box:battle_box /srv/battle_box

Install Postgres (and Create the "battle_box" Database)

apt install postgresql postgresql-contrib
sudo -u postgres createuser --echo --no-createdb --pwprompt --no-superuser battle_box
sudo -u postgres createdb battle_box

Install NGINX

apt install nginx

Configuring NGINX and getting SSL certs

This has to be done in two steps, so that lets encrypt can get its certs and then we configure nginx to listen on 4242 with the lets encrypt certs

cat | envsubst '$BATTLE_BOX_HOST' > /etc/nginx/sites-available/default <<'CONF'
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name $BATTLE_BOX_HOST;
  location ~ /.well-known {
    root /var/www/html;
    allow all;
  }
  location / {
    proxy_pass http://127.0.0.1:4000/;
    proxy_http_version 1.1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}
CONF

Run Certbot

certbot --nginx

Setup streaming for TCP connections using the Let's Encrypt Certs

cat | envsubst '$BATTLE_BOX_HOST' > /etc/nginx/nginx.conf <<'CONF'
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;


events {
	worker_connections 768;
}

http {
	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	gzip on;

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

stream {
  server {
	  listen 4242 ssl;
	  proxy_pass 127.0.0.1:4001;
	  ssl_certificate /etc/letsencrypt/live/$BATTLE_BOX_HOST/fullchain.pem;
	  ssl_certificate_key /etc/letsencrypt/live/$BATTLE_BOX_HOST/privkey.pem;
  }
}
CONF

Create your ENV file

You can generate secrets in the following way

$ openssl rand -base64 36

Be sure to fill in these values

cat | envsubst > /etc/default/battle_box <<CONF
BATTLE_BOX_HOST=$BATTLE_BOX_HOST
BATTLE_BOX_SECRET_KEY_BASE=$FILL_ME_IN
BATTLE_BOX_DATABASE_URL=$FILL_ME_IN
BATTLE_BOX_GITHUB_CLIENT_ID=$FILL_ME_IN
BATTLE_BOX_GITHUB_CLIENT_SECRET=$FILL_ME_IN
BATTLE_BOX_LIVE_VIEW_SALT=$FILL_ME_IN
CONF

Building the Image

Clone the Repo

git clone https://github.com/FlyingDutchmanGames/battle_box.git

Build the image

cd battle_box
docker build . -t battle_box:`git rev-parse HEAD`
docker build . -t battle_box:master

Creating the System Service

Create a directory to hold the configs

mkdir /srv/battle_box

Create the service config

cat > /etc/systemd/system/battle_box.service <<CONF
[Unit]
Description=BattleBox
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/srv/battle_box
ExecStart=/usr/bin/docker run -p 4000 -p 4001 --network="host" --env-file=/etc/default/battle_box battle_box:master
Restart=on-failure
RestartSec=5
Environment=LANG=en_US.UTF-8
SyslogIdentifier=battle_box
RemainAfterExit=no
[Install]
WantedBy=multi-user.target
CONF

Enable the service

systemctl enable battle_box.service

The Running Server

Get an Interactive Elixir Console

Get into the Docker container

docker exec -it `docker ps | grep battle_box | awk '{print $1}'` /bin/bash

Once inside

./battle_box/bin/battle_box remote

Running Migrations

While in an Elixir console on the running server

iex(battle_box@botskreig)1> BattleBox.Release.migrate()