diff --git a/.kamal/secrets.staging b/.kamal/secrets.staging index 46eccf3fd..da2952efa 100644 --- a/.kamal/secrets.staging +++ b/.kamal/secrets.staging @@ -1,6 +1,12 @@ -SECRETS=$(kamal secrets fetch --adapter 1password --account basecamp --from Deploy/Fizzy Deployments/BASECAMP_REGISTRY_PASSWORD Deployments/DASH_BASIC_AUTH_SECRET Staging/RAILS_MASTER_KEY) +SECRETS=$(kamal secrets fetch --adapter 1password --account basecamp --from Deploy/Fizzy Deployments/BASECAMP_REGISTRY_PASSWORD Deployments/DASH_BASIC_AUTH_SECRET Staging/RAILS_MASTER_KEY Staging/MYSQL_ALTER_PASSWORD Staging/MYSQL_ALTER_USER Staging/MYSQL_APP_PASSWORD Staging/MYSQL_APP_USER Staging/MYSQL_READONLY_PASSWORD Staging/MYSQL_READONLY_USER) GITHUB_TOKEN=$(gh config get -h github.com oauth_token) BASECAMP_REGISTRY_PASSWORD=$(kamal secrets extract BASECAMP_REGISTRY_PASSWORD $SECRETS) DASH_BASIC_AUTH_SECRET=$(kamal secrets extract DASH_BASIC_AUTH_SECRET $SECRETS) RAILS_MASTER_KEY=$(kamal secrets extract RAILS_MASTER_KEY $SECRETS) +MYSQL_ALTER_PASSWORD=$(kamal secrets extract MYSQL_ALTER_PASSWORD $SECRETS) +MYSQL_ALTER_USER=$(kamal secrets extract MYSQL_ALTER_USER $SECRETS) +MYSQL_APP_PASSWORD=$(kamal secrets extract MYSQL_APP_PASSWORD $SECRETS) +MYSQL_APP_USER=$(kamal secrets extract MYSQL_APP_USER $SECRETS) +MYSQL_READONLY_PASSWORD=$(kamal secrets extract MYSQL_READONLY_PASSWORD $SECRETS) +MYSQL_READONLY_USER=$(kamal secrets extract MYSQL_READONLY_USER $SECRETS) diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint index 4f8ccb547..ad59377a4 100755 --- a/bin/docker-entrypoint +++ b/bin/docker-entrypoint @@ -2,7 +2,7 @@ # If running the rails server then create or migrate existing database if [ "${1}" == "./bin/thrust" ] && [ "${2}" == "./bin/rails" ] && [ "${3}" == "server" ]; then - ./bin/rails db:prepare + MIGRATE=1 ./bin/rails db:prepare fi exec "${@}" diff --git a/config/database.yml b/config/database.yml index 513794386..2b5085410 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,7 +1,20 @@ +<% + if ENV["MIGRATE"].present? + mysql_app_user_key = "MYSQL_ALTER_USER" + mysql_app_password_key = "MYSQL_ALTER_PASSWORD" + else + mysql_app_user_key = "MYSQL_APP_USER" + mysql_app_password_key = "MYSQL_APP_PASSWORD" + end + + mysql_app_user = ENV[mysql_app_user_key] + mysql_app_password = ENV[mysql_app_password_key] +%> + default: &default adapter: trilogy - host: <%= ENV.fetch "DB_HOST", "127.0.0.1" %> - port: <%= ENV.fetch "DB_PORT", 33380 %> + host: <%= ENV.fetch "FIZZY_DB_HOST", "127.0.0.1" %> + port: <%= ENV.fetch "FIZZY_DB_PORT", 3306 %> pool: 50 timeout: 5000 @@ -9,22 +22,27 @@ development: primary: <<: *default database: fizzy_development + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> replica: <<: *default database: fizzy_development replica: true + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> cable: <<: *default database: development_cable migrations_paths: db/cable_migrate + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> cache: <<: *default database: development_cache migrations_paths: db/cache_migrate + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> queue: <<: *default database: development_queue migrations_paths: db/queue_migrate + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". @@ -33,27 +51,48 @@ test: primary: <<: *default database: fizzy_test + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> replica: <<: *default database: fizzy_test + port: <%= ENV.fetch "FIZZY_DB_PORT", 33380 %> replica: true production: &production primary: <<: *default - database: fizzy_<%= Rails.env %> + database: fizzy_production + host: <%= ENV["MYSQL_DATABASE_HOST"] %> + username: <%= mysql_app_user %> + password: <%= mysql_app_password %> + replica: + <<: *default + database: fizzy_production + host: <%= ENV["MYSQL_DATABASE_REPLICA_HOST"] %> + username: <%= ENV["MYSQL_READONLY_USER"] %> + password: <%= ENV["MYSQL_READONLY_PASSWORD"] %> + replica: true cable: <<: *default - database: <%= Rails.env %>_cable + database: fizzy_solidcable_production + host: <%= ENV["MYSQL_SOLID_CABLE_HOST"] %> + username: <%= mysql_app_user %> + password: <%= mysql_app_password %> migrations_paths: db/cable_migrate - cache: - <<: *default - database: <%= Rails.env %>_cache - migrations_paths: db/cache_migrate queue: <<: *default - database: <%= Rails.env %>_queue + database: fizzy_solidqueue_production + host: <%= ENV["MYSQL_SOLID_QUEUE_HOST"] %> + username: <%= mysql_app_user %> + password: <%= mysql_app_password %> migrations_paths: db/queue_migrate + cache: + <<: *default + database: fizzy_solidcache_production + host: <%= ENV["MYSQL_SOLID_CACHE_HOST"] %> + username: <%= mysql_app_user %> + password: <%= mysql_app_password %> + migrations_paths: db/cache_migrate beta: *production staging: *production diff --git a/config/deploy.production.yml b/config/deploy.production.yml index 6ae1172ce..fd8bf9b12 100644 --- a/config/deploy.production.yml +++ b/config/deploy.production.yml @@ -1,21 +1,18 @@ servers: web: hosts: - - fizzy-app-101.df-iad-int.37signals.com - - fizzy-app-102.df-iad-int.37signals.com - - fizzy-app-01.sc-chi-int.37signals.com - - fizzy-app-02.sc-chi-int.37signals.com - - fizzy-app-401.df-ams-int.37signals.com - - fizzy-app-402.df-ams-int.37signals.com + - fizzy-app-01.sc-chi-int.37signals.com: sc_chi + - fizzy-app-02.sc-chi-int.37signals.com: sc_chi + - fizzy-app-101.df-iad-int.37signals.com: df_iad + - fizzy-app-102.df-iad-int.37signals.com: df_iad + - fizzy-app-401.df-ams-int.37signals.com: df_ams + - fizzy-app-402.df-ams-int.37signals.com: df_ams labels: otel_scrape_enabled: true jobs: hosts: - - fizzy-app-101.df-iad-int.37signals.com - options: - # NFS mount for backups - # See https://3.basecamp.com/2914079/buckets/37331921/todos/9175385847 - mount: type=volume,src=backups,dst=/backups,volume-driver=local,volume-opt=type=nfs,volume-opt=device=:/fizzy-production-backups,"volume-opt=o=addr=purestorage.sc-chi-int.37signals.com,nfsvers=3,rw,noatime,nconnect=8,soft,timeo=30,retrans=2" + - fizzy-app-101.df-iad-int.37signals.com: df_iad + - fizzy-app-102.df-iad-int.37signals.com: df_iad labels: otel_scrape_enabled: true @@ -28,6 +25,26 @@ ssh: env: clear: RAILS_ENV: production + MYSQL_DATABASE_HOST: fizzy-mysql-primary + MYSQL_DATABASE_REPLICA_HOST: fizzy-mysql-replica + MYSQL_SOLID_CABLE_HOST: fizzy-mysql-primary + MYSQL_SOLID_QUEUE_HOST: fizzy-mysql-primary + secret: + - RAILS_MASTER_KEY + - MYSQL_ALTER_PASSWORD + - MYSQL_ALTER_USER + - MYSQL_APP_PASSWORD + - MYSQL_APP_USER + - MYSQL_READONLY_PASSWORD + - MYSQL_READONLY_USER + tags: + sc_chi: + MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-101.df-iad-int.37signals.com + df_iad: + MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-101.df-iad-int.37signals.com + df_ams: + MYSQL_SOLID_CACHE_HOST: fizzy-solidcache-db-101.df-iad-int.37signals.com + accessories: load-balancer: diff --git a/config/deploy.staging.yml b/config/deploy.staging.yml index 8ee71d6fa..d89e41e3b 100644 --- a/config/deploy.staging.yml +++ b/config/deploy.staging.yml @@ -1,17 +1,18 @@ servers: web: hosts: - - fizzy-staging-app-01.sc-chi-int.37signals.com - - fizzy-staging-app-02.sc-chi-int.37signals.com - - fizzy-staging-app-101.df-iad-int.37signals.com - - fizzy-staging-app-102.df-iad-int.37signals.com - - fizzy-staging-app-401.df-ams-int.37signals.com - - fizzy-staging-app-402.df-ams-int.37signals.com + - fizzy-staging-app-101.df-iad-int.37signals.com: df_iad + - fizzy-staging-app-102.df-iad-int.37signals.com: df_iad + - fizzy-staging-app-01.sc-chi-int.37signals.com: sc_chi + - fizzy-staging-app-02.sc-chi-int.37signals.com: sc_chi + - fizzy-staging-app-401.df-ams-int.37signals.com: df_ams + - fizzy-staging-app-402.df-ams-int.37signals.com: df_ams labels: otel_scrape_enabled: true jobs: hosts: - - fizzy-staging-app-01.sc-chi-int.37signals.com + - fizzy-staging-app-101.df-iad-int.37signals.com: df_iad + - fizzy-staging-app-102.df-iad-int.37signals.com: df_iad labels: otel_scrape_enabled: true @@ -24,6 +25,26 @@ ssh: env: clear: RAILS_ENV: staging + MYSQL_DATABASE_HOST: fizzy-staging-mysql-primary + MYSQL_DATABASE_REPLICA_HOST: fizzy-staging-mysql-replica + MYSQL_SOLID_CABLE_HOST: fizzy-staging-mysql-primary + MYSQL_SOLID_QUEUE_HOST: fizzy-staging-mysql-primary + secret: + - RAILS_MASTER_KEY + - MYSQL_ALTER_PASSWORD + - MYSQL_ALTER_USER + - MYSQL_APP_PASSWORD + - MYSQL_APP_USER + - MYSQL_READONLY_PASSWORD + - MYSQL_READONLY_USER + tags: + sc_chi: + MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-101.df-iad-int.37signals.com + df_iad: + MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-101.df-iad-int.37signals.com + df_ams: + MYSQL_SOLID_CACHE_HOST: fizzy-staging-solidcache-db-101.df-iad-int.37signals.com + accessories: load-balancer: diff --git a/config/initializers/active_storage.rb b/config/initializers/active_storage.rb index 830f8582c..096239d13 100644 --- a/config/initializers/active_storage.rb +++ b/config/initializers/active_storage.rb @@ -3,3 +3,8 @@ ActiveSupport.on_load(:active_storage_blob) do expires_in 5.minutes, public: true end end + +# Use DB read/write splitting for Active Storage models +ActiveSupport.on_load(:active_storage_record) do + connects_to database: { writing: :primary, reading: :replica } +end diff --git a/script/configure-lb-staging.sh b/script/configure-lb-staging.sh index 17ae50494..789865d16 100755 --- a/script/configure-lb-staging.sh +++ b/script/configure-lb-staging.sh @@ -4,66 +4,44 @@ set -e # fizzy-staging-lb-01.sc-chi-int.37signals.com # -# Service Host Path Target State TLS -# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-02.sc-chi-int.37signals.com running yes -# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes ssh app@fizzy-staging-lb-01.sc-chi-int.37signals.com \ docker exec fizzy-load-balancer \ kamal-proxy deploy fizzy \ + --force \ --tls \ --host=fizzy.37signals-staging.com \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ - --read-target=fizzy-staging-app-02.sc-chi-int.37signals.com \ - --tls-acme-cache-path=/certificates - -ssh app@fizzy-staging-lb-01.sc-chi-int.37signals.com \ - docker exec fizzy-load-balancer \ - kamal-proxy deploy fizzy-admin \ - --host=fizzy.37signals-staging.com \ - --path-prefix /admin \ - --strip-path-prefix=false \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com + --writer-affinity-timeout=1s \ + --tls-acme-cache-path=/certificates \ + --target=fizzy-staging-app-101.df-iad-int.37signals.com \ + --target=fizzy-staging-app-102.df-iad-int.37signals.com \ + --read-target=fizzy-staging-app-01.sc-chi-int.37signals.com \ + --read-target=fizzy-staging-app-02.sc-chi-int.37signals.com # fizzy-staging-lb-101.df-iad-int.37signals.com # -# Service Host Path Target State TLS -# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-102.df-iad-int.37signals.com running yes -# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes ssh app@fizzy-staging-lb-101.df-iad-int.37signals.com \ docker exec fizzy-load-balancer \ kamal-proxy deploy fizzy \ + --force \ --tls \ --host=fizzy.37signals-staging.com \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ - --read-target=fizzy-staging-app-102.df-iad-int.37signals.com \ - --tls-acme-cache-path=/certificates - -ssh app@fizzy-staging-lb-101.df-iad-int.37signals.com \ - docker exec fizzy-load-balancer \ - kamal-proxy deploy fizzy-admin \ - --host=fizzy.37signals-staging.com \ - --path-prefix /admin \ - --strip-path-prefix=false \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com + --writer-affinity-timeout=1s \ + --tls-acme-cache-path=/certificates \ + --target=fizzy-staging-app-101.df-iad-int.37signals.com \ + --target=fizzy-staging-app-102.df-iad-int.37signals.com # fizzy-staging-lb-401.df-ams-int.37signals.com # -# Service Host Path Target State TLS -# fizzy fizzy.37signals-staging.com / fizzy-staging-app-01.sc-chi-int.37signals.com,fizzy-staging-app-402.df-ams-int.37signals.com running yes -# fizzy-admin fizzy.37signals-staging.com /admin fizzy-staging-app-01.sc-chi-int.37signals.com running yes ssh app@fizzy-staging-lb-401.df-ams-int.37signals.com \ docker exec fizzy-load-balancer \ kamal-proxy deploy fizzy \ + --force \ --tls \ --host=fizzy.37signals-staging.com \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com \ - --read-target=fizzy-staging-app-402.df-ams-int.37signals.com \ - --tls-acme-cache-path=/certificates + --writer-affinity-timeout=1s \ + --tls-acme-cache-path=/certificates \ + --target=fizzy-staging-app-101.df-iad-int.37signals.com \ + --target=fizzy-staging-app-102.df-iad-int.37signals.com \ + --read-target=fizzy-staging-app-401.df-ams-int.37signals.com \ + --read-target=fizzy-staging-app-402.df-ams-int.37signals.com -ssh app@fizzy-staging-lb-401.df-ams-int.37signals.com \ - docker exec fizzy-load-balancer \ - kamal-proxy deploy fizzy-admin \ - --host=fizzy.37signals-staging.com \ - --path-prefix /admin \ - --strip-path-prefix=false \ - --target=fizzy-staging-app-01.sc-chi-int.37signals.com