Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .kamal/secrets → .kamal/secrets-common
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,5 @@
# KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD

# Improve security by using a password manager. Never check config/master.key into git!
RAILS_MASTER_KEY=$(cat config/credentials/production.key)

KAMAL_REGISTRY_PASSWORD=$(aws ecr get-login-password --region us-east-2)
3 changes: 3 additions & 0 deletions .kamal/secrets.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Secrets for `kamal <command> -d production`. Shared secrets live in .kamal/secrets-common.
# DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
RAILS_MASTER_KEY=$(cat config/credentials/production.key)
3 changes: 3 additions & 0 deletions .kamal/secrets.staging
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Secrets for `kamal <command> -d staging`. Shared secrets live in .kamal/secrets-common.
# DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
RAILS_MASTER_KEY=$(cat config/credentials/staging.key)
5 changes: 4 additions & 1 deletion config/cable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ development:
test:
adapter: test

production:
production: &solid_cable
adapter: solid_cable
connects_to:
database:
writing: cable
polling_interval: 0.1.seconds
message_retention: 1.day

staging:
<<: *solid_cable
4 changes: 4 additions & 0 deletions config/cache.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ test:
production:
database: cache
<<: *default

staging:
database: cache
<<: *default
1 change: 1 addition & 0 deletions config/credentials/staging.yml.enc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eeoCByo6ZKfHPIAiUs+RWlMG6ctONoh7PtOa+YhVOHmJ+Cyx/g8veArB8vviyXaXJKDSnTVKGtmN4iFkRmv8U80LVXuIrguyLPU71VhTVjN6D/Z3msO8lE4EuFVqmm2nSgwxqv3kNsnzq0PvUaFka/gLMGYiJc1lxnqNaa49uLPPoGO6ou8HwarmXNfUsiga7P6NIgltzccC6kEqxbfriBophSo4vzLdYCo1jfkb01IFa1TALIB3r6HZ68dFXLiKaXdjEu0f1u0gL0wOajGbl0ov8MEhGMr0sQUV/BjjEy65JNSYU/95OCoZxbljVgYpSX+DYuCrEdSDqOVL6d/icFGSrQZ3SnRWHtE4xi/38m4J77WYwO8m8VE1tcWCOgLNfXKQcy+lQIBWOThypclncYLTuCXZYGucKwd6GtRpL2pWcskP0vKwNSXtDauLp/mdOCiOA3JXr8rkxsEiwKtH9PlBHDQnSczjW+x+aFk5M36/7JkPLgNKQXfJ--1UqKYQAZ+lgiu89x--T/GJd6zjnSiOqNo1NLjbsw==
18 changes: 18 additions & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,21 @@ production:
<<: *default
database: storage/production_cable.sqlite3
migrations_paths: db/cable_migrate

# Staging uses its own database files in the same storage/ volume as production.
staging:
primary:
<<: *default
database: storage/staging.sqlite3
cache:
<<: *default
database: storage/staging_cache.sqlite3
migrations_paths: db/cache_migrate
queue:
<<: *default
database: storage/staging_queue.sqlite3
migrations_paths: db/queue_migrate
cable:
<<: *default
database: storage/staging_cable.sqlite3
migrations_paths: db/cable_migrate
14 changes: 14 additions & 0 deletions config/deploy.staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Staging destination. Deploy with: bin/kamal deploy -d staging
# Values here are merged over config/deploy.yml.

servers:
web:
- 18.117.181.111

ssh:
user: ec2-user
keys: ["~/.ssh/2026rfg-staging.pem"]

env:
clear:
RAILS_ENV: staging
24 changes: 12 additions & 12 deletions config/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ service: endsideout
# Name of the container image (use your-user/app-name on external registries).
image: endsideout

# Deploy to these servers.
servers:
web:
- 18.117.181.111
# job:
# hosts:
# - 192.168.0.1
# cmd: bin/jobs
# Always deploy to a named destination (config/deploy.<destination>.yml), for example `bin/kamal deploy -d staging`.
require_destination: true

# Servers are set per destination.
# servers:
# web:
# - 192.168.0.1
# job:
# hosts:
# - 192.168.0.1
# cmd: bin/jobs

# Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server.
# If used with Cloudflare, set encryption mode in SSL/TLS setting to "Full" to enable CF-to-app encryption.
Expand Down Expand Up @@ -97,10 +100,7 @@ builder:
# - GITHUB_TOKEN
- RAILS_MASTER_KEY

# Use a different ssh user than root
ssh:
user: ec2-user
keys: ["~/.ssh/2026rfg-staging.pem"]
# The ssh user and keys are set per destination.


# Use accessory services (secrets come from .kamal/secrets).
Expand Down
4 changes: 2 additions & 2 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# config.action_mailer.raise_delivery_errors = false

# Set host to be used by links generated in mailer templates.
config.action_mailer.default_url_options = { host: "staging-classroom.endsideout.org", protocol: "https" }
config.action_mailer.default_url_options = { host: "classroom.endsideout.org", protocol: "https" }

# Specify outgoing SMTP server. Remember to add smtp/* credentials via bin/rails credentials:edit.
# config.action_mailer.smtp_settings = {
Expand All @@ -81,7 +81,7 @@

# Enable DNS rebinding protection and other `Host` header attacks.
config.hosts = [
"staging-classroom.endsideout.org"
"classroom.endsideout.org"
]

# Skip DNS rebinding protection for the default health check endpoint.
Expand Down
8 changes: 8 additions & 0 deletions config/environments/staging.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require_relative "production"

Rails.application.configure do
staging_host = "staging-classroom.endsideout.org"

config.action_mailer.default_url_options = { host: staging_host, protocol: "https" }
config.hosts = [ staging_host ]
end
3 changes: 3 additions & 0 deletions config/queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ test:

production:
<<: *default

staging:
<<: *default
5 changes: 4 additions & 1 deletion config/recurring.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
# priority: 2
# schedule: at 5am every day

production:
production: &production
clear_solid_queue_finished_jobs:
command: "SolidQueue::Job.clear_finished_in_batches(sleep_between_batches: 0.3)"
schedule: every hour at minute 12

staging:
<<: *production
29 changes: 29 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Deployment

## Configuring AWS Instance
Kamal's deployment model includes a proxy that runs on the instance and handles the app via a blue/green deployment model.
During deployment the current version of the app is running while the new version is being deployed.
During the deployment process, the proxy runs status checks on the new version of the app to ensure it is healthy before switching traffic over to it.
This approach means that during deployment, two versions of the app are running at the same time, which can cause memory issues if the instance is too small.
When choosing an instance you either need to ensure the instance has enough memory to run two versions of the app at the same time, or you need to add swap space to the instance to ensure it doesn't run out of memory during deployment.
If you choose to add swap space, you need to ensure the instance has a big enough volume to add swap space.
*AWS defaults to 8GB volumes, which is realistically not enough to add swap space (or honestly to not run into other issues).* Be sure that you choose a volume size that is big enough to add swap space. 20 GB is a good minimum.

## Secrets and Credentials
### Rails Credentials
The encryption keys for Rails credentials are stored in AWS Secrets Manager.
In order to deploy you need to create a key file in the config/credentials folder such as `config/credentials/staging.key` with the value from secrets manager.
*These files should remain gitignored and not be checked into source control.*

### SSH Keys
Kamal uses SSH to connect to the instance and deploy the application. This key is stored in AWS Secrets Manager and needs to be downloaded and placed in the `~/.ssh/` folder with permissions set to 600.
Note you should use the same file name referenced for the key in the environment specific deployment configuration. For example [deploy.staging.yml](../config/deploy.staging.yml)

## AWS CLI
You need to be logged into the AWS CLI to deploy. You can use `aws configure` to set up your credentials.
You can make a named profile for this AWS account if you have multiple AWS accounts using `aws configure --profile your_profile_name`.
To ensure that kamal uses the correct profile, run EXPORT AWS_PROFILE=your_profile_name to set the profile for the current terminal session.

## Important Gotchas
- We have configured kamal to use explicit deploy targets. Therefore you always need to specify the target environment when using any kamal command. For example, `bin/kamal deploy -d staging`
- Kamal only deploys committed code. If you have uncommitted changes, they will not be deployed.
Loading