Skip to content

Commit 24ef3c2

Browse files
committed
Terraform GCP with Kamal v2
1 parent 05f03e1 commit 24ef3c2

File tree

18 files changed

+589
-44
lines changed

18 files changed

+589
-44
lines changed

.gitignore

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,45 @@
3535

3636
/app/assets/builds/*
3737
!/app/assets/builds/.keep
38+
39+
/config/credentials/production.key
40+
41+
### Terraform template
42+
# Local .terraform directories
43+
**/.terraform/*
44+
45+
# .tfstate files
46+
./terraform-gcloud/terraform-state/
47+
*.tfstate
48+
*.tfstate.*
49+
50+
# Crash log files
51+
crash.log
52+
crash.*.log
53+
54+
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
55+
# password, private keys, and other secrets. These should not be part of version
56+
# control as they are data points which are potentially sensitive and subject
57+
# to change depending on the environment.
58+
*.tfvars
59+
*.tfvars.json
60+
61+
# Ignore override files as they are usually used to override resources locally and so
62+
# are not checked in
63+
override.tf
64+
override.tf.json
65+
*_override.tf
66+
*_override.tf.json
67+
68+
# Ignore transient lock info files created by terraform apply
69+
.terraform.tfstate.lock.info
70+
71+
# Include override files you do wish to add to version control using negated pattern
72+
# !example_override.tf
73+
74+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
75+
# example: *tfplan*
76+
77+
# Ignore CLI configuration files
78+
.terraformrc
79+
terraform.rc

.kamal/secrets

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
1+
# Use gcloud to read secrets from GCP Secret Manager
2+
# First, load the project_id from Terraform outputs
3+
PROJECT_ID=$(cd ./terraform-gcloud && terraform output -raw project_id)
4+
5+
# Fetch secrets from Google Cloud Secrets Manager using the project ID
6+
# Edit secrets in GCP Secret Manager web UX:
7+
KAMAL_REGISTRY_PASSWORD=$(gcloud secrets versions access latest --secret=KAMAL_REGISTRY_PASSWORD --project="$PROJECT_ID")
8+
9+
DB_PASSWORD=$(gcloud secrets versions access latest --secret=DB_PASSWORD --project="$PROJECT_ID")
10+
11+
SECRET_KEY_BASE=$(gcloud secrets versions access latest --secret=SECRET_KEY_BASE --project="$PROJECT_ID")
12+
13+
# Use this if you want to use Rails credentials
14+
# RAILS_MASTER_KEY=$(gcloud secrets versions access latest --secret=RAILS_MASTER_KEY --project="$PROJECT_ID")
15+
16+
# Possibly useful comments that you can probably ignore are below.
117
# Secrets defined here are available for reference under registry/password, env/secret, builder/secrets,
218
# and accessories/*/env/secret in config/deploy.yml. All secrets should be pulled from either
319
# password manager, ENV, or a file. DO NOT ENTER RAW CREDENTIALS HERE! This file needs to be safe for git.
420

5-
# Example of extracting secrets from 1password (or another compatible pw manager)
6-
# SECRETS=$(kamal secrets fetch --adapter 1password --account your-account --from Vault/Item KAMAL_REGISTRY_PASSWORD RAILS_MASTER_KEY)
7-
# KAMAL_REGISTRY_PASSWORD=$(kamal secrets extract KAMAL_REGISTRY_PASSWORD ${SECRETS})
8-
# RAILS_MASTER_KEY=$(kamal secrets extract RAILS_MASTER_KEY ${SECRETS})
9-
1021
# Use a GITHUB_TOKEN if private repositories are needed for the image
1122
# GITHUB_TOKEN=$(gh config get -h github.com oauth_token)
12-
1323
# Grab the registry password from ENV
14-
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
24+
# KAMAL_REGISTRY_PASSWORD=${KAMAL_REGISTRY_PASSWORD}
1525

16-
# Improve security by using a password manager. Never check config/master.key into git!
17-
RAILS_MASTER_KEY=$(cat config/master.key)
26+
# Use op to read secrets from 1password directly because using kamal secret commands results in parse errors
27+
# KAMAL_REGISTRY_PASSWORD=$(op read op://kamal-demo/Items/KAMAL_REGISTRY_PASSWORD/password)
28+
# RAILS_MASTER_KEY=$(op read op://kamal-demo/Items/RAILS_MASTER_KEY/password)

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ WORKDIR /rails
1616

1717
# Install base packages
1818
RUN apt-get update -qq && \
19-
apt-get install --no-install-recommends -y curl libjemalloc2 libvips postgresql-client && \
19+
apt-get install --no-install-recommends -y curl libjemalloc2 libvips postgresql-client iputils-ping && \
2020
rm -rf /var/lib/apt/lists /var/cache/apt/archives
2121

2222
# Set production environment

Procfile.dev

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
web: bin/rails server
22
css: bin/rails tailwindcss:watch
3+
db: docker-compose up db

bin/kamal

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,10 @@ end
2424
require "rubygems"
2525
require "bundler/setup"
2626

27+
require_relative '../lib/deployment_manager'
28+
29+
unless DeploymentManager.new.deployed_ip_matches_configured_ip?
30+
abort("Rerun './terraform-gcloud/bin/stand-up' to fix this or change the host IP directly in 'config/deploy.yml'")
31+
end
32+
2733
load Gem.bin_path("kamal", "kamal")

config/database.yml

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,32 +60,15 @@ test:
6060
<<: *default
6161
database: rails_kamal_demo_test
6262

63-
# As with config/credentials.yml, you never want to store sensitive information,
64-
# like your database password, in your source code. If your source code is
65-
# ever seen by anyone, they now have access to your database.
66-
#
67-
# Instead, provide the password or a full connection URL as an environment
68-
# variable when you boot the app. For example:
69-
#
70-
# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase"
71-
#
72-
# If the connection URL is provided in the special DATABASE_URL environment
73-
# variable, Rails will automatically merge its configuration values on top of
74-
# the values provided in this file. Alternatively, you can specify a connection
75-
# URL environment variable explicitly:
76-
#
77-
# production:
78-
# url: <%= ENV["MY_APP_DATABASE_URL"] %>
79-
#
8063
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
8164
# for a full overview on how database connection configuration can be specified.
82-
#
65+
# The values here need to correspond to the values in the `terraform-gcloud/main.tf` file.
66+
# The password comes from ENV variable DB_PASSWORD.
8367
production:
8468
primary: &primary_production
8569
<<: *default
8670
database: rails_kamal_demo_production
87-
username: rails_kamal_demo
88-
password: <%= ENV["RAILS_KAMAL_DEMO_DATABASE_PASSWORD"] %>
71+
username: rails_user
8972
cache:
9073
<<: *primary_production
9174
database: rails_kamal_demo_production_cache

config/deploy.yml

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
1+
# This deploy.yml file is configured to work with the kamal_tf script.
2+
# Please use the kamal_tf script to run kamal commands with dynamic IP addresses from Terraform.
3+
# Example usage: bin/kamal_tf deploy
4+
15
# Name of your application. Used to uniquely configure containers.
26
service: rails_kamal_demo
37

48
# Name of the container image.
5-
image: your-user/rails_kamal_demo
9+
image: shakacodedemo/rails_kamal_demo
610

711
# Deploy to these servers.
812
servers:
9-
web:
10-
- 192.168.0.1
11-
# job:
12-
# hosts:
13-
# - 192.168.0.1
14-
# cmd: bin/jobs
13+
web: # Next value is set by Terraform script "stand-up" in sibling repo
14+
- 34.59.165.111
15+
# job:
16+
# hosts:
17+
# - 34.59.165.111
18+
# cmd: bin/jobs
1519

1620
# Enable SSL auto certification via Let's Encrypt and allow for multiple apps on a single web server.
1721
# Remove this section when using multiple web servers and ensure you terminate SSL at your load balancer.
1822
#
1923
# Note: If using Cloudflare, set encryption mode in SSL/TLS setting to "Full" to enable CF-to-app encryption.
24+
# uncomment next line for a real host name
2025
proxy:
2126
ssl: true
22-
host: app.example.com
27+
# IMPT: Edit for your real host name
28+
host: gcp.kamaltutorial.com
2329

2430
# Credentials for your image host.
2531
registry:
2632
# Specify the registry server, if you're not using Docker Hub
2733
# server: registry.digitalocean.com / ghcr.io / ...
28-
username: your-user
34+
# IMPT: Edit for your real Docker Hub username
35+
username: shakacodedemo
2936

3037
# Always use an access token rather than real password when possible.
3138
password:
@@ -34,12 +41,16 @@ registry:
3441
# Inject ENV variables into containers (secrets come from .kamal/secrets).
3542
env:
3643
secret:
37-
- RAILS_MASTER_KEY
44+
- DB_PASSWORD
45+
- SECRET_KEY_BASE
3846
clear:
3947
# Run the Solid Queue Supervisor inside the web server's Puma process to do jobs.
4048
# When you start using multiple servers, you should split out job processing to a dedicated machine.
4149
SOLID_QUEUE_IN_PUMA: true
4250

51+
# This is the networking to get to host machine from within the Rails docker container
52+
DB_HOST: 172.18.0.1
53+
4354
# Set number of processes dedicated to Solid Queue (default: 1)
4455
# JOB_CONCURRENCY: 3
4556

@@ -61,13 +72,11 @@ aliases:
6172
logs: app logs -f
6273
dbc: app exec --interactive --reuse "bin/rails dbconsole"
6374

64-
6575
# Use a persistent storage volume for sqlite database files and local Active Storage files.
6676
# Recommended to change this to a mounted volume path that is backed up off server.
6777
volumes:
6878
- "rails_kamal_demo_storage:/rails/storage"
6979

70-
7180
# Bridge fingerprinted assets, like JS and CSS, between versions to avoid
7281
# hitting 404 on in-flight requests. Combines all files from new and old
7382
# version inside the asset_path.
@@ -88,8 +97,8 @@ builder:
8897
# - RAILS_MASTER_KEY
8998

9099
# Use a different ssh user than root
91-
# ssh:
92-
# user: app
100+
ssh:
101+
user: justin
93102

94103
# Use accessory services (secrets come from .kamal/secrets).
95104
# accessories:
@@ -114,3 +123,7 @@ builder:
114123
# port: 6379
115124
# directories:
116125
# - data:/data
126+
127+
# Configure rolling deploys by setting a wait time between batches of restarts.
128+
# 30 is the default. First deploy will need a longer time to create the database.
129+
deploy_timeout: 30

config/puma.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,6 @@
3939
# Specify the PID file. Defaults to tmp/pids/server.pid in development.
4040
# In other environments, only set the PID file if requested.
4141
pidfile ENV["PIDFILE"] if ENV["PIDFILE"]
42+
43+
# test change to see if this gets server to connect to kamal-proxy
44+
# bind "tcp://0.0.0.0:3000"

0 commit comments

Comments
 (0)