Step 1.
Setup you hostinger server
- SSH into the remote server :
ssh root@<hostinger_ip_address>
- Create user:
sudo adduser <newusername>
- Grant administrative rights:
sudo usermod -aG sudo <newusername>
Configure access:
sudo visudo
- And add this line :
<newusername> ALL=(ALL) NOPASSWD:ALL
Switch user: su - <newusername>
Generate SSH Key and add to github
ssh-keygen -t rsa -b 4096
: once its generated add the public key to github
Make a directory where rails app will be deployed
mkdir -p /path/to/parent_directory/sub_directory
- example in our case:
mkdir -p /home/<newusername>/<application_name>
- Change the ownership:
sudo chown -R <newusername>:group /home/<newusername>/<application_name>
Install prerequisite:
- sudo apt-get update
- sudo apt-get install -y curl git-core nodejs yarn build-essential libpq-dev
Install rvm
- \curl -sSL https://get.rvm.io | bash -s stable --ruby
- source ~/.rvm/scripts/rvm
- rvm use 3.1.2 --default
Install postgresql
- sudo apt update
- sudo apt install postgresql postgresql-contrib
- sudo systemctl start postgresql
- sudo systemctl enable postgresql
Create user in postgresql
- sudo -u postgres psql
- create user: CREATE USER username WITH PASSWORD 'password';
- Alter the user: ALTER USER username WITH SUPERUSER CREATEDB CREATEROLE REPLICATION BYPASSRLS;
Note: If you have other database providers(example: AWS RDS) you can skip he postgresql installation
Step 2
Generate SSH Key and add to hostinger server
Execute below on your local machine
- ssh-keygen -t ed25519 -C
your_email@example.com
ssh-copy-id -i ~/.ssh/id_ed25519.pub <hostinger_newusername>@<hostinger_ip_address>
Configure your rails app:
- Add below gems inside development group of your gem file
group :development do
gem 'capistrano'
gem 'capistrano3-puma'
gem 'capistrano-rails', require: false
gem 'capistrano-bundler', require: false
gem 'capistrano-rvm'
end
- bundle install
- bundle exec cap install
- modify your Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
require 'capistrano/rails'
require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/rails/assets'
require 'capistrano/puma'
require "capistrano/rails/migrations"
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
- modify your deploy.rb file
lock "~> 3.18.0"
set :application, '<application_name>'
set :repo_url, '<git ssh url, example: git@github.com:ak-need/test-rails.git>' # Edit this to match your repository
set :branch, :main
set :deploy_to, '/home/<newusername>/<application_name>'
set :pty, true
set :linked_files, %w{ config/boot.rb config/master.key config/credentials.yml.enc config/database.yml config/storage.yml }
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads', 'public/images', 'public/documents'
set :config_files, %w(database.yml)
set :keep_releases, 5
set :rvm_type, :user
set :rvm_ruby_version, 'ruby-3.1.2' # Edit this if you are using MRI Ruby
set :puma_rackup, -> { File.join(current_path, 'config.ru') }
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock" #accept array for multi-bind
set :puma_conf, "#{shared_path}/puma.rb"
set :puma_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
set :puma_threads, [0, 8]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, false
namespace :deploy do
after :restart, :clear_cache do
on roles(:web), in: :groups, limit: 3, wait: 10 do
end
end
end
- modify your config/deploy/production.rb file
set :user, 'deploy'
set :pty, true
set :use_sudo, true
set :stage, :production
set :deploy_via, :remote_cache
set :deploy_to, "/home/<newusername>/<application_name>"
set :ssh_options, { forward_agent: true, user: '<newusername>' }
set :branch, 'main' # Default branch is master
server '82.112.235.108', user: '<newusername>', roles: %w{web app db}, primary: true
namespace :deploy do
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute "sudo service nginx restart"
end
end
after :finishing, 'deploy:restart'
after :finishing, 'deploy:cleanup'
end
- Copy linked_files from you local machine to hostinger server
###### Move to your rails app directory if you are not there
scp config/database.yml <newusername>@<hostinger_ip_address>:/home/<newusername>/shared/config/
example: scp config/database.yml test@83.111.215.208:/home/test/shared/config/
Finaly
bundle exec cap production deploy
Your application should be deployed but now configure nginx with passenger
sudo apt-get update
sudo apt-get install -y libnginx-mod-http-passenger
sudo nano /etc/nginx/sites-available/default
and paste the below
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name <domain name or ip address>;
root /home/<newusername>/<application_name>/current/public;
passenger_enabled on;
passenger_app_env production;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri @app;
}
location @app {
passenger_enabled on;
passenger_base_uri /;
passenger_app_root /home/<newusername>/<application_name>/current;
passenger_document_root /home/<newusername>/<application_name>/current/public;
passenger_ruby /home/<newusername>/.rvm/rubies/ruby-3.1.2/bin/ruby;
passenger_app_env production;
}
}
- Test nginx
sudo nginx -t
- Finally restart the nginx:
sudo systemctl restart nginx