-
Notifications
You must be signed in to change notification settings - Fork 0
Deploying Autolab with Docker (DEPRECATED)
These are the instructions for setting up Autolab for production usage using Docker. It's the recommended way to deploy an instance of Autolab for real-world usage.
It is a bit opinionated, though. If you're more interested in the essential setup instructions for deploying in production, see Deploying Autolab on Ubuntu. Alternatively, if you're interested in contributing to Autolab, it's easier to just set up a development environment. See Installing Autolab on Ubuntu for these instructions.
- 0. Overview
- 1. Provision a Server
- 2. Prep the Development Environment
- 3. Install Docker & Docker Compose
- 4. Get the Autolab source
- 5. Configure Devise Authentication
- 6. Configure Nginx
- 7. Configure the Production Rails Environment
- 8. HTTPS
- 9. Configure the Tango Backend
- 10. Make Required Volume Directories
- 11. Build and Run the Containers
- 12. Create the Database
- 13. Create an Administrator Account
- Updating
- Tips
- TODO
- Onwards
Here's a list of some of the technologies that are going to be involved in this installation, as well as quick overview of the game plan going forwards:
- Phusion Passenger for serving the core Rails app
- Nginx for serving the static files and playing host to Passenger
- MySQL as required by the Rails app
- Mandrill for sending transactional emails
- Docker for lightweight containerization and reproducible builds
- Docker Compose to orchestrate the whole deal
We'll cover installing Docker, move a few config files into place, and finally use Docker Compose to build and run the application.
This guide starts all the way from the beginning with a bare bones server; if you already have a box that you know you'll be running the installation on, feel free to skip to Step 3.
Unfortunately, we don't have documentation on how to get a domain name
registered. You'll need a custom domain or subdomain to set up Autolab. If
you're doing this for your school, there's a chance you can ask them to give you
access to a subdomain. Otherwise, you can look into DNS registrars like
Namecheap or Gandi to acquire your own domain name. You might be
able to get away with using localhost
or a hard-coded IP address, but this
hasn't been tested.
If you don't already have a server, we recommend a VPS (virtual private server). There are plenty of VPS providers online, so pick your favorite. If you're looking for a recommendation, Digital Ocean is probably the most popular VPS provider right now (and if you sign up with this referral link, you can get enough credit to set up and try out Autolab for for a month for free).
I'll be assuming you're on a standard Ubuntu droplet, but apart from installing Docker there should be no reason why any of the setup instructions are too different.
Once you have a box that you can SSH into, you'll want to do a few simple maintenance tasks to lock it down and prevent spammers from harassing you. These tasks only take 5 minutes, and are all documented in Bryan Kennedy's My First 5 Minutes on a Server. There's only one hiccup with these instructions, and the solution is detailed here.
Now would be a good idea to set up some DNS records that you can use to SSH into your server.
Summary:
- Get a digital ocean droplet
- Run through My First 5 Minutes on a Server
- Set up some DNS records for easy SSH access
We're going to need Git installed eventually, so let's just do it now (again, I'm assuming this is an Ubuntu server):
$ sudo apt-get install git
# Configure Git so that it knows who you are
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
$ git config --global color.ui true
$ git config --global credential.helper cache
Be sure to insert your name and your email address where necessary.
Let's also install pip
, as it'll make installing Docker Compose easier.
$ sudo apt-get install python-pip
(Installing pip
is not strictly required; refer to the Docker Compose
documentation for alternative installation instructions).
Docker has some good installation instructions for Ubuntu available on it's web site.
Follow these steps in particular:
-
Install Docker for Ubuntu
- Also on that page:
- Create a docker group under "Optional Configurations"
- Enable UFW Forwarding under "Optional Configurations"
-
Install Docker Compose
- You can follow the installation instructions that use
pip
if you installed it in the previous step.
- You can follow the installation instructions that use
You can install the Autolab source anywhere on your machine. I'll be using
~/autolab-prod
for this example, but you may want to consider putting it in
/opt
or somewhere where multiple people can access it if there will be
multiple system administrators.
First up is to get the docker-compose.yml
file:
$ git clone https://github.com/autolab/autolab-docker ~/autolab-prod
Next, you'll need to grab the actual Rails app:
# to make sure we're in the repository we just cloned
$ cd ~/autolab-prod
$ git clone https://github.com/autolab/Autolab
(TODO: also clone the Tango source)
You might be thinking, "Git repositories in Git repositories, why not just use submodules?"
Using submodules requires us to make an additional change to the
autolab-docker
repository every time we make a release for Autolab, thus
creating twice the amount of work for us. To make things go smoother, we've
opted not to use submodules here.
More information on how to update your app as releases are made can be found below in the section called Updating.
Next up we have to configure authentication. There are a couple of steps to this.
First, simply copy the templated config file into place. I'll be giving all the relevant filenames relative to the autolab-prod (i.e. parent) repo:
$ cp Autolab/config/initializers/devise.rb{.template,}
Next, generate a new secret key:
$ python -c "import random; print hex(random.getrandbits(512))[2:-1]"
Use this to update the value of config.secret_key
in
Autolab/config/initializers/devise.rb
.
You'll also want to change the hostname in the email address under
config.mailer_sender
(shown below) to the domain you plan to use for viewing
the site.
...
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'creds@<YOUR_WEBSITE>'
...
The specific value doesn't really matter too much; it's only used as the "From" address when sending out new user and password reset instructions.
(TODO: This file is where we can configure omniauth providers, like Facebook or Google logins. This needs to be documented).
First, copy the stock Nginx configuration into place:
$ cp Autolab/docker/nginx{.template,}.conf
Next, you will need to edit server_name
in Autolab/docker/nginx.conf
(snippet shown below) to set the appropriate host name. This should be the host
name where users will access your site.
...
server_name example.com;
...
There are some other settings in this file (currently commented out) relating to SSL that we'll get to a bit later.
Next up we need to configure the production Rails environment; i.e., the
settings Rails uses when we have RAILS_ENV=production
.
The first step is to copy the template into place:
$ cp Autolab/config/environments/production{.template,}.rb
This is a pretty long step, so we've broken it up into a couple sub-steps. All
changes will be done in Autolab/config/environments/production.rb
.
Next up, let's configure email. The Rails app uses email for various features,
include sending out user confirmation emails and instructor-to-student bulk
emails. We recommend that you use Mandrill. They have a very
lenient free tier (12,000 emails/month) and a solid service including
analytics. Update: Mandrill appears to have changed their volume provided
by their free tier. Some alternative services have larger free tiers (for
example Mailgun). Feel free to use any mail provider (including
rolling your own mail server); the configuration should be similar to what's
described below for Mandrill.
-
Create an account at https://mandrill.com/signup/
-
Go to the settings page and create a new API key
-
In
Autolab/config/environments/production.rb
, uncomment theconfig.action_mailer.smtp_settings
block (shown below). Update your username to your Mandrill username and your password to one of your API keys that you've created.# Use a custom smtp server, like Mandrill #config.action_mailer.smtp_settings = { # address: 'smtp.mandrillapp.com', # port: 25, # enable_starttls_auto: true, # authentication: 'login', # user_name: 'MANDRILL_USERNAME', # password: 'MANDRILL_PASSWORD', # domain: 'example.com', #}
-
Change
config.action_mailer.delivery_method
to use raw SMTP:config.action_mailer.delivery_method = :smtp
-
Uncomment
config.action_mailer.default_url_options
(shown below) and fill in your host appropriately. This is the host that Rails will use when generating URL links in emails it sends.# Provide context to the email generator about the host #config.action_mailer.default_url_options = {protocol: 'http', host: 'example.com' }
-
From the Mandrill Domains settings page, add your domain and configure the DKIM and SFF settings by creating TXT records with your DNS provider. They link to some instructions for how to do this, but the process will differ depending on which DNS provider you are using.
To be emailed every time an error occurs in the Rails app, fill in all the
appropriate information for the ExceptionNotification
middleware block, shown
below.
...
config.middleware.use ExceptionNotification::Rack,
email: {
email_prefix: "[Autolab Error] ",
sender_address: "\"NOTIFIER\" <[email protected]>",
exception_recipients: "[email protected]"
}
...
-
email_prefix
andsender_address
can be anything, their values will only affect the way things are displayed for the recipient. -
exception_recipients
should be the email where you'd like to receive exception notifications.
You can run Autolab with or without HTTPS encryption. We strongly recommend you run it with HTTPS.
To set up HTTPS, you'll need to get an SSL certificate. There are many ways you can get one. Here are a few options:
- Go through your school
- Many universities have a program whereby they'll grant SSL certificates to students for free. Some of these programs require you to be using a school-related domain name, but some don't. You should be able to find out more information from your school's IT department.
- If possible, we recommend this option.
- Use StartSSL
- The online service StartSSL offers free single domain SSL certificates. The
catch is that
- they're only free for a single subdomain (wildcard certs cost money)
- their website isn't exactly the most intuitive
- This tutorial offers a pretty comprehensive walkthrough of how to get a free StartSSL certificate
- If you can't get a cert from your school, we recommend this option.
- The online service StartSSL offers free single domain SSL certificates. The
catch is that
- Use a paid service
- There are plenty of services online that offer paid SSL certificates.
- Wait for Let's Encrypt, coming mid-2015
- This is a project that aims to offer free, no-stress SSL certificates for the entire Web.
Take the time now to get yourself a certificate and a key file. The next few steps will show you what to do with them to configure Nginx to use them properly.
In Autolab/docker/nginx.conf
, uncomment the three lines referenced below:
...
# Uncomment these settings to use SSL (you may wish to change the filenames
# appropriately)
#listen 443 ssl;
#ssl_certificate /etc/nginx/ssl/unified.crt;
#ssl_certificate_key /etc/nginx/ssl/my-private-decrypted.key;
# EFF recommended SSL settings
#ssl_prefer_server_ciphers on;
#ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:ECDH+3DES:RSA+AES:RSA+3DES:!ADH:!AECDH:!MD5:!DSS;
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
...
Note: You may want to remove includeSubDomains
if you experience issues
when trying to visit sites on a sister subdomain to the one you've configured
Autolab to work with.
At this point, you can rename unified.crt
and my-private-decrypted.key
to
whatever you want (in the nginx.conf
file above), corresponding to the
certificate and key file that you should have created earlier.
Next up, we need to put the SSL certificate and key file in a place that our
Docker build will know about them. In the same level as the docker-compose.yml
file, run:
$ mkdir -p ssl
Finally, put your certificate and key file in this folder, making sure to match
up the names with the names you provided in your nginx.conf
.
Disabling HTTPS is strongly discouraged. It is documented here only for very special cases. You should exhaust every effort to enable SSL before following these instructions.
To disable HTTPS, just comment out the Rack::SslEnforcer
line in your
production.rb
file (some context given to help you locate it):
...
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
config.middleware.use Rack::SslEnforcer, :except => [ /log_submit/, /local_submit/ ]
...
Currently you have to configure Tango separately from the Dockerized Rails app. (TODO: Add support for Dockerized Tango)
First, copy the configuration file into place:
$ cp Autolab/config/autogradeConfig.rb{.template,}
Then, follow the installation instructions at the Tango Wiki.
The Autolab app requires a couple data volumes to be created: one to hold course submissions and other configuration files, and another to persist the database across containers.
To create them:
$ mkdir -p db-data
$ mkdir -p Autolab/courses
You might want to consider making one or both of these folders symlinks to
folders. Effective use of symlinks can make Autolab management simple. For
example, maybe db-data
is a symlink to a RAID drive for database storage
redundancy, or Autolab/courses
is a symlink to a networked location where
instructors can access their students' submissions from the command line.
Finally, we've reached the point where we can build and run the containers! If everything's gone according to plan, you should be able to run
$ docker-compose up -d
and view your live site! If you've configured your DNS records appropriately,
you can go to your-host.example.com
in your browser to see Autolab running.
Notes:
-
If the process fails with an error like
Cannot start container: Cannot link to a non running container
, see issue #559 for a workaround. -
If you're unfamiliar with or new to Docker and Docker Compose, I'd recommend that you skim over some best practices for what to expect when dealing with Docker.
-
The first time you run
docker-compose up -d
it will take a long time. Docker is downloading and building all the images required to serve the app. This will only happen once, at which point build times will get much faster. You may want to read about Docker caching to find out about how how you can minimize your build times. -
If it hangs after printing "
Fetching source index from https://rubygems.org/
", just give it time. It's runningbundle install
, which is really slow. Luckily, we don't have to run this very often.- Every time there are changes to the Gemfile (i.e., any time an Autolab
developer adds a project dependency), build times will be slow because Docker
has to run a
bundle install
, which is really slow. - If this step gives you a warning not to run
bundle install
as root, just ignore it. It doesn't apply because we're using Docker containers.
- Every time there are changes to the Gemfile (i.e., any time an Autolab
developer adds a project dependency), build times will be slow because Docker
has to run a
-
If the build fails with error
ENOMEM
, it's probably because the amount of memory available on your system is too low for the build to complete. This is fine: Autolab normally takes a small amount of memory, but Docker builds (andbundle install
s) are memory intensive. To get around this, try adding a swapfile to your system. -
If you get hit by a really big wall of text, it's probably just the log from precompiling the static assets. (The filenames should look like a lot of CSS and JS files.)
We'll need to run a one-off command to create the MySQL databases:
$ docker-compose run --rm -e RAILS_ENV=production web rake db:create
This creates a temporary container based of web
as specified in the
docker-compose.yml
file, and uses it to run the rake db:create
command, and
it cleans up after itself when it's done (--rm
).
Similarly, we'll need to migrate the database:
$ docker-compose run --rm -e RAILS_ENV=production web rake db:migrate
Because the docker-compose.yml
file mounted db-data/
as a data volume into
the mysql
container, you'll never have to run db:create
again, and you'll
only have to run db:migrate
if the Autolab developers release an update that
they mention requires a migration.
By now, you should be able to view the app in your web browser. Navigate to the deployed app and sign up for a new account. It should ask for your name, email, and password.
If you configured Mandrill correctly, you will shortly receive an account verification email. Follow the verification link back to the deployed app and sign in with your newly verified account. You should see a page telling you that you are not registered for any courses.
Once you have successfully created an account, you can use the
admin:promote_user
rake task to promote yourself to the admin level (inserting
your email where appropriate; make sure to keep the square brackets):
$ docker-compose run --rm -e RAILS_ENV="production" web rake 'admin:promote_user[[email protected]]'
You are now an administrator of your very own Autolab deployment!
From time to time, the Autolab team releases updates. When release updates become available, you should be able to follow these steps to redeploy an updated version of the app:
# stop the containers, remove them, and delete associated volumes
# (this doesn't delete the data in your host volumes, like db-data/)
$ docker-compose stop && docker-compose rm -v
# get the updated source
$ cd Autolab
$ git pull origin master
# you may want to substitute master for a specific tagged release
$ cd -
# build a new container based on the new code
# depending on the changes introduced, this could take a while
$ docker-compose build web
# While not strictly necessary, you will probably want to clean
# up your old images, volumes, and possibly containers at this
# point. For more information, see
# http://odino.org/spring-cleaning-of-your-docker-containers/
# Run migrations
# This step is only necessary if the release notes for the
# update mention that this release requires migrations, but it
# should be safe to run it even if there aren't migrations to
# be run
$ docker-compose run --rm -e RAILS_ENV=production web rake db:migrate
# Start up the containers again
$ docker-compose up -d
You'll notice that this process can be completely automated if you want it to be.
These are some additional tips to help make sure that you have an awesome experience using Autolab:
By updating often you'll ensure that you have a smooth Autolab experience because you'll be able to do multiple small updates rather than unweildly, all-encompassing updates.
All the config files we touched in this process are ignored by version control, so that people don't accidentally commit their config files to the upstream Autolab source repo.
To have your personal config files all backed up and versioned, you should move
them to a separate folder, say ~/autolab-configs
, make this folder into a Git
repository, and create symlinks to config files in this folder where Autolab
expects there to be config files. For example, you could have a directory
structure that looks like
~
├── autolab-configs
│ ├── config
│ │ └── database.yml
│ └── docker
│ └── nginx.conf
└── autolab-prod
└── Autolab
├── ...
├── config
│ ├── ...
│ └── database.yml -> ~/autolab-configs/config/database.yml
├── ...
├── docker
│ ├── ...
│ └── nginx.conf -> ~/autolab-configs/docker/nginx.conf
└── ...
As you might have noticed, this guide is not entirely complete. This is a list of TODOs for the Autolab developers to remind them what still needs to happen, as well as give the user some insight into what's on deck.
These TODOs will be turned into issues as soon as this pull request lands.
All the instructions to set up Tango on the same host as the local deployment should be just as scripted as the Autolab frontend setup like this was.
Documentation for Devise Omniauth providers is lacking. We should document how
more providers can be added to devise.rb
so that users can enable these if
they want.
This includes the documentation in this file as well as other Autolab pages that reference Devise.
We should also figure out a way to remove "Sign in with you CMU account" from the sign in page. This is relevant for the CMU installation of Autolab, but not for anyone else.
Now that you've got Autolab set up, you should be sure to check out the rest of the documentation on how to create classes and labs and all in all make your life easier with autograding.
If you ran into issues while setting this up, please open an issue or send us an email to let us know. There shouldn't have been that many gotchas (except for maybe setting up DNS settings and configuring your server). The core Autolab Rails app functionality shouldn't be the issue. If it is, we'd really love to know about it so that we can help fix it.
See something wrong or out of date? Did our wording trip you up? Bad documentation sucks for everyone--be sure to let us know if there's something out of place!
-- The Autolab Team