Skip to content

Commit

Permalink
Merge pull request #193 from maxbarsukov/dev
Browse files Browse the repository at this point in the history
docs: 📚 update deployment guides
  • Loading branch information
maxbarsukov committed Aug 17, 2022
2 parents 5309d3c + 35cec84 commit d2b8bcf
Show file tree
Hide file tree
Showing 14 changed files with 363 additions and 11 deletions.
4 changes: 2 additions & 2 deletions Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
web: bundle exec whenever --set 'environment=production' --update-crontab && bundle exec rails server -p $PORT -e production
worker: bundle exec sidekiq
web: bundle exec whenever --set 'environment=production' --update-crontab tollowy_production && bundle exec rails server -p $PORT -e production -b 0.0.0.0
worker: bundle exec sidekiq -e production
2 changes: 1 addition & 1 deletion Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
web: bundle exec whenever --set 'environment=development' --update-crontab && bundle exec rails server -p $PORT
web: bundle exec whenever --set 'environment=development' --update-crontab tollowy_development && bundle exec rails server -p $PORT -b 0.0.0.0
worker: bundle exec sidekiq
25 changes: 19 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,24 @@ For security, Postgres doesn’t allow you to see queries from other users witho

With a superuser, run:

$ psql -U postgres -d tollowy_production -a -f bin/pghero-permissions.sql -v pghero_password="'pghero_user_password'" -v database_name=tollowy_development
$ psql -U postgres -d tollowy_production -a -f bin/pghero-permissions.sql -v pghero_password="'pghero_user_password'" -v database_name=tollowy_production
$ psql -U postgres -d tollowy_development -a -f bin/pghero-permissions.sql -v pghero_password="'pghero_user_password'" -v database_name=tollowy_development

#### Elasticsearch

Add to `elasticsearch.yml`

http.cors.allow-origin: "/.*/"
http.cors.enabled: true

network.bind_host: 0.0.0.0
network.host: localhost
discovery.type: single-node

#### Whenever

To use `whenever` gem you should have `cron` installed.
Run `whenever --update-crontab` to update your crontab.
Run `whenever --update-crontab <identifier_name>` to update your crontab.
Use `--set 'environment=production` argument to set environment.

Need more detailed installation instructions?
Expand All @@ -143,7 +155,7 @@ Need more detailed installation instructions?
9) Setup `Elasticsearch` username & password and changr `.env` file if needed;
10) Run `bundle exec rails searchkick:reindex:custom:all` to reindex your models;
11) Configure and start `Nginx` if needed;
12) Generate `crontab` with `bundle exec whenever --update-crontab`;
12) Generate `crontab` with `bundle exec whenever --update-crontab tollowy_development`;

Finally, run `foreman start` and check your `http://localhost:3000` (or `:80` if you use `Nginx`)

Expand Down Expand Up @@ -200,6 +212,7 @@ Some `ENV` settings you can use at self-hosted `Followy API`:
- Use `rails db:seed export=false` to not generate csv files.
- Use `rails db:seed force=true` to seed db even if there is existing data.
- `rails db:seed load=true` – loads data to database from `db/fixtures/*.csv` files.
- `rails db:kill_postgres_connections` – Kills all PostgreSQL connections.
- `rails pghero:analyze` – Run `PgHero` database analyzer.
- `rails pghero:rails pghero:autoindex` – Run `PgHero` auto-indexer.
- `rails pghero:capture_query_stats` – Run `PgHero` capture query stats.
Expand Down Expand Up @@ -247,7 +260,7 @@ Run `bin/tests` or `bundle exec rails spec` to launch the test runner.

### Docker

Run `bin/docke-setup` and `bin/docker-tests` to launch tests runner in Docker;
Run `bin/docker-setup` and `bin/docker-tests` to launch tests runner in Docker;


## Linting <a name="linting"></a>
Expand All @@ -264,7 +277,7 @@ or run it together with `bin/quality`

### Docker

Run `bin/docke-setup` and `bin/docker-quality` to launch quality checkers in Docker;
Run `bin/docker-setup` and `bin/docker-quality` to launch quality checkers in Docker;


## Other <a name="other"></a>
Expand Down Expand Up @@ -326,7 +339,7 @@ Please, use [refinements](https://docs.ruby-lang.org/en/2.4.0/syntax/refinements
#### Cron

- Logs are located at `log/cron_log.log`
- Update `crontab` with `bundle exec whenever --update-crontab`;
- Update `crontab` with `bundle exec whenever --update-crontab tollowy_development`;

#### Profiling

Expand Down
2 changes: 1 addition & 1 deletion app/interactors/user/authenticate_by_credentials.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def authenticated?
end

def user
@user ||= User.find_by('username = :uoe OR email = :uoe', uoe: username_or_email)
@user ||= User.find_by('lower(username) = lower(:uoe) OR lower(email) = lower(:uoe)', uoe: username_or_email)
end

def error_data
Expand Down
2 changes: 1 addition & 1 deletion app/views/admin/sessions/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<li class="menu_item" id="i18n-en"><a href="/admin/sign_in?locale=en">English</a></li>
</ul>
</li>
<li class="menu_item" id="docs"><a rel="nofollow" data-method="delete" href="/docs">Документация</a></li>
<li class="menu_item" id="docs"><a rel="nofollow" data-method="delete" href="/docs"><%= t('views.admin.sessions.new.header.docs') %></a></li>
</ul>
</div>

Expand Down
3 changes: 3 additions & 0 deletions config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ default: &default
password: <%= ENV["DATABASE_PASSWORD"] %>
port: <%= ENV['DATABASE_PORT'] || '5432' %>
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
min_messages: warning

development:
<<: *default
Expand All @@ -17,3 +19,4 @@ test:
production:
<<: *default
database: <%= ENV["DATABASE_PRODUCTION_DB"] || 'tollowy_production' %>
host: <%= ENV['DATABASE_HOST'] { 'localhost' } %>
2 changes: 2 additions & 0 deletions config/deploy/Procfile.deploy
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web: bundle exec whenever --set 'environment=production' --update-crontab tollowy_production && RAILS_ENV=production RACK_ENV=production bundle exec puma -p $PORT -b unix:///home/deploy/apps/tollowy/shared/sockets/puma.sock -e production -C config/puma.rb
worker: bundle exec sidekiq -e production
89 changes: 89 additions & 0 deletions config/deploy/nginx/api.followy.ru.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
upstream app {
# Path to Puma SOCK file, as defined previously
server unix:/home/deploy/apps/tollowy/shared/sockets/puma.sock fail_timeout=0;
}

server {
listen 80 default_server;
listen [::]:80 default_server;

# listen 443 ssl http2;
# listen [::]:443 ssl http2;

server_name api.followy.ru www.api.followy.ru;

# RSA certificate
# ssl_certificate /etc/letsencrypt/live/api.followy.ru/fullchain.pem; # managed by Certbot
# ssl_certificate_key /etc/letsencrypt/live/api.followy.ru/privkey.pem; # managed by Certbot

# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

# Redirect non-https traffic to https
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# }

root /home/deploy/apps/tollowy/public;

try_files $uri/index.html $uri @app;

# deny requests for files that should never be accessed
location ~ /\. {
deny all;
}

location ~* ^.+\.(rb|log)$ {
deny all;
}

# serve static (compiled) assets directly if they exist (for rails production)
location ~ ^/(assets|images|javascripts|stylesheets|swfs|system)/ {
try_files $uri @app;

access_log off;
gzip_static on;

expires max;
add_header Cache-Control public;

# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}

location /sidekiq {
proxy_set_header X-Script-Name /sidekiq;
proxy_pass http://app/sidekiq;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Real-IP $remote_addr;
}

# send non-static file requests to the app server
location / {
try_files $uri @app;
}

location @app {
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;

proxy_read_timeout 150;
proxy_pass http://app;
proxy_redirect off;
}

client_max_body_size 100m;
}
61 changes: 61 additions & 0 deletions config/deploy/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
user www-data;
include /etc/nginx/modules-enabled/*.conf;

worker_processes 4;
worker_rlimit_nofile 200000;

pid /var/run/nginx.pid;

events {
use epoll;
multi_accept on;
worker_connections 16384;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

sendfile on;
tcp_nopush on;
types_hash_max_size 4096;

keepalive_timeout 65;
keepalive_requests 1000;
reset_timedout_connection on;

proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;

fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;

gzip on;
gzip_proxied expired no-cache no-store private auth;
gzip_comp_level 5;
gzip_vary on;
gzip_min_length 1024;
gzip_disable "msie6";
gzip_types text/plain text/xml application/xml application/xml+rss application/x-javascript text/javascript text/css text/json application/json text/x-json application/vnd.api+json;

open_file_cache max=200000 inactive=20s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio" '
'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';

access_log /var/log/nginx/access.log main buffer=16k;
error_log /var/log/nginx/error.log;

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=one:10m max_size=1g inactive=60m;
proxy_cache_key $scheme$request_method$host$request_uri;

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
65 changes: 65 additions & 0 deletions config/deploy/puma.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
threads min_threads_count, max_threads_count

# Specifies the `worker_timeout` threshold that Puma will use to wait before
# terminating a worker in development environments.
#
worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development'

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch('PORT', 3000)

# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch('RAILS_ENV') { 'development' }

# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch('PIDFILE') { 'tmp/pids/server.pid' }

app_dir = File.expand_path('..', __dir__)
shared_dir = "#{app_dir}/shared"

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
require 'active_record'
begin
ActiveRecord::Base.connection.disconnect!
rescue StandardError
ActiveRecord::ConnectionNotEstablished
end
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
workers ENV.fetch('WEB_CONCURRENCY', 2)

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
preload_app!

# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
1 change: 1 addition & 0 deletions config/locales/views/admin/sessions/new/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ en:
submit: Log In
header:
languages: Languages
docs: Documentation
labels:
password: 'Password:'
username_or_email: 'Username or email:'
1 change: 1 addition & 0 deletions config/locales/views/admin/sessions/new/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ru:
submit: Войти
header:
languages: Язык
docs: Документация
labels:
password: 'Пароль:'
username_or_email: 'Имя пользователя или email:'
Loading

0 comments on commit d2b8bcf

Please sign in to comment.