Ruby on Rails
Ruby on Rails (よく Rails とか RoR と略されます) は Ruby プログラミング言語によるオープンソースのウェブアプリケーションフレームワークです。Rails はウェブ開発者によって高速な開発のために使用されているアジャイル開発で使われるように出来ています。
このドキュメントでは Arch Linux システムで Ruby on Rails フレームワークをセットアップする方法を説明します。
目次
インストール
Ruby on Rails を使うには Ruby をインストールする必要があるので、先に Ruby の記事を読んでインストールを済まして下さい。また、nodejs パッケージも必要に成ります。
Ruby on Rails 自体は複数の方法でインストールできます:
選択肢 A: RubyGems
現在のユーザーで Rails をインストールするコマンド:
$ gem install rails
ドキュメントのビルドには時間がかかります。ドキュメントは不要の場合、--no-document
を install コマンドに付けて下さい。
$ gem install rails --no-document
gem は Ruby モジュールのパッケージマネージャであり、Arch Linux における pacman のようなものです。gem をアップデートするには、次を実行:
$ gem update
選択肢 B: pacgem
AUR の pacgemAUR を使って Rails をインストールすることができます。Pacgem は自動的に PKGBUILD を作成して、それぞれの gem の Arch パッケージを作成します。そしてパッケージは pacman を使ってインストールされます。
# pacgem rails
gem パッケージは次のコマンドでアップデートできます:
# pacgem -u
選択肢 C: AUR
AUR には ruby-railsAUR パッケージが存在します。
選択肢 D: Quarry バイナリリポジトリ
非公式の quarry リポジトリから ruby-rails をインストールしてください。
設定
Rails には WeBrick という名前のベーシックな HTTP サーバーが付属しています。テストアプリケーションを作成してテストすることができます。まず、rails コマンドでアプリケーションを作成:
$ rails new testapp_name
現在の作業ディレクトリの中に新しいフォルダが作成されます。
$ cd testapp_name
次にウェブサーバーを起動します。デフォルトではポート 3000 を使います:
$ rails server
ローカルマシンのブラウザから http://localhost:3000 を開いて testapp_name のウェブサイトを開いてください。
テストページには "Welcome aboard" と表示されるはずです。
アプリケーションサーバー
The built-in Ruby On Rails HTTP server (WeBrick) is convenient for basic development, but it is not recommended for production use. Instead, you should use an application server such as #Thin, #Unicorn or Phusion Passenger.
Thin
First install thin gem:
$ gem install thin
Then start it using:
$ thin start
Unicorn
Unicorn is a stand-alone application server that cannot talk directly to clients. Instead, a web server must sit between clients and Unicorn, proxying requests as needed. Unicorn is loosely based on Mongrel. It is used by Github, and it uses an architecture that tries hard to find the best child for handling a request. Explanation of differences between Unicorn and Mongrel.
Install the Unicorn gem:
# gem install unicorn
Then create a configuration file for your application in /etc/unicorn/
. For example; here is a configuration example (Based on [1]) for Redmine:
/etc/unicorn/redmine.ru
working_directory "/srv/http/redmine" pid "/tmp/redmine.pid" preload_app true timeout 60 worker_processes 4 listen 4000 stderr_path('/var/log/unicorn.log') GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true after_fork do |server, worker| #start the worker on port 4000, 4001, 4002 etc... addr = "0.0.0.0:#{4000 + worker.nr}" # infinite tries to start the worker server.listen(addr, :tries => -1, :delay => -1, :backlog => 128) #Drop privileges if running as root worker.user('nobody', 'nobody') if Process.euid == 0 end
Start it using:
# usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru
Systemd サービス
Put the following contents in /etc/systemd/system/unicorn.service
:
/etc/systemd/system/unicorn.service
[Unit] Description=Unicorn application server After=network.target [Service] Type=forking User=redmine ExecStart=/usr/bin/unicorn -D -E production -c /etc/unicorn/redmine.ru [Install] WantedBy=multi-user.target
You can now easily start and stop unicorn using systemctl
Nginx の設定
After setting up Nginx, configure unicorn as an upstream server using something like this (Warning: this is a stripped example. It probably doesn't work without additional configuration):
http { upstream unicorn { server 127.0.0.1:4000 fail_timeout=0; server 127.0.0.1:4001 fail_timeout=0; server 127.0.0.1:4002 fail_timeout=0; server 127.0.0.1:4003 fail_timeout=0; } server { listen 80 default; server_name YOURHOSTNAMEHERE; location / { root /srv/http/redmine/public; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://unicorn; } } }
Apache/Nginx (Phusion Passenger を使用)
Passenger also known as mod_rails
is a module available for Nginx and Apache, that greatly simplifies setting up a Rails server environment. Nginx does not support modules as Apache and has to be compiled with mod_rails
in order to support Passenger; let Passenger compile it for you. As for Apache, let Passenger set up the module for you.
Start by installing the 'passenger' gem:
# gem install passenger
If you are aiming to use Apache, run:
# passenger-install-apache2-module
In case a rails application is deployed with a sub-URI, like http://example.com/yourapplication, some additional configuration is required, see the modrails documentation
For Nginx:
# passenger-install-nginx-module
The installer will provide you with any additional information regarding the installation (such as installing additional libraries).
To serve an application with Nginx, configure it as follows:
server { server_name app.example.org; root path_to_app/public; # Be sure to point to 'public' folder! passenger_enabled on; rails_env development; # Rails environment. }
データベース
Most web applications will need to interact with some sort of database. ActiveRecord (the ORM used by Rails to provide database abstraction) supports several database vendors, the most popular of which are MySQL, SQLite, and PostgreSQL.
SQLite
SQLite is the default lightweight database for Ruby on Rails. To enable SQLite, simply install sqlite.
PostgreSQL
postgresql をインストールしてください。
MySQL
First, install and configure a MySQL server. Please refer to MySQL on how to do this.
A gem with some native extensions is required, probably best installed as root:
# gem install mysql
You can generate a rails application configured for MySQL by using the -d
parameter:
$ rails new testapp_name -d mysql
You then need to edit config/database.yml
. Rails uses different databases for development, testing, production and other environments. Here is an example development configuration for MySQL running on localhost:
development: adapter: mysql database: my_application_database username: development password: my_secret_password
Note that you do not have to actually create the database using MySQL, as this can be done via Rails with:
# rake db:create
If no errors are shown, then your database has been created and Rails can talk to your MySQL database.
Rails パーフェクトセットアップ
Phusion Passenger running multiple Ruby versions.
- Arch Linux: A simple, lightweight distribution. ;)
- Nginx: A fast and lightweight web server with a strong focus on high concurrency, performance and low memory usage.
- Passenger (a.k.a. mod_rails or mod_rack): Supports both Apache and Nginx web servers. It makes deployment of Ruby web applications, such as those built on Ruby on Rails web framework, a breeze.
- Ruby Version Manager (RVM): A command-line tool which allows you to easily install, manage, and work with multiple Ruby environments from interpreters to sets of gems. RVM lets you deploy each project with its own completely self-contained and dedicated environment —from the specific version of ruby, all the way down to the precise set of required gems to run your application—.
- SQLite: The default lightweight database for Ruby on Rails.
ステップ 0: SQLite
Install sqlite.
ステップ 1: RVM
Make a multi-user RVM installation as specified here.
In the 'adding users to the rvm group' step, do
# usermod -a -G rvm http # usermod -a -G rvm nobody
http
and nobody
are the users related to Nginx and Passenger, respectively.
ステップ 2: Ruby
Once you have a working RVM installation in your hands, it is time to install the latest Ruby interpreter
$ rvm install 2.0.0
ステップ 3: Nginx と Passenger
Run the following to allow passenger install nginx:
$ rvm use 2.0.0 $ gem install passenger $ rvmsudo passenger-install-nginx-module
The passenger gem will be put into the default gemset.
This will download the sources of Nginx, compile and install it for you. It will guide you through all the process. Note that the default location for Nginx will be /opt/nginx
.
After completion, add the following two lines into the 'http block' at /opt/nginx/conf/nginx.conf
that look like:
http { ... passenger_root /usr/local/rvm/gems/ruby-2.0.0-p353/gems/passenger-3.0.9; passenger_ruby /usr/local/rvm/wrappers/ruby-2.0.0-p353/ruby; ... }
ステップ 4: Gemsets と Apps
For each Rails application you should have a gemset. Suppose that you want to try RefineryCMS against BrowserCMS, two open-source Content Management Systems based on Rails.
Install RefineryCMS first:
$ rvm use 2.0.0@refinery --create $ gem install rails -v 4.0.1 $ gem install passenger $ gem install refinerycms refinerycms-i18n sqlite3
Deploy a RefineryCMS instance called refineria:
$ cd /srv/http/ $ rvmsudo refinerycms refineria
Install BrowserCMS in a different gemset:
$ rvm use 2.0.0@browser --create $ gem install rails -v 4.0.1 $ gem install passenger $ gem install browsercms sqlite3
Deploy a BrowserCMS instance called navegador:
$ cd /srv/http/ $ rvmsudo browsercms demo navegador $ cd /srv/http/navegador $ rvmsudo rake db:install
Passenger for Nginx and Passenger Standalone
Observe that the passenger gem was installed three times and with different intentions; in the environments
- 2.0.0 => for Nginx,
- 2.0.0@refinery => Standalone
- 2.0.0@browser => Standalone
The strategy is to combine Passenger for Nginx with Passenger Standalone. One must first identify the Ruby environment (interpreter plus gemset) that one uses the most; in this setup the Ruby interpreter and the default gemset were selected. One then proceeds with setting up Passenger for Nginx to use that environment (step 3).
- Applications within the chosen environment can be served as in Apache/Nginx (using Phusion Passenger), page up in this article.
- All applications that are to use a different Ruby version and/or gemset can be served separately through Passenger Standalone and hook into the main web server via a reverse proxy configuration (step 6).
ステップ 5: .rvmrc ファイルと所有者
This step is crucial for the correct behaviour of the setup. RVM seeks for .rvmrc files when changing folders; if it finds one, it reads it. In these files normally one stores a line like
rvm <ruby_version>@<gemset_name>
so the specified environment is set at the entrance of applications' root folder.
Create /srv/http/refineria/.rvmrc doing
# echo "rvm ree@refinery" > /srv/http/refineria/.rvmrc
, and /srv/http/navegador/.rvmrc with
# echo "rvm 2.0.0@browser" > /srv/http/navegador/.rvmrc
You have to enter to both application root folders now, because every first time that RVM finds a .rvmrc it asks you if you trust the given file, consequently you must validate the two files you have just created.
These files aid the programs involved to find the correct gems.
Apart, if applications' files and folders are not owned by the right user you will face database write-access problems. The use of rvmsudo produces root-owned archives when generated by Rails; in the other hand, nobody is the user for Passenger —if you have not changed it—: who will use and should posses them. Fix this doing
# chown -R nobody.nobody /srv/http/refineria /srv/http/navegador
ステップ 6: リバースプロキシ
You have to start the Passenger Standalone web servers for your applications. So, do
$ cd /srv/http/refineria $ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d
and
$ cd /srv/http/navegador $ rvmsudo passenger start --socket tmp/sockets/passenger.socket -d
. The first time that you run a Passenger Standalone it will perform a minor installation.
Note that you are using unix domain sockets instead of the commonly-used TCP sockets; it turns out that unix domain are significantly faster than TCP sockets.
システムの起動時に Passenger Standalone デーモンを起動
Do you have a script? Please post it here.
The systemd script below was made for a Typo blog I host at /srv/http/typo. It's located at /etc/systemd/system/passenger_typo.service. I set the Environment= tags (see "man systemd.exec") from the output of "rvm env". The only exception was PATH=, which I had to combine from my regular PATH and the output of rvm env.
Note: If you don't set the "WorkingDirectory=" variable to your application folder, passenger will fail to find your app and will subsequently shut itself down.
[Unit] Description=Passenger Standalone Script for Typo After=network.target [Service] Type=forking WorkingDirectory=/srv/http/typo PIDFile=/srv/http/typo/tmp/pids/passenger.pid Environment=PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo/bin:/usr/local/rvm/gems/ruby-2.0.0-p0@global/bin:/usr/local/rvm/rubies/ruby-2.0.0-p0/bin:/usr/local/rvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl Environment=rvm_env_string=ruby-2.0.0-p0@typo Environment=rvm_path=/usr/local/rvm Environment=rvm_ruby_string=ruby-2.0.0-p0 Environment=rvm_gemset_name=typo Environment=RUBY_VERSION=ruby-2.0.0-p0 Environment=GEM_HOME=/usr/local/rvm/gems/ruby-2.0.0-p0@typo Environment=GEM_PATH=/usr/local/rvm/gems/ruby-2.0.0-p0@typo:/usr/local/rvm/gems/ruby-2.0.0-p0@global Environment=MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.0.0-p0 Environment=IRBRC=/usr/local/rvm/rubies/ruby-2.0.0-p0/.irbrc ExecStart=/bin/bash -c "rvmsudo passenger start --socket /srv/http/typo/tmp/sockets/passenger.socket -d" [Install] WantedBy=multi-user.target
ステップ 7: デプロイメント
サブドメインを使用
Once again edit /opt/nginx/conf/nginx.conf to include some vital instructions:
## RefineryCMS ## server { server_name refinery.domain.com; root /srv/http/refineria/public; location / { proxy_pass http://unix:/srv/http/refineria/tmp/sockets/passenger.socket; proxy_set_header Host $host; } } ## BrowserCMS ## server { server_name browser.domain.com; root /srv/http/navegador/public; location / { proxy_pass http://unix:/srv/http/navegador/tmp/sockets/passenger.socket; proxy_set_header Host $host; } }
サブドメインを使用しない
If you for some reason don't want to host each application on it's own subdomain but rather in a url like: site.com/railsapp
then you could do something like this in your config:
server { server_name site.com; #Base for the html files etc root /srv/http/; #First application you want hosted under domain site.com/railsapp location /railsapp { root /srv/http/railsapp/public; #you may need to change passenger_base_uri to be the uri you want to point at, ie: #passenger_base_uri /railsapp; #but probably only if you're using the other solution with passenger phusion proxy_pass http://unix:/srv/http/railsapp/tmp/sockets/passenger.socket; proxy_set_header Host $host; } #Second applicatino you want hosted under domain site.com/anotherapp location /anotherapp { root /srv/http/anotherapp/public; #same thing about the passenger_base_uri here, but with value /anotherapp instead proxy_pass http://unix:/srv/http/anotherapp/tmp/sockets/passenger.socket; proxy_set_header Host $host; } }
At this point you are in conditions to run Nginx with:
# systemctl start nginx
and to access both CMSs through refinery.domain.com and browser.domain.com.
参照
- http://beginrescueend.com/integration/passenger
- http://blog.phusion.nl/2010/09/21/phusion-passenger-running-multiple-ruby-versions
参照
- Ruby on Rails http://rubyonrails.org/download.
- Mongrel http://mongrel.rubyforge.org.