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
- Port 22 (SSH)
- Port 80 (HTTP to be redirected to HTTP 443)
- Port 443 (HTTPS)
- 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()