Deploying to Heroku
Before deploying
Start by making sure that you've gone through our notes of some things to consider before deploying.
Why Heroku?
Heroku is a PaaS provider that takes care of all network and hardware maintenance requirements for running web applications.
It also makes the deployment and update process extremely simple when compared to the use of traditional IaaS providers.
Steps on Heroku
Begin by signing up on Heroku, and familiarizing yourself with how Ruby apps run on Heroku.
Set up the Heroku app
Create a new Heroku app, to which we'll deploy Dalasa.
Configure your new Heroku app using environment variables.
- Add configuration for the file storage service.
- Add configuration for the email service.
- Set environment variable
ASSET_HOST
to your app's fully qualified domain name (FQDN), which should look likemy-app-name.herokuapp.com
. - Set environment variable
PREPARE_FOR_PRECOMPILATION
totrue
. - Set environment variable
YARN_PRODUCTION
tofalse
.
There are more optional features that you can enable - read through the sections below.
Add the new Heroku app as a git remote.
Push the repository to your Heroku app:
git push heroku master
.
This should leave you with a Heroku app that already has an empty Postgres database attached to it.
Set up the database
Set up the database using the schema, and seed a few basic entries into the database. We'll use the Heroku CLI to execute the Rails tasks on the production environment.
heroku run rails db:schema:load
heroku run rails db:seed
Set up a user to sign in with
At this point, the database should have a single user in it: [email protected]
. You should set a password for this
user and use it to gain access to the platform.
We'll start a Rails console on Heroku to do so:
heroku run console
Once the console is ready, find and update the user entry.
user = User.find_by(email: '[email protected]')
user.update!(
password: 'a secure password',
password_confirmation: 'a secure password',
)
You should discard this user, later, via the school administration interface once you've enrolled yourself as a school admin.
Set a primary domain
Let's inform the application about its domain address. On the Heroku console, run:
School.first.domains.create!(fqdn: 'my-app-name.herokuapp.com', primary: true)
Change my-app-name.herokuapp.com
to match your actual fully qualified domain name.
You can have more than one domain responding to requests, so you can use this same process to add more custom domains.
Make sure that only one domain is set to primary: true
. This primary domain will be used to generate URLs in emails
and such.
Start the dynos
Finally, start the web and worker dynos on Heroku.
heroku ps:scale web=1 worker=1
Now, if you visit the web address for your Heroku app, you should see the homepage for your school. You should also be able to sign in as [email protected]
to start working on your school.
Scheduling periodic tasks
There are a few tasks that must be run scheduled to run periodically; this can be done using Heroku's Scheduler add-on.
cleanup
(daily) - used to perform general database cleanup of orphaned entries.daily_digest
(daily) - sends a daily digest of updates via email to all users in the school.notify_and_delete_inactive_users
(daily) - checks for inactive users, notifies those who are a month away from deletion, and deletes notified users after the configured time.
- Add the Scheduler add-on on Heroku.
heroku addons:create scheduler:standard
- Open the Scheduler dashboard for your app.
heroku addons:open scheduler
- Add the the jobs using the Add Job option in the dashboard. Schedule both tasks to run as per the requirements noted above.
File storage using AWS
To allow users to upload files, and to retrieve them, we'll use AWS's S3. The service has extensive documentation.
The following process is overly simplified, but is what you'll broadly need to do:
- Create a new S3 bucket to store uploaded files.
- Set up an IAM user with read & write permissions on the bucket.
- Configure Dalasa to use the newly created bucket using the correct credentials. Refer
AWS_*
keys inexample.env
.
Sending emails with Postmark
To set up Dalasa to send transactional emails, you'll need to create a Postmark account, and add the POSTMARK_API_TOKEN
environment variable with your account's API token.
Before proceeding with the next step, finish Postmark's account approval process, and make sure that outbound emails (such as sign-in emails) to domains other than your own are working.
Setting up the bounce and spam complaint webhook
You can configure Dalasa to block sending of emails to user addresses that are hard-bouncing, or where the users have complained that messages are spam. To do so, create a webhook once you've gotten outbound mails working.
- You can create webhooks by logging into your Postmark account, and heading to Servers > Your Server > Your Message Stream > Webhooks > Add Webhook.
- The webhook should be pointed to:
https://your.school.domain/users/email_bounce
. - The Bounce and Spam Complaint options should be the events that are selected - there is no need to include the message content.
- Add some Basic auth credentials, and use those values to configure the
POSTMARK_HOOK_ID
andPOSTMARK_HOOK_SECRET
environment variables on Heroku.
Performance and error monitoring with New Relic
To enable performance and error monitoring with New Relic, sign up for a New Relic account and configure its credentials using the NEW_RELIC_LICENSE_KEY
key.
Adding Memcached Cloud as cache store for API rate limiting
You need to add a cache store to handle API rate limiting in the application.
- Add the Memcached Cloud add-on on Heroku.
heroku addons:create memcachedcloud
- Configure the
GRAPH_API_RATE_LIMIT
environment variable on Heroku to the permitted requests per second.
Signing in with OAuth
Warning: These instructions, for signing in with OAuth, are rough. This feature will need to be made configurable before its documentation can be expanded / re-written.
- Create OAuth apps for Google, Github, and Facebook, setting the redirect URI for each of these apps to
https://your.school.domain/users/auth/SERVICE/callback
, where service is one ofgithub
,facebook
, orgoogle_oauth2
. - Set credentials for OAuth apps using environment variables (find required keys in
example.env
). - Set the
SSO_DOMAIN
environment variable to your fully qualified domain name (your.school.domain
, for example).
Direct Upload to Vimeo
To enable direct uploads to a Vimeo account from the curriculum editor, add the VIMEO_ACCESS_TOKEN
and VIMEO_ACCOUNT_TYPE
(basic
, plus
, pro
, business
, premium
) environment variables.
Make sure that the access token has the following scopes enabled:
private
create
edit
upload
video_files
Note: You cannot upload private videos if your Vimeo account type is
basic
.
Webpush Notifications
To enable webpush notification you will have to set mandatory environment variable VAPID_PUBLIC_KEY
and VAPID_PRIVATE_KEY
.
You can generate the keys by running the following on the server. (Detailed Doc)
vapid_key = Webpush.generate_key
#VAPID_PUBLIC_KEY
vapid_key.public_key
#VAPID_PRIVATE_KEY
vapid_key.private_key
Content Delivery Network
To enable delivery of user-uploaded files through a CDN, you will have to set Cloudfront environment variables.
Create a Cloudfront public key to generate signed URLs with canned policy.
Create a cloudfront distribution for accessing the private AWS S3 contents with signed URLs.
Set up the required environment variables:
# Bas64 encoded private key used for generating the cloudfront public key
CLOUDFRONT_PRIVATE_KEY_BASE_64_ENCODED=cloudfront_private_key_from_aws
# Cloudfront hostname
CLOUDFRONT_HOST=cloudfront_host_from_aws
# Cloudfront public key pair ID
CLOUDFRONT_KEY_PAIR_ID=cloudfront_key_pair_id_from_aws
# An integer in seconds used to compute the expiry time for the signed URL
CLOUDFRONT_EXPIRY=expiry_in_seconds
Troubleshooting
If you're encountering crashes or errors, the first thing you should do is check the server logs. You can watch the Rails production.log
file on Heroku by using the logs
command:
heroku logs --tail