Installation Guide
Before you install¶
The following installation guide will document setup with Docker because it's what we at Team 1533 Triple Strange and The Red Alliance use. It's also important to note that StrangeScout is designed to be run behind a reverse proxy, and as such does not have built-in support for HTTPS certificates. We do provide example configurations using the traefik reverse proxy, but you are more than welcome to use your own reverse proxy, or even fork the code and roll in your own support for HTTPS.
Dependencies¶
StrangeScout only has two true dependencies:
Docker is the program that allows services to be run as individual containers on a host machine, and Docker Compose is a utility that simplifies choreography of multiple docker containers.
You will also need to have a domain pointing at the server you're installing StrangeScout on.
First, install Docker following the available installation instructions for your distribution of choice, for example on an x86_64 Ubuntu server you would run the following (as root):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
Secondly, install Docker Compose following the available installation instructions for your distribution of choice, for example on a *nix server you would run the following (as root):
1 2 3 4 5 6 7 | |
After both dependencies have been installed, ensure the Docker system service has been started and enabled:
1 2 | |
Setting up the reverse proxy¶
Now that all dependencies have been installed we can begin setting up traefik for our reverse proxy.
For the sake of organization and due to the way docker-compose names containers, you should make a directory to store the reverse proxy files. Run the following two commands before continuing to setup the reverse proxy:
1 2 | |
Creating a docker network¶
The first step to setting up traefik is to create a new docker network:
1 | |
This will allow for containers on the same network to easily communicate with each other. In our case it allows for the StrangeScout server to communicate with the database in its own separate container.
Creating the certificate file¶
Any modern website should be served using the HTTPS protocol. This ensures any data sent to or from the users is encrypted and cannot be read by unauthorized persons. Our reverse proxy, traefik, has built in support for HTTPS, and can automatically update certificates for HTTPS using ACME (Automated Certificate Management Environment). To do so, we need somewhere to store these certificates. Create a file with the following command as root:
1 | |
Note
In order for traefik to store certificates in this file, it must be owned by root. When creating the file, ensure you're running the command as root or using sudo!
In order to work properly, we need to set specific permissions on this file. It must ONLY be readable and writable by root. Update the files permissions with the following command as root:
1 | |
Note
chmod is used to update file attributes. In this case, we're setting the file permissions to 600, which corresponds to R/W for the owner, and no permissions for anyone else. Because the file is owned by root, only root can access the file. If these permissions are not set traefik will not be able to get certificates.
Creating the compose file¶
Now that our network and ACME certificate file have been created, we can put together the docker-compose file for the reverse proxy. To start, we need to create our compose file:
1 | |
Now that we have our compose file, let's start with some basic options:
1 2 3 4 5 6 7 8 9 10 | |
What we're doing here is start off by stating that we're using version 3.3 of the docker-compose syntax. Next we start our list of services, and define a service with the name reverse-proxy. Within the reverse-proxy service we specify that it should use the traefik:v2.0 image from Docker Hub, that the container name should be reverse-proxy, the hostname should be reverse-proxy, and the container should always restart if it fails.
Note
the hostname key sets friendly names that containers can be accessed by on the docker network we created earlier. While this isn't necessary for the reverse proxy container, it will be useful later when we want to specify the url to access the database at.
Next, we'll add some command line options that will be given to traefik when it runs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
--providers.dockertells traefik we have services running via docker--entrypoints.web.address=:80: Sets the port on the entrypoint namedwebto port 80--entrypoints.websecure.address=:443sets the port on the entrypoint namedwebsecureto port 443--entrypoints.mongodb.address=:27017sets the port on the entrypoint namedmongodbto port 27017--certificatesresolvers.leresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directorysets the URL of the ca server to use for ACME certificates--certificatesresolvers.leresolver.acme.email=<youremail@yourdomain.tld>sets the email used when acquiring certificates--certificatesresolvers.leresolver.acme.storage=/acme.jsontells traefik where to store certificates--certificatesresolvers.leresolver.acme.tlschallenge=truetells traefik what method to use to get certificates
Note
Entrypoints are points where network traffic can enter traefik to be routed. The web entrypoint will be used for unencrypted HTTP traffic (we'll be setting it up to automatically redirect to HTTPS as well), the websecure entrypoint for encrypted HTTPS traffic, and the mongodb entrypoint for direct access to our database.
Next we need to open the ports that we defined in our traefik entrypoints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
Each port definition has two parts, separated by a : colon. The first part describes the port to map to on the host machine, while the second part is the port to bind to within the container. For example, 80:80 means that requests to port 80 on the host machine will route to port 80 within the container. In our case we are routing ports 80, 443, and 27017 on the host machine to those same ports within the traefik container.
Note
Port definitions can also be more specific, including a specific interface they should listen to. For example, 127.0.0.1:80:80 would only map traffic on port 80 from localhost to the container.
The next step is to setup some volumes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
Here we are defining two volumes for the container.
"./acme.json:/acme.json"mounts our ACME certificate file to/acme.jsonin the container, which is where we've told traefik to look for it"/var/run/docker.sock:/var/run/docker.sock:ro"mounts our host machine's docker socket read-only inside the container
Mounting the docker socket in the container allows traefik to find out which containers it needs to connect to and what traffic to route to them.
Next we need to set some labels on the container, which will be used to configure some additional features:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
traefik.http.middlewares.compress.compress=truecreates a new traefik middleware called compress that compresses traffictraefik.http.middlewares.redirect-to-https.redirectscheme.scheme=httpscreates a middleware that redirects traffic to HTTPStraefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)creates a router that matches to all domainstraefik.http.routers.redirs.entrypoints=websets the router to listen on the HTTP web entrypointtraefik.http.routers.redirs.middlewares=redirect-to-httpsenables the HTTPS redirection middleware
Essentially, these labels enable compression on web traffic and automatically redirect any HTTP traffic to HTTPS.
Finally, we can add our docker network:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | |
There are two parts to adding the network. First, we tell our reverse-proxy service to attach to the strangescout_main network, then we define the network in the top level of the compose file.
Starting the reverse proxy¶
To start the reverse proxy you only need to run one command:
1 | |
As long as you're in the same directory as the docker-compose.yml file, it will automatically be read and the service will start up and fork to the background thanks to the -d flag!
Setting up the database¶
After we've setup the reverse proxy, we'll need a database to store our scouting data. In the case of StrangeScout we use MongoDB.
As with the reverse proxy, we'll once again create a directory to store the database files:
1 2 | |
We also need persistent storage for the database, so we'll create a directory for that as well:
1 | |
Creating the compose file¶
To start, we need to create our compose file:
1 | |
The compose file for the database will start very similarly to that of the reverse proxy:
1 2 3 4 5 6 7 8 9 10 | |
Next, we need to mount our data directory into the container:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Next we need to setup the root database account:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
MONGO_INITDB_ROOT_USERNAME: rootsets the database's root account username torootMONGO_INITDB_ROOT_PASSWORD: example-passwordsets the account password toexample-password
By convention you'll probably want to leave the username as root. Make sure the password is something secure because this account will have full read/write access to the entire database!
Now we need to set some labels to tell our reverse proxy how to route database traffic:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
traefik.tcp.routers.mongodb.entrypoints=mongodbtells traefik to put this container on a TCP router with themongodbentrypoint we setup that allows traffic on MongoDB's port 27017traefik.tcp.routers.mongodb.rule=HostSNI(`*`)tells traefik to match all domains, which is required for traefik TCP services
Finally, we attach the docker network to the container:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Starting the database¶
The database will be started with the exact same command as the reverse proxy:
1 | |
Building StrangeScout¶
While we do provide prebuilt docker images, you may decide to build StrangeScout yourself. If you want to use prebuilt images you can skip this step.
Cloning the repository¶
The first step to build any project is to clone its repository. StrangeScout has separate repositories for the frontend, backend, and deploy scripts. Since we're trying to build the final product, we want to clone the build repository. We also need to make sure we've cloned the submodules:
1 2 3 4 | |
Building the image¶
Thanks to the premade Dockerfile, building the image is as simple as one command:
1 | |
Once the command completes, you'll have a docker image tagged strangescout!
Setting up StrangeScout¶
Once again we'll start by creating a self contained directory:
1 2 | |
Creating the compose file¶
The StrangeScout service itself doesn't require any persistent volumes or other local files, so all we have to do is create a compose file:
1 | |
And start editing:
1 2 3 4 5 6 7 8 9 10 | |
We once again start the same way as the database and reverse proxy services. Here we're using the latest prebuilt image, but if you built the image yourself you should put whatever you tagged it as for the image key. A list of prebuilt image tags can be found here: https://hub.docker.com/r/theredalliance/strangescout/tags
Next we need to set some environment variables:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
SECRET=jwt-secretsets the secret used to encrypt the tokens used for authenticating users. This should be a random string of your choice."DB_URL=mongodb://root:db-password@mongodb:27017/dbname?authSource=admin"sets the URL of the database.root:db-passwordcorresponds to the root username and password we set up earlier.@mongodb:27017says to go to port 27017 - the default MongoDB port, at hostnamemongodb, which is what we set the database container hostname to.dbnameis the name of the database within Mongo that your data will be stored in, and can be set to anything you want following the rules set here: https://docs.mongodb.com/manual/reference/limits/#restrictions-on-db-names.?authSource=adminsays to use theadmindatabase to find the user. This should not be changed.
DB_DEBUGenables debug logs from the backend (omit completely to disable)ADMIN_EMAILsets the email address of the default strangescout admin accountADMIN_PASSWORDsets the password for the default admin accountTBA_KEYsets the API key for The Blue Alliance integration
Next we need to add a template file. StrangeScout uses a YAML file to define the game. Premade templates can be found under Premade Game Templates. To use your template, we need to mount it as a volume:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
./template.yml:/template.yml tells docker to mount the file ./template.yml at /template.yml inside the container. Change the first part of the mount to point to your template file.
Next we need to set some labels to tell Traefik how to route our container:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
traefik.http.routers.strangescout.rule=Host(`<yourdomain.tld>`)tells traefik what domain to route to StrangeScout. Change<yourdomain.tld>accordingly.traefik.http.routers.strangescout.entrypoints=websecuretells traefik to redirect traffic to HTTPStraefik.http.routers.strangescout.tls.certresolver=leresolvertells traefik to automatically get HTTPS certificatestraefik.http.routers.strangescout.middlewares=compresstells traefik to compress traffic
The final step is to set the docker network:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | |
Starting StrangeScout¶
We can now start StrangeScout:
1 | |
Setting Up Webhooks¶
StrangeScout supports webhooks from The Blue Alliance API. So set them up, go to your api account on The Blue Alliance, and add a new webhook at url https://<yourdomain.tld>/api/webhook. Follow TBA's guide to set up the webhook. When you send the verification message, the code will be logged to the containers logs, along with the TBA_HMAC header. To finalize setup, add TBA_HMAC as an environment variable in the docker-compose file and set it to the logged TBA-HMAC header, and restart the container.