Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Staging infrastructure #13

Draft
wants to merge 21 commits into
base: master
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@
.env
vendor/bundle
public/system

infrastructure/salt-ssh/pki
infrastructure/salt-ssh/var
infrastructure/salt-ssh/cache
infrastructure/.vagrant
17 changes: 17 additions & 0 deletions Capfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# Include tasks from other gems included in your Gemfile
require "capistrano/bundler"
#require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/puma"
install_plugin Capistrano::Puma

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ group :development do
gem "listen", ">= 3.0.5", "< 3.2"
gem "web-console", ">= 3.3.0"
gem "spring"
gem "capistrano", "~> 3.12", require: false
gem "capistrano-rails", "~> 1.4", require: false
gem "capistrano3-puma", "~> 3.1", require: false
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]



27 changes: 27 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ GEM
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
airbrussh (1.4.0)
sshkit (>= 1.6.1, != 1.7.0)
arel (9.0.0)
ast (2.4.0)
awesome_print (1.8.0)
aws-partitions (1.70.0)
aws-sdk-core (3.17.0)
aws-partitions (~> 1.0)
Expand All @@ -60,6 +63,20 @@ GEM
bcrypt (3.1.13)
bindex (0.5.0)
builder (3.2.4)
capistrano (3.12.1)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
capistrano-bundler (1.6.0)
capistrano (~> 3.1)
capistrano-rails (1.4.0)
capistrano (~> 3.1)
capistrano-bundler (~> 1.1)
capistrano3-puma (3.1.1)
capistrano (~> 3.7)
capistrano-bundler
puma (~> 3.4)
climate_control (0.2.0)
coderay (1.1.2)
coffee-rails (4.2.2)
Expand Down Expand Up @@ -120,6 +137,9 @@ GEM
mini_portile2 (2.4.0)
minitest (5.14.0)
mqtt (0.5.0)
net-scp (2.0.0)
net-ssh (>= 2.6.5, < 6.0.0)
net-ssh (5.2.0)
nio4r (2.5.2)
nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
Expand Down Expand Up @@ -232,6 +252,9 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sshkit (1.21.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0)
thor (1.0.1)
Expand Down Expand Up @@ -263,7 +286,11 @@ PLATFORMS
ruby

DEPENDENCIES
awesome_print
aws-sdk-s3
capistrano (~> 3.12)
capistrano-rails (~> 1.4)
capistrano3-puma (~> 3.1)
coffee-rails (~> 4.2)
devise
dotenv-rails
Expand Down
11 changes: 11 additions & 0 deletions config/deploy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"
set :application, "coronadonor-api"
#set :repo_url, "[email protected]:factn/coronadonor-api.git"
set :repo_url, "https://github.com/factn/coronadonor-api.git"

ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
set :deploy_to, "/home/coronadonor-api_#{fetch(:stage)}/"

append :linked_files, "config/master.key"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
2 changes: 2 additions & 0 deletions config/deploy/production.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set :rails_env, 'production'
server "127.0.0.1", port: 10022, user: 'coronadonor-api_production', roles: %w{web app db}
2 changes: 2 additions & 0 deletions config/deploy/staging.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
set :rails_env, 'staging'
server "127.0.0.1", port: 10022, user: 'coronadonor-api_staging', roles: %w{web app db}
3 changes: 3 additions & 0 deletions config/deploy/vagrant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
server "127.0.0.1", port: 10022, user: 'coronadonor-api_development', roles: %w{web app db}
set :deploy_to, "/home/coronadonor-api_development/"
set :rails_env, 'staging'
119 changes: 119 additions & 0 deletions config/environments/staging.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.

# Code is not reloaded between requests.
config.cache_classes = true

# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance.
config.eager_load = true

# Full error reports are disabled and caching is turned on.
config.consider_all_requests_local = false
config.action_controller.perform_caching = true

# Attempt to read encrypted secrets from `config/secrets.yml.enc`.
# Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or
# `config/secrets.yml.key`.
config.read_encrypted_secrets = true

# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present?

# Compress JavaScripts and CSS.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass

# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false

# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb

# Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com'

# Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX

# Store uploaded files on the local file system (see config/storage.yml for options)
config.active_storage.service = :local


# Mount Action Cable outside main process or domain
# config.action_cable.mount_path = nil
# config.action_cable.url = 'wss://example.com/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]

# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true

# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :debug

# Prepend all log lines with the following tags.
config.log_tags = [:request_id]

# Use a different cache store in production.
# config.cache_store = :mem_cache_store

# Use a real queuing backend for Active Job (and separate queues per environment)
# config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "lion_#{Rails.env}"
config.action_mailer.perform_caching = false

# Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
# config.action_mailer.raise_delivery_errors = false

# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found).
config.i18n.fallbacks = true

# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify

# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new

# Use a different logger for distributed setups.
# require 'syslog/logger'
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')

if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
end

# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false

config.paperclip_defaults = {
storage: :s3,
s3_credentials: {
bucket: ENV.fetch("S3_BUCKET_NAME"),
access_key_id: ENV.fetch("AWS_ACCESS_KEY_ID"),
secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY"),
s3_region: ENV.fetch("AWS_REGION"),
s3_host_name: "s3-#{ENV.fetch("AWS_REGION")}.amazonaws.com"
}
}

if ENV['CLOUDMQTT_URL']
uri = URI.parse ENV["CLOUDMQTT_URL"]

config.MQTTOptions = {
remote_host: uri.host,
remote_port: uri.port,
username: uri.user,
password: uri.password
}.freeze
end

config.TRUST_THRESHOLD = 0.5
end
4 changes: 4 additions & 0 deletions infrastructure/Saltfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
salt-ssh:
root_dir: ./
config_dir: ./salt-ssh
state_output: changes
25 changes: 25 additions & 0 deletions infrastructure/Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

# This is just a basic Debian VM to test the Salt formulas
Vagrant.configure("2") do |config|
config.vm.box = "debian/contrib-buster64"

config.vm.network "forwarded_port", guest: 22, host: 10022, host_ip: "127.0.0.1"
config.vm.provider "virtualbox" do |vb|
vb.memory = "512"
end

config.vm.hostname = 'salt-test.local'
config.vm.synced_folder "./states", "/srv/salt"
config.vm.synced_folder "./pillar", "/srv/pillar"
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<-SHELL
wget -O - https://repo.saltstack.com/py3/debian/10/amd64/latest/SALTSTACK-GPG-KEY.pub | sudo apt-key add -
echo deb http://repo.saltstack.com/py3/debian/10/amd64/latest buster main > /etc/apt/sources.list.d/saltstack.list
apt-get update
apt-get -y install vim salt-minion
SHELL
end
3 changes: 3 additions & 0 deletions infrastructure/pillar/top.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
base:
'salt-test.local':
- vagrant
7 changes: 7 additions & 0 deletions infrastructure/pillar/vagrant.sls
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
coronadonor-api:
database:
name: coronadonor_api_development
username: vagrant_test_db
password: secret
master_key: 1234

10 changes: 10 additions & 0 deletions infrastructure/salt-ssh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
This repository contains a minimal environment for controlling our
infrastructure via salt-ssh.

Before you start, you will need to have salt-ssh installed.

You can get it through PyPI:

sudo apt install python-pip
sudo pip install salt-ssh

9 changes: 9 additions & 0 deletions infrastructure/salt-ssh/master
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root_dir: ./salt-ssh
pki_dir: pki
cachedir: cache
file_roots:
base:
- ./states
pillar_roots:
base:
- ./pillar
7 changes: 7 additions & 0 deletions infrastructure/salt-ssh/roster
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
vagrant:
host: 127.0.0.1
port: 10022
user: vagrant
passwd: vagrant
sudo: true
example.com: 4.4.4.4
68 changes: 68 additions & 0 deletions infrastructure/states/coronadonor_api/files/nginx.site.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
upstream coronadonor_api {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).

# for UNIX domain socket setups:
#server 127.0.0.1:3000 fail_timeout=0;
server unix:/home/coronadonor_api/app/shared/tmp/sockets/puma.sock;
}

server {
# if you're running multiple servers, instead of "default" you should
# put your main domain name here

# you could put a list of other domain names this application answers
server_name coronadonor_api.example.com;

root /home/coronadonor_api/app/current/public/;
access_log /var/log/nginx/coronadonor_api_access.log;
rewrite_log on;

client_max_body_size 1000m;
client_body_buffer_size 100m;

location / {
try_files $uri @app;
}

location @app {
#all requests are sent to the UNIX socket
proxy_pass http://coronadonor_api;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on; # Optional
proxy_set_header X-Forwarded-Port $server_port;




proxy_connect_timeout 900;
proxy_send_timeout 900;
proxy_read_timeout 900;

proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

#satisfy all;
# allow 4.4.4.4;
# deny all;

auth_basic "Please log-in first...";
auth_basic_user_file /etc/nginx/coronadonor_api_passwd;
}

}


server {
listen 80;
server_name coronadonor_api.example.com;

}
Loading