├── Capfile ├── README.md └── config ├── deploy.rb ├── nginx-with-ssl.conf └── nginx.conf /Capfile: -------------------------------------------------------------------------------- 1 | require "capistrano/setup" 2 | require "capistrano/deploy" 3 | require 'capistrano/rails' 4 | require 'capistrano/bundler' 5 | require 'capistrano/rbenv' 6 | require 'capistrano/puma' 7 | require "capistrano/scm/git" 8 | 9 | install_plugin Capistrano::SCM::Git 10 | install_plugin Capistrano::Puma 11 | 12 | Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # All package and actions to deploy rails app 2 | ============================================= 3 | # Estimated time ~40 minutes 4 | ----------------------------- 5 | 6 | * [Rails 5](http://rubyonrails.org/) 7 | * [Nginx](https://www.nginx.com/resources/wiki/) 8 | * [Mysql](https://www.mysql.com/) 9 | * [Puma](http://puma.io/) 10 | * [Ubuntu 16.04](https://www.ubuntu.com/) 11 | * [Capistrano](http://capistranorb.com/) 12 | 13 | 14 | ### The tutorial work with server by [digitalocean.com](https://m.do.co/c/03deef324558) 15 | ##### Login and create a droplet Ubuntu 16.04x64 1gb cpu & 30gb disk 16 | 17 | ``` 18 | ssh root@xxx.xxx.xx 19 | 20 | sudo apt-get install aptitude 21 | 22 | sudo apt-get update 23 | 24 | sudo aptitude update 25 | 26 | sudo aptitude safe-upgrade 27 | ``` 28 | If you have error with locale 29 | ------------------------------ 30 | ``` 31 | sudo locale-gen el_GR.UTF-8 32 | ``` 33 | ##### Next exit from server and create ssh connection 34 | ``` 35 | ssh-copy-id root@xxx.xxx.xx 36 | 37 | sudo adduser deploy 38 | 39 | sudo adduser deploy sudo 40 | 41 | ssh-copy-id deploy@xxx.xxx.xx 42 | ``` 43 | 44 | ##### Edit ssh setting 45 | ``` 46 | sudo vim /etc/ssh/sshd_config 47 | ``` 48 | ##### Next, we need to find the line that looks like this: 49 | 50 | ``` 51 | PermitRootLogin yes 52 | ``` 53 | ##### Modify this line to "no" like this to disable root login: 54 | ``` 55 | PermitRootLogin no 56 | ``` 57 | 58 | ##### Next, we need to find the line that looks like this: 59 | ``` 60 | Port 22 61 | ``` 62 | ##### Modify this line between 22 and 50000: 63 | 64 | ``` 65 | Port 4323 66 | ``` 67 | 68 | ##### Next, reload service ssh 69 | ``` 70 | service ssh restart 71 | ``` 72 | 73 | #### Install additional packages from Rails 74 | ``` 75 | sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev nodejs 76 | ``` 77 | 78 | 79 | ##### Install git & nginx 80 | ``` 81 | sudo apt-get install curl git-core nginx -y 82 | ``` 83 | 84 | ##### Install version ruby language rbenv 85 | ``` 86 | cd 87 | git clone https://github.com/rbenv/rbenv.git ~/.rbenv 88 | echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc 89 | echo 'eval "$(rbenv init -)"' >> ~/.bashrc 90 | exec $SHELL 91 | ``` 92 | 93 | 94 | #### Install ruby build plugin for rbenv 95 | 96 | ``` 97 | git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build 98 | echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc 99 | exec $SHELL 100 | ``` 101 | 102 | 103 | ###### Show ruby available versions 104 | 105 | ``` 106 | rbenv install -l 107 | 108 | rbenv install 2.4.0 109 | 110 | rbenv global 2.4.0 111 | 112 | rbenv rehash 113 | 114 | ruby -v 115 | ``` 116 | 117 | **You just add following line to your local `~/.gemrc` file (it is in your home folder)** 118 | 119 | `gem: --no-document` 120 | 121 | ##### Next, install ruby gems version control system 122 | 123 | ``` 124 | gem install bundler 125 | 126 | rbenv rehash 127 | ``` 128 | 129 | 130 | ##### Install Rails 131 | 132 | ``` 133 | gem install rails -V --no-ri --no-rdoc 134 | 135 | rbenv rehash 136 | ``` 137 | 138 | 139 | ### Create ssh key and copy 140 | 141 | ``` 142 | ssh-keygen -t rsa 143 | 144 | cat ~/.ssh/id_rsa.pub 145 | ``` 146 | 147 | ##### Visit the github and add ssh, after test it 148 | 149 | ``` 150 | ssh -T git@github.com 151 | ``` 152 | 153 | 154 | #### Next, install Mysql 155 | ``` 156 | sudo aptitude update 157 | 158 | sudo apt-get install mysql-server mysql-client libmysqlclient-dev 159 | 160 | sudo mysql_install_db 161 | 162 | sudo mysql_secure_installation 163 | ``` 164 | 165 | Create mysql database 166 | 167 | ``` 168 | mysql -u root -p 169 | 170 | CREATE DATABASE `app` CHARACTER SET utf8 COLLATE utf8_general_ci; 171 | ``` 172 | 173 | 174 | 175 | **Add additional gem into Gemfile** 176 | 177 | ``` 178 | group :development do 179 | gem 'capistrano', require: false 180 | gem 'capistrano-rbenv', require: false 181 | gem 'capistrano-rails', require: false 182 | gem 'capistrano-bundler', require: false 183 | gem 'capistrano3-puma', require: false 184 | end 185 | 186 | gem 'puma' 187 | ``` 188 | 189 | #### Next, install gems 190 | 191 | ``` 192 | bundle 193 | 194 | rbenv rehash 195 | ``` 196 | 197 | #### Create files from caristrano 198 | 199 | ``` 200 | cap install 201 | ``` 202 | 203 | 204 | 205 | 206 | Copy [config/deploy.rb](../master/config/deploy.rb) & [Capfile](../master/Capfile) files 207 | and paste in your rails app 208 | 209 | 210 | 211 | ``` 212 | git add -A 213 | git commit -m "Set up Puma, Nginx & Capistrano" 214 | git push origin master 215 | ``` 216 | 217 | Run capistrano init 218 | 219 | ``` 220 | cap production deploy:initial 221 | ``` 222 | 223 | 224 | 225 | #### make file /home/deploy/apps/app/shared/config/database.yml 226 | ``` 227 | production: 228 | adapter: mysql2 229 | pool: 5 230 | timeout: 5000 231 | encoding: utf8 232 | database: app 233 | username: root 234 | password: xxxxxxxxx 235 | ``` 236 | 237 | 238 | 239 | #### Set ubuntu environment variable 240 | ``` 241 | rails secret 242 | 243 | sudo vim /etc/environment 244 | ``` 245 | 246 | #### and add this line below 247 | 248 | ``` 249 | export SECRET_KEY_BASE=abb2e9e094bb8fb1aa216defed455caa0f9 250 | ``` 251 | 252 | 253 | At first time run in apps/app/release/2017456534 254 | 255 | ``` 256 | RAILS_ENV=production bundle exec rake db:create 257 | ``` 258 | 259 | Example [config/nginx.conf](../master/config/nginx.conf) file, paste in your rails app 260 | 261 | 262 | ##### set nginx virtualhost 263 | ``` 264 | sudo rm /etc/nginx/sites-enabled/default 265 | 266 | sudo ln -nfs "/home/deploy/apps/app/current/config/nginx.conf" "/etc/nginx/sites-enabled/app" 267 | 268 | sudo service nginx restart 269 | ``` 270 | 271 | 272 | At the end, run 273 | 274 | **If you want only to restart puma server** 275 | 276 | `cap production deploy:restart` 277 | 278 | 279 | **After deploy, publish change** 280 | 281 | `git add -A` 282 | `git commit -m "Deploy Message"` 283 | `git push origin master` 284 | `cap production deploy` 285 | 286 | 287 | ####How to install let's encrypt [#1](https://github.com/xargr/rails_deploy/issues/1) 288 | 289 | if you have some problem, create new issue in this repo 290 | 291 | ##Happy coding... 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | lock "3.7.2" 2 | 3 | set :rbenv_ruby, '2.4.0' 4 | 5 | # Change these 6 | server 'xxx.xxx.xx', port: 4433, roles: [:web, :app, :db], primary: true 7 | 8 | set :repo_url, 'git@github.com:username/reponame.git' 9 | set :application, 'app' 10 | set :user, 'deploy' 11 | set :puma_threads, [4, 16] 12 | set :puma_workers, 0 13 | 14 | # Don't change these unless you know what you're doing 15 | set :pty, true 16 | set :use_sudo, false 17 | set :stage, :production 18 | set :deploy_via, :remote_cache 19 | set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}" 20 | set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock" 21 | set :puma_state, "#{shared_path}/tmp/pids/puma.state" 22 | set :puma_pid, "#{shared_path}/tmp/pids/puma.pid" 23 | set :puma_access_log, "#{release_path}/log/puma.error.log" 24 | set :puma_error_log, "#{release_path}/log/puma.access.log" 25 | set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) } 26 | set :puma_preload_app, true 27 | set :puma_worker_timeout, nil 28 | set :puma_init_active_record, true # Change to false when not using ActiveRecord 29 | set :keep_releases, 3 30 | 31 | ## Defaults: 32 | #set :scm, :git 33 | #set :branch, :master 34 | # set :format, :pretty 35 | # set :log_level, :debug 36 | # set :keep_releases, 5 37 | 38 | ## Linked Files & Directories (Default None): 39 | set :linked_files, %w{config/database.yml} 40 | set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} 41 | 42 | namespace :puma do 43 | desc 'Create Directories for Puma Pids and Socket' 44 | task :make_dirs do 45 | on roles(:app) do 46 | execute "mkdir #{shared_path}/tmp/sockets -p" 47 | execute "mkdir #{shared_path}/tmp/pids -p" 48 | end 49 | end 50 | 51 | before :start, :make_dirs 52 | end 53 | 54 | namespace :deploy do 55 | desc "Make sure local git is in sync with remote." 56 | task :check_revision do 57 | on roles(:app) do 58 | unless `git rev-parse HEAD` == `git rev-parse origin/master` 59 | puts "WARNING: HEAD is not the same as origin/master" 60 | puts "Run `git push` to sync changes." 61 | exit 62 | end 63 | end 64 | end 65 | 66 | desc 'Initial Deploy' 67 | task :initial do 68 | on roles(:app) do 69 | before 'deploy:restart', 'puma:start' 70 | invoke 'deploy' 71 | end 72 | end 73 | 74 | desc 'Restart application' 75 | task :restart do 76 | on roles(:app), in: :sequence, wait: 5 do 77 | invoke 'puma:restart' 78 | end 79 | end 80 | 81 | before :starting, :check_revision 82 | after :finishing, :compile_assets 83 | after :finishing, :cleanup 84 | #after :finishing, :restart 85 | end 86 | 87 | # ps aux | grep puma # Get puma pid 88 | # kill -s SIGUSR2 pid # Restart puma 89 | # kill -s SIGTERM pid # Stop puma 90 | 91 | # Default branch is :master 92 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp 93 | 94 | # Default deploy_to directory is /var/www/my_app_name 95 | # set :deploy_to, "/var/www/my_app_name" 96 | 97 | # Default value for :format is :airbrussh. 98 | # set :format, :airbrussh 99 | 100 | # You can configure the Airbrussh format using :format_options. 101 | # These are the defaults. 102 | # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto 103 | 104 | # Default value for :pty is false 105 | # set :pty, true 106 | 107 | # Default value for :linked_files is [] 108 | # append :linked_files, "config/database.yml", "config/secrets.yml" 109 | 110 | # Default value for linked_dirs is [] 111 | # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" 112 | 113 | # Default value for default_env is {} 114 | # set :default_env, { path: "/opt/ruby/bin:$PATH" } 115 | -------------------------------------------------------------------------------- /config/nginx-with-ssl.conf: -------------------------------------------------------------------------------- 1 | upstream puma { 2 | server unix:///home/deploy/apps/app/shared/tmp/sockets/app-puma.sock; 3 | } 4 | 5 | server { 6 | listen 80 default_server deferred; 7 | server_name example.com www.example.com; 8 | return 301 https://$server_name$request_uri; 9 | } 10 | 11 | 12 | server { 13 | 14 | listen 443 ssl http2; 15 | listen [::]:443 ssl http2; 16 | include snippets/ssl-example.com.conf; 17 | include snippets/ssl-params.conf; 18 | server_name example.com; 19 | return 301 https://www.example.com$request_uri; 20 | } 21 | 22 | 23 | server { 24 | 25 | listen 443 ssl http2 default_server; 26 | listen [::]:443 ssl http2 default_server; 27 | include snippets/ssl-example.com.conf; 28 | include snippets/ssl-params.conf; 29 | server_name www.example.com.gr; 30 | 31 | 32 | root /home/deploy/apps/app/current/public; 33 | access_log /home/deploy/apps/app/current/log/nginx.access.log; 34 | error_log /home/deploy/apps/app/current/log/nginx.error.log info; 35 | 36 | 37 | 38 | location ^~ /assets/ { 39 | gzip_static on; 40 | expires max; 41 | add_header Cache-Control public; 42 | } 43 | 44 | try_files $uri/index.html $uri @puma; 45 | location @puma { 46 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 47 | proxy_set_header Host $http_host; 48 | proxy_redirect off; 49 | 50 | proxy_pass http://puma; 51 | } 52 | 53 | error_page 500 502 503 504 /500.html; 54 | client_max_body_size 10M; 55 | keepalive_timeout 10; 56 | 57 | location ~ /.well-known { 58 | allow all; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /config/nginx.conf: -------------------------------------------------------------------------------- 1 | upstream puma { 2 | server unix:///home/deploy/apps/app/shared/tmp/sockets/app-puma.sock; 3 | } 4 | 5 | server { 6 | listen 80 default_server deferred; 7 | server_name example.com www.example.com; 8 | 9 | root /home/deploy/apps/app/current/public; 10 | access_log /home/deploy/apps/app/current/log/nginx.access.log; 11 | error_log /home/deploy/apps/app/current/log/nginx.error.log info; 12 | 13 | location ^~ /assets/ { 14 | gzip_static on; 15 | expires max; 16 | add_header Cache-Control public; 17 | } 18 | 19 | try_files $uri/index.html $uri @puma; 20 | location @puma { 21 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 22 | proxy_set_header Host $http_host; 23 | proxy_redirect off; 24 | proxy_pass http://puma; 25 | } 26 | 27 | error_page 500 502 503 504 /500.html; 28 | client_max_body_size 10M; 29 | keepalive_timeout 10; 30 | } 31 | --------------------------------------------------------------------------------