ClientComm uses a number of third-party services to operate. You will need to have credentials with all these services to run ClientComm in production.
- Heroku for hosting the application.
- Twilio for handling messages and phone calls.
- Amazon Web Services for domain management, file storage, and monitoring.
- Mailgun for sending notification and administrative emails.
- LastPass for secrets management.
- Pingdom for uptime monitoring.
- Sentry for error tracking.
- Skylight for performance profiling.
- Mixpanel for analytics.
- Intercom for customer support.
Heroku, Twilio, AWS, and Mailgun are critical services; ClientComm cannot run without them. LastPass, Pingdom, Sentry, Skylight, Mixpanel, and Intercom are useful tools for developing, maintaining, and supporting ClientComm, but are not necessary for it to run. That said, the application as written expects to have all the services above available, so eliminating any of them will require editing application code.
NOTE: All command line examples assume bash as the default shell. If you are using zsh use
=(command)
instead of <(command)
.
We use Terraform to manage ClientComm's infrastructure. Install Terraform
with Homebrew: brew install terraform
; or by downloading the installer.
For each production instance of ClientComm you must provide a backend that points to an s3
terraform backend provider. We put our backend
file in a LastPass secure note named terraform-backend
:
bucket = "[THE NAME OF YOUR TERRAFORM STATE BUCKET]"
region = "[THE AWS REGION, i.e. us-west-1]"
access_key = "[THE AWS ACCESS KEY OF AN ACCOUNT WITH READ/WRITE ACCESS TO THE BUCKET]"
secret_key = "[THE AWS SECRET KEY OF AN ACCOUNT WITH READ/WRITE ACCESS TO THE BUCKET]"
On the command line, use the terraform init
command to point to this backend and specify the key,
or environment name, of the deployment you're managing. We use a deployment name that corresponds
with the subdomain of the deploy; so a demo
deployment name would correspond with an app deployed
to demo.clientcomm.org
:
terraform init -backend-config <(lpass show --notes terraform-backend) -backend-config 'key=[DEPLOYMENT NAME]'
In Twilio, create a new subaccount (if you use them to manage your deploys), then buy an SMS-capable
phone number in the appropriate area code. Configure the A CALL COMES IN webhook
to point to https://[DEPLOYMENT NAME].clientcomm.org/incoming/voice/
and the A MESSAGE COMES IN
webhook to point to https://[DEPLOYMENT NAME].clientcomm.org/incoming/sms/
(see the image below).
On the Alert Triggers page, set up the following triggers to send email to an alerts address (see image below):
- Trigger on ANY alert, at value 1 (First alert of the day)
- Trigger on ANY alert, at value 10 (Alert after 10 issues in a single day)
This will give you early warning if Twilio's having trouble delivering messages to ClientComm.
We use AWS CloudWatch Alarms
to monitor our job queue and alert us if there's activity (or lack of activity) that requires human
attention. You will need to set up an SNS topic
to send events to. Create a SNS topic called cc-alerts
if it doesn't already exist, and add your
alerts email to it as a subscriber. If you name it something other than cc-alerts
, you must update
the corresponding line in the terraform file.
Create a secure note in LastPass called (for example)
clientcomm-personal-terraform-secrets
with the AWS access and secret keys of an account that has
permission to create and destroy resources (Route 53 DNS records, s3 buckets, CloudWatch alarms).
We use IAM credentials unique to each person who is authorized to deploy the application:
aws_access_key = "[DEPLOYER'S AWS ACCESS KEY]"
aws_secret_key = "[DEPLOYER'S AWS SECRET ACCESS KEY]"
Now you're ready to manage a production deployment. We use a secure note in LastPass to contain secrets and specific configuration for each deploy:
mailgun_api_key = ""
mailgun_domain = ""
mailgun_smtp_password = ""
mailgun_require_dkim = "false"
route53_app_zone_id = ""
route53_email_zone_id = ""
app_domain = ""
heroku_api_key = ""
heroku_app_name = ""
heroku_email = ""
papertrail_plan = "papertrail:choklad"
unclaimed_email = ""
unclaimed_password = ""
admin_email = ""
admin_password = ""
devise_secret_key_base = ""
intercom_app_id = ""
intercom_secret_key = ""
mixpanel_token = ""
sentry_deploy_hook = ""
sentry_endpoint = ""
skylight_authentication = ""
time_zone = "Pacific Time (US & Canada)"
twilio_account_sid = ""
twilio_auth_token = ""
twilio_phone_number = ""
report_day = "1"
Many of these variables are self-explanatory, but there are a few details that need further explanation:
route53_app_zone_id
: this variable should point to a zone file that hosts the main domain you wish to use for your deployments. This will be used to create the [deployment].[main_domain].tld CNAME record in your route53 zone that points at Herokuroute53_email_zone_id
: this variable behaves largely the same as app zone ID but is used to create the proper mx and TXT (for SPIF and DKIM) records for sending email with Mailgun, as HSTS prevents us from sharing a domain across the app and Mailgun.app_domain
: the full domain of your deploy, i.e.demo.clientcomm.org
heroku_email
: currently, due to the behavior of the Terraform Heroku provider, you must provide an email associated with a Heroku account that has access to the pipeline you want to use.heroku_app_name
: This must begin with a letter. We recommend a name of the form "clientcomm-[your organizaion]", for example "clientcomm-cfa"papertrail_plan
: Papertrail is a Heroku add-on that manages application logs;papertrail:choklad
is the free tier.unclaimed_email
,unclaimed_password
: used to set up the unclaimed client ClientComm account in the new deploy.admin_email
,admin_password
: used to set up a ClientComm account with admin permissions in the new deploy.devise_secret_key_base
: Devise is the user account authentication system that ClientComm uses; runrake secret
on the command line to generate a value for this field.sentry_deploy_hook
: Used to organize Sentry alerts; set up instructions are here.report_day
: ClientComm will generate and email usage reports one day a week; use this variable to set which day that is. Set from "0" for Sunday to "6" for Saturday.
If you're maintaining multiple deploys, the variables that will definitely need to change between
deploys are: mailgun_domain
, app_domain
, heroku_app_name
, unclaimed_email
,
unclaimed_password
, admin_email
, admin_password
, devise_secret_key_base
, time_zone
,
twilio_account_sid
, twilio_auth_token
, and twilio_phone_number
.
Once you have created and saved the secure note in LastPass you are ready to deploy. First get Terraform's plan for the deploy:
terraform plan -var-file <(lpass show --notes clientcomm-personal-terraform-secrets)
If you believe the plan accurately reflects the changes or additions you wish to make, run apply:
terraform apply -var-file <(lpass show --notes clientcomm-personal-terraform-secrets)
There is a manual step during the deploy; the Heroku Scheduler interface will launch. Add two jobs; one for the Twilio status update rake task to run every 10 minutes:
rake messages:update_twilio_statuses
And one for the usage report rake task to run once a day:
rake reports:generate_and_send_reports
Although generate_and_send_reports
will run daily, it'll only send emails when the day of the week
matches the value of the report_day
variable mentioned above.
There are a few finishing touches that must be done manually.
You'll need to log in to Mailgun to verify the email domain. Click on the Domains menu, click the new domain that was just created, and click the Check DNS Records Now button.
On Pingdom, create a new uptime check to point to the new deploy's front page. It should check once a minute, alert after 2 minutes down; and the Slack webhook integration should be checked if you use Slack to manage alerts.
If you have a help page for your deploy, you can add a link to it in the menu bar by
setting the HELP_LINK
config variable like so:
heroku set:config HELP_LINK='https://example.com/' --app [APP-NAME]
When clients are deactivated in ClientComm, the user is presented with a survey that must be filled out before the deactivation can proceed. To create this survey on your deploy, start up a rails console on the remote server with the Heroku CLI:
heroku run rails c --app [APP-NAME]
Then create a survey question:
SurveyQuestion.create!(text: 'What was the outcome for this client?')
...and the multiple-choice responses:
question = SurveyQuestion.last
response_texts = ['Successful termination', 'Unsuccessful termination', 'Other / not applicable']
response_texts.each do |text|
SurveyResponse.create!(survey_question: question, text: text)
end