Good day, habrovchane!How to move to VDS in 15 minutes and not go into the study of nginx, unicorn and capistrano. Step by step instructions under the cut.
I constantly hear from many familiar PHP programmers that they don’t want to go to the rails just because there is no adequate and cheap hosting with a normal control panel. In fact, the question is where it is hosted, if you write on the rails, it has already been raised a hundred times on Habré, which is why I will not talk about it. When I first did a project on rails, I ran into a host search, but this was not the case, the main thing for me was the easy process of launching the application on the hosting. I decided to buy myself a VDS and use it as a test server. The process of setting up and preparing VDS was complicated by the fact that I did not find instructions from A to Z, and since I, roughly speaking, did not shine with knowledge in the configuration not only of VDS, but also nginx and unicorn, and much more. I did not need configs in 200 lines and terribly confused settings for heavily loaded applications, my task was to simply launch the site for a minimum of money and time and give it to the customer along with this VDS. In this article I want to write exactly the instruction that I needed, I hope that it will be useful for many beginners to write on the tracks and will perhaps serve as an additional incentive for those PHP programmers who still doubt and continue to use frameworks that copy Ruby On Rails features and tweaks. I think this is the same as putting the engine from a Mercedes to a penny. It seems to be pretty, but that is still not right.
')
So let's get started
What you should have to begin with:
- Purchased and working VDS with any Debian family system
- Purchased domain from any registrar
For reference: all actions, in my case, are performed on VDS with Ubuntu Server 11.10.
Install and configure nginx
We go to the machine via ssh through the terminal:
:~ ssh root@<ip >
We put nginx from the repository:
:~ apt-get install nginx
Create a directory for our application configs, what if there are several of them:
:~ mkdir /etc/nginx/sites
We write a config for the first application. I use vim, but this is a matter of taste, you can use at least a standard nano:
:~ vi /etc/nginx/sites/first_app.conf
We write here the following contents:
server {
listen 80;
# , .
# , , .
server_name first_app.com;
root /home/first_app/web-app/public;
client_max_body_size 32m;
location / {
try_files $uri @unicorn;
}
location @unicorn {
proxy_set_header Client-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass unix:/home/first_app/web-app/tmp/sockets/unicorn.sock;
}
}
Now we edit the nginx server itself. Below is the complete config file:
user nobody nogroup;
worker_processes 4;
pid /var/run/nginx.pid;
events {
worker_connections 4096;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
log_format main '$remote_addr - $remote_user[$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "http_x_forwarded_for"'
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
# gzip_vary on;
gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites/*.conf;
}
#mail {
# # See sample authentication script at:
# # wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
Now we need nginx to start automatically when VDS starts. To do this, install the supervisor runit:
:~ apt-get install runit
:~ mkdir /etc/sv/nginx
Create an executable file to run nginx:
:~ vi /etc/sv/nginx/run
And write there is this:
#!/bin/sh
exec 2>&1
exec /usr/sbin/nginx
Making it executable:
:~ chmod +x /etc/sv/nginx/run
Check whether the whole thing earned:
:~ /etc/sv/nginx/run
:~ ps aux | grep nginx
If everything is good, you will see 4 running worker_process and nginx server. Problems can arise only if Apache was installed by default on VDS. So it was with me, which naturally means busy port 80. Feel free to demolish Apache and kill all its processes. I hope you are doing well and we will continue. It remains to make a symlink for automatic launch:
:~ ln -s /etc/sv/nginx/ /etc/service
Congratulations nginx installed and configured. At all about everything with proper snapshot it will take about 2 minutes. We also need to create a user from which the application will run:
:~ adduser first_app
:~ vi home/itnotes/.bashrc
Add to this file:
export RAILS_ENV=production
Installing RVM and RubyGems
In the same terminal we continue:
:~ apt-get install curl
:~ bash -s stable < <(curl -s raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
:~ apt-get install build-essential bison openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev
:~ gpasswd -a first_app rvm
:~ apt-get install rubygems
:~ rvm use --create ruby-1.9.2-p318@first_app
:~ rvm ruby-1.9.2-p318@global gem install bundler
:~ mkdir /home/first_app/web-app
:~ apt-get install git-core git-gui git-doc
Here we install curl, then with its help we install rvm, deliver a pack of packages that will be useful for compiling Ruby, running sqlite, etc. After that we put Rubygems, create a gemset for our project, install the bundler for all projects and create a folder for our application in the home directory of the user we created. Install Git.
We leave from the root, we complete ssh.
Install Ruby
We come under the created user on ssh:
:~ ssh first_app@<IP >
:~ rvm install ruby-1.9.2-p318
We leave and go under the root again.
DB, Capistrano and Unicorn
In most cases, mysql is used as a database, but you know, my personal opinion is that if a project is not big, and what a site does there is itself, then you shouldn’t use it, sqlite is enough for it. In addition, we will save a lot of time. Then move to mysql, if you need it at all, you can make it without any problems. Therefore, we will not configure any subd, but go straight to Capistrano.
Add in the Gemfile applications:
group :development do
...
gem 'capistrano-deploy', '~> 0.1.1', :require => nil
end
group :production do
...
gem 'unicorn', '~> 3.6.2', :require => nil
end
Create a Capfile project in the root with the following contents:
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require "rvm/capistrano"
set :rvm_ruby_string, '1.9.2'
require 'capistrano-deploy'
use_recipes :git, :rails, :bundle, :unicorn
server '<IP >', :web, :app, :db, :primary => true
set :user, 'first_app'
set :deploy_to, '/home/first_app/web-app'
set :repository, 'git@github.com:<>'
after 'deploy:update', 'bundle:install'
after 'deploy:restart', 'unicorn:stop'
There is a small nuance here, if you, like my git repository, are on github, then you need to remember to generate rsa keys from under the created user on the VDS. How to do this is written in detail on github.com.
In the terminal we write:
:~ mkdir /etc/sv/first_app_unicorn
:~ touch /etc/sv/first_app_unicorn/run
:~ chmod +x /etc/sv/first_app_unicorn/run
:~ vi /etc/sv/first_app_unicorn/run
We write this file in this file:
#!/bin/sh
exec 2>&1
export USER=first_app
export HOME=/home/$USER
export RAILS_ENV=production
UNICORN="/usr/local/rvm/bin/rvm ruby-1.9.2-p318@first_app exec bundle exec unicorn"
UNICORN_CONF=/etc/unicorn/first_app.rb
cd $HOME/web-app
exec chpst -u $USER:$USER $UNICORN -c $UNICORN_CONF
Next, fill in the /etc/unicorn/first_app.rb file with this:
worker_processes 4
working_directory "/home/first_app/web-app"
listen "/home/first_app/web-app/tmp/sockets/unicorn.sock", :backlog => 64
pid "/home/first_app/web-app/tmp/pids/unicorn.pid"
stderr_path "/home/first_app/web-app/log/unicorn.stderr.log"
stdout_path "/home/first_app/web-app/log/unicorn.stdout.log"
Last spurt:
ln -s /etc/sv/first_app_unicorn /etc/service
Domain Setting
You need to add 2 type A records: for the @ and www subdomains, indicating the IP of your VDS. It would be nice to do this before setting up the server, then while you are all setting up the changes take effect.
Come make sandwiches and run in the browser.
Conclusion
To quickly update minor changes on the site, I created such a file in the application root:
git add .
git commit -a -m "Release"
git push
cap deploy:update
cap deploy:restart
I called it deploy and made it executable. Now to update the site on github and VDS only one command is required:
:~ ./deploy