Ruby и .

Установка Ruby on Rails на Windows

Вопреки SEO-шному заголовку, статья затрагивает более обширную тему: разворачивание и настройку полноценного Ubuntu сервера, на котором будут запускаться все ваши Ruby приложения (в том числе Ruby on Rails), устанавливаться джемы и дополнительная инфраструктура (например, базы данных), без которой сложно представить современное веб-приложение.

При этом, благодаря тому, что сервер будет работать в отдельной виртуальной машине, вам не придется отказываться от родной Windows, освоенного вдоль и поперек Notepad++ и обожаемого Дьябло 3.

Почему так сложно

Почему Ubuntu (Linux)

Читатель, уже немного знакомый с Ruby, наверняка спросит «а как же RubyInstaller

Без сомнения, простые инсталляторы вроде RailsInstaller позволяют поиграться с irb и запустить свой первый Магазин-на-Рельсах практически мгновенно. Если закрыть глаза на то, что консоль Windows не способна отображать цвета, а вместо кириллицы выводит знаки вопроса, и что некоторые джемы работают через пень-колоду, это неплохой вариант для тех, кто хочет «пощупать».

Другое дело, если вы всерьез намереваетесь посвятить себя веб-разработке. Рано или поздно придется столкнуться с выкладкой приложения на рабочий сервер, которые — сюрприз! — поголовно работают на Ubuntu/Debian и прочих линуксах. Поэтому в ваших же интересах, чтобы эта встреча случилась рано. Хотя Rails разработчик не обязан быть админом, на практике выходит, что настройкой сервера и поднятием Rails окружения занимается именно он. И уж если на то пошло, нельзя написать эффективное приложение, не понимая, как устроена операционная система, в которой оно запускается.

Если вы верстаете под Ruby on Rails, крайне важно иметь идентичное с остальной командой окружение. Поверьте, когда разработчик в разгар сдачи работы заказчику добавляет в проект новый джем, который не устанавливается на вашей машине, а вам еще переверстывать полмакета, но без злополучного джема даже сервер не запустить — это очень неприятно и для вас, и для разработчика, которому придется эту проблему решать. Имея же у себя на машине Linux-based сервер, вы можете рассчитывать на то, что всё, запускающееся «у них», гарантированно установится и запустится у вас.

Почему Windows

Конечно, не стоит тут же сносить под корень Windows в надежде, что прогрессивные десктопные дистрибутивы, вроде Ubuntu или Linux Mint, смогут заменить годами настраиваемую под себя систему и парк привычных приложений. К сожалению, даже свежие версии Ubuntu приходится «допиливать напильником» (особенно это касается установок на ноутбуки). Постигая тонкости Linux философии и сражаясь с аппаратными и интерфейсными проблемами, вы рискуете потерять интерес к тому, из-за чего всё началось,— Ruby.

Именно поэтому вариант с виртуальной машиной представляется наиболее разумным: вы ничем не жертвуете, не рискуете потерять информацию и продолжаете использовать в работе знакомые инструменты.

Недостатки

Виртуальная машина требует гораздо больше ресурсов, чем Ruby интерпретатор, запущенный непосредственно из-под Windows. Так, ко времени первого запуска Rails проекта придется приплюсовать время старта самой операционной системы (Ubuntu), это же касается объема занимаемой оперативной памяти: ≈400 Mb против 70-80.

Однако, для нынешнего поколения компьютеров такие издержки — уже не что-то запредельное, тогда как преимущества подобного подхода очевидны.

Запуск сервера с помощью Vagrant

Давайте вначале разберемся, к чему мы в итоге должны прийти. Наша цель — установка и настройка виртуальной машины, внутри которой будет крутиться серверный Linux дистрибутив (конкретнее, Ubuntu 12.04 Server).

На сервере будет расшарена папка, поэтому все сохраненные в ней файлы будут одновременно доступны и для редактирования в Windows, и для запуска интерпретатором Ruby в Linux.

Для управления сервером будет использоваться удаленный доступ через SSH с помощью клиента PuTTY. Визуально консоль PuTTY ничем не будет отличаться от родной командной строки Windows, но все команды, конечно же, будут исполняться на стороне сервера, а значит, придется изучить несколько расхожих, специфичных для Linux, команд.

Наконец, чтобы видеть результаты работы, порт 3000 на сервере (который по умолчанию использует Rails) доступен в Windows под тем же номером. Таким образом, зайдя в браузере по локальному адресу http://127.0.0.1:3000, вы на самом деле будете обращаться к приложению, запущенному в этот момент на сервере в виртуальной машине.

Выглядит это примерно так:

Ubuntu server в виртуальной машине

VirtualBox и Vagrant

Приятная новость: бóльшая часть работы по установке и настройке сервера уже сделана, вам достаточно лишь скачать уже готовый образ виртуальной машины и запустить его.

  1. Копия виртуальной машины будет работать под управлением VirtualBox, поэтому для начала нужно убедиться, что у вас установлена версия не ниже 4.1 или установить ее.
  2. Следующий шаг — установка консольной программы Vagrant. Он (Vagrant) займется распаковкой образа виртуальной машины, будет управлять ее запуском и остановкой, а также позволит выполнить тонкую настройку с помощью файла Vagrantfile. Собственно, вам никто не запрещает делать запуск и настройку вручную, Vagrant — просто удобная оболочка для управления VirtualBox.
  3. Скачиваете на жесткий диск т. н. бокс (box), который подготовил я. Vagrant box — не что иное, как архив с образом уже созданной виртуальной машины.
  4. Включение бокса в список доступных Vagrant'у. Эта операция выполняется единожды (если быть точнее, каждый раз, когда вы скачиваете новый бокс). Для этого нужно в консоли (командной строке) Windows набрать vagrant box add ruby path\to\box. Ruby — произвольное имя, которое вы даете боксу, затем идет полный путь до ранее загруженного вами файла.
  5. Поскольку вам часто придется открывать консоль с нужной текущей папкой, это удобнее делать прямо из проводника через контекстное меню папки. Для этого нужно добавить в него пункт «Открыть консоль здесь».
  6. Создаете папку, в которой будут храниться ваши Rails проекты (содержимое этой папки будет доступно серверу в запущенной виртуальной машине). Находясь в этой папке, выполняете в консоли vagrant init ruby. Vagrant создаст в папке шаблонный файл настроек Vagrantfile, его пока не трогаем.
  7. Первый запуск виртуальной машины. Продолжая находиться в папке для будущих проектов, в консоли выполняете vagrant up. В этот момент Vagrant находит Vagrantfile и проверяет, существует ли связанная с этой папкой виртуальная папка, и если нет (а так оно и есть), то клонирует указанный в Vagrantfile базовый бокс и запускает эту копию. Такой подход дает возможность создать несколько независимых друг от друга (и по-разному настроенных) виртуальных машин. Но самое главное, пожалуй, это то, что вы можете без опаски исследовать и настраивать сервер: любые фатальные действия легко исправить, просто удалив «испорченную» машину и создав ее заново из базового бокса.

Второй и последующий запуски выполняются аналогично с помощью vagrant up, но они происходят намного быстрее (используется уже скопированная виртуальная машина).

Обычно после запуска виртуальная машина висит в фоновом режиме вплоть до перезагрузки/выключения Windows, но если вдруг понадобится освободить занимаемую оперативную память, для останова используйте команду vagrant halt.

PuTTY

На запущенном вами сервере уже создан один пользователь c именем vagrant. Чтобы действовать от его имени и управлять системой, вы будете использовать популярный SSH клиент для Windows — PuTTY.

Я выполнил все необходимые настройки клиента, вам остается только скачать его. Распакуйте архив в любую папку и запустите файл ruby-bootstrap.reg, чтобы импортировать настройки в реестр.

После этого достаточно запустить putty.exe, загрузить сессию ruby-bootstrap и нажать Open. Вы будете успешно аутентифицированы на сервере под учетной записью vagrant и можете выполнять команды. Например, запустить интерактивный интерпретатор Ruby:

vagrant@precise32:~$ irb
1.9.3p194 :001 > 1 + 1
 => 2

Для нормального отображения текста в консоли очень рекомендую скачать и установить шрифт DejaVu Sans Mono.

Первый проект Ruby on Rails

На сервере расшареной является корневая папка vagrant, поэтому все файлы, которые вы хотите редактировать «снаружи», нужно создавать там. Последовательность для создания тестового проекта Ruby on Rails может выглядеть так:

vagrant@precise32:~$ cd /vagrant/
vagrant@precise32:/vagrant$ rails new my-project
vagrant@precise32:/vagrant$ cd my-project
vagrant@precise32:/vagrant/my-project$ rails generate scaffold User name
vagrant@precise32:/vagrant/my-project$ rake db:migrate
vagrant@precise32:/vagrant/my-project$ rails server

После этого по адресу http://127.0.0.1:3000/users должна быть видна шаблонная страница для просмотра и редактирования пользователей, а в папке Windows, где была выполнена команда vagrant up, должна появиться подпапка my-project.

Настройка Git и SSH

Каждый уважающий свой труд разработчик работает с кодом только через систему контроля версий. В Ruby сообществе в 99% случаев для этого используется Git, и если не хотите быть белой вороной, придется его установить и освоить.

Поскольку рабочие файлы фактически будут доступны обеим операционным системам, выбор, где настраивать и, собственно, работать с Git, за вами. По собственному опыту могу сказать, что просматривать изменения в файлах удобнее в графическом клиенте, а не в консоли, поэтому лучше это всё-таки делать в Windows.

Для этого нужно установить msysgit (настройки по умолчанию) и сохранить в настройках Git информацию о себе, создав в корне вашей домашней директории файл .gitconfig (именно с точкой в начале) примерно такого содержания:

[user]
  name = Flash Gordon
  email = flash@gordon.com

Что касается графических клиентов, если ваш редактор — Rubymine, в нем уже есть замечательная интеграция с Git, иначе могу порекомендовать установить TurtoiseGit (внедряется в проводник).

Онлайн-репозитории

Следующим шагом, еслы вы планируете использовать Github или BitBucket, будет генерация SSH ключей. Через Пуск -> Программы -> Git -> Git Bash открываете консоль и там вводите (со своим e-mail, конечно же):

ssh-keygen -t rsa -C "flash@gordon.com"

Соглашаетесь с папкой по умолчанию (жмете на ввод), затем еще дважды на ввод для создания пустого пароля для секретного ключа. После этого переходите в созданную генератором папку (.ssh/ в корне вашей домашней директории) и копируете в буфер обмена содержимое публичного ключа id_rsa.pub (про себя отмечаем, что рядом лежит секретный ключ id_rsa, вот его как раз нужно бережно хранить). Скопированный текст нужно вставить в разделе профиля Github или Bitbucket, который так и называется — SSH keys.

Heroku

Если планируете использовать Heroku, то эту же пару ключей нужно скопировать на Ubuntu сервер (т. к. консольная утилита heroku будет установлена именно там). Одинаковая пара на обеих машинах нужна, потому что отправка кода на Heroku будет происходить из Windows через Git, а запуск обслуживающих команд (например, миграции) — на Ubuntu, при этом в обоих случаях будет проводиться проверка подлинности, и конечно же, опознать вас должно как одну и ту же учетную запись.

Для этого, находясь в Windows, нужно скопировать .ssh/ вместе с ключами в расшареную с сервером папку, затем подключиться к запущенной виртуальной машине через PuTTY и там скопировать оба ключа в такую же папку .ssh/, только уже в домашней директории пользователя vagrant (под которым вы, собственно, и работаете):

vagrant@precise32:~$ cd /vagrant/
vagrant@precise32:/vagrant$ cp -r .ssh /home/vagrant
vagrant@precise32:/vagrant$ gem install heroku
vagrant@precise32:/vagrant$ heroku keys:add

RVM

На сервере уже установлен Ruby MRI 1.9.3 через RVM. Последний позволяет держать на машине несколько версий интерпретатора Ruby и переключаться между ними. Допустим, вам понадобится работать со старым проектом на Rails 2.3.X, тогда, чтобы установить версию Ruby 1.8:

vagrant@precise32:~$ rvm install 1.8.7

После этого достаточно поместить в папку с проектом файл .rvmrc содержания:

rvm use 1.8.7

и каждый раз, когда вы будете переходить в эту папку в серверной консоли (а вам придется это сделать, хотя бы для того, чтобы запустить rails server), RVM будет менять текущую версию Ruby на 1.8.7.

Несмотря на то, что RVM поддерживает т. н. gemset'ы, я не рекомендую их использовать. Лучше полагаться на Bundler, тем более, что на сервере уже включена его интеграция с Rubygems, что позволяет запускать исполняемые файлы указанной в Gemfile версии без префикса bundle exec.

Что сразу понадобится в Linux

Консоль

Командная строка для человека, привыкшего к мышке-менюшкам, поначалу кажется настоящим адом. Непонятно, что туда можно вводить вообще, команды (и их параметры!) нужно запоминать (или лезть в справочник), и каждый раз набирать их на клавиатуре. Ниже — самые очевидные вещи, знание которых спасет вам тонну времени и нервов.

История команд

Перемещаться по ней можно с помощью курсорных клавиш вверх/вниз. Например, вы опечатались и набрали вместо rails server:

vagrant@precise32:/vagrant/my-shop$ rals server

на что получите резонный ответ «не знаю такой команды» и пустое приглашение:

rals: command not found
vagrant@precise32:/vagrant/my-shop$

Вместо того, чтобы вводить всё по-новой, нажмите клавишу вверх и исправьте в подставленной команде опечатку.

Автодополнение

Для длинных команд очень полезным оказывается автодополнение по клавише Tab после того, как набрано несколько начальных символов. Кроме названий исполняемых файлов дополняются имена папок и файлов, и это очень спасает, когда в качестве параметра нужно указать полный путь к файлу.

Если несколько команд начинаются одинаково (такое случается нередко), а набранных букв недостаточно для однозначной подстановки, повторное нажатие на Tab покажет все возможные варианты.

Например, в текущей папке лежат файлы user.rb и uploader.rb, и вы хотите запустить последний в интерпретаторе Ruby. Тогда достаточно набрать в консоли:

vagrant@precise32:/vagrant/utils$ ruby up 

нажать Tab (команда автоматически развернется до ruby uploader.rb), а затем на ввод.

Ввод паролей

Пароли при вводе не маскируются звездочками, как в Windows, они вообще не отображаются. Это нормально, нужно просто ввести нужную фразу и нажать на ввод.

Ctrl+C Ctrl+V

Вставка из буфера обмена выполняется правой клавишей мыши, а чтобы скопировать туда текст, нужно просто выделить его мышью.

Запуск нескольких программ

По умолчанию программы (процессы), запущенные в консоли (терминале), привязываются к нему. С одной стороны это удобно, т. к. позволяет завершать процесс с помощью комбинации клавиш Ctrl+C (или Ctrl+D), все сообщения выводятся в этот же терминал (например, логи Rails сервера). С другой стороны — не очень удобно, потому что запущенное приложение блокирует такой терминал и никаких других команд уже не введешь.

Обойти это ограничение просто: запуском еще одной консоли, в данном случае еще одного экземпляра PuTTY. Если вас раздражает куча открытых окон, обратите внимание на SuperPutty, который добавляет поддержку табов.

Файловая система

В Linux у файлового дерева может быть только один корень (он обозначается /), тогда как в Windows их может быть несколько, в зависимости от количества разделов: диски C:\, D:\ и т. д. Поскольку корень один, то все остальные разделы и устройства (например, DVD-Rom) видны как обычные папки, подключенные к нему (названия и конкретное месторасположение целиком на совести пользователя).

Разделителем в файловых путях является прямая косая черта (/), например

/vagrant/projects/my-shop/app/models/user.rb

Если путь начинается ею (а значит — с корня), то он является абсолютным, иначе — относительным от текущей папки. Иногда для запуска исполнительных файлов требуется принудительно указать системе искать файл относительно текущего местоположения, тогда путь начинают с точки (например, ./bin/start).

Если точкой можно заменить текующую папку, то двоеточием (..) — родительскую, например, путь ../recipes означает: чтобы найти папку recipes, нужно подняться на уровень выше текущей.

Текущая папка всегда отображается в консоли после имени пользователя. По умолчанию (при открытии нового терминала) это его домашняя директория (в вашей виртуальной машине это /home/vagrant), для которой имеется краткий синоним: ~.

Чтобы сменить текущую директорию, используется команда cd (change directory), она может принимать в качестве аргумента как абсолютный, так и относительный путь. Допустим, в домашней директории пользователя vagrant есть две папки: my_music и my_books, тогда:

vagrant@precise32:~$ cd my_music
vagrant@precise32:~/my_music$ cd
vagrant@precise32:~$ cd /home/vagrant/my_books
vagrant@precise32:~/my_books$ cd ..
vagrant@precise32:~$

Чтобы просмотреть содержимое папки, используют команду ls (list). Если вызвать ее без аргументов, увидите, что находится в текущей папке, иначе — в том месте, которое указали. Поскольку в Linux файлы и папки, начинающиеся с точки, считаются скрытыми (например, .ssh), просмотреть всё содержимое папки помогает вызов с ключом a (all): ls -a.

Администраторские права

Как и в любой другой операционной системе, некоторые важные действия (например, установку и удаление программ глобально, на уровне системы) могут выполнять только пользователи с администраторскими правами. В Linux в таком случае обычно подразумевают пользователя с неограниченными правами (root user или superuser), однако, входить в систему и постоянно работать под этой учетной записью крайне не рекомендуется из соображений безопасности.

Вместо этого пользователю vagrant (под которым вы работаете в виртуальной машине) разрешено в момент выполнения любой команды притвориться администратором с помощью префикс-команды sudo. Например, чтобы увидеть содержимое папки lost+found, недостаточно набрать ls /lost+found, нужно в этот момент быть суперпользователем: sudo ls /lost+found.

После ввода такой команды запрашивается пароль того пользователя, который ее выполняет (а не того, кем он хочет стать), в вашем случае — пользователя vagrant (пароль — vagrant). В данной системе запрос пароля отключен (что категорически запрещено делать на реальных серверах по понятным причинам), но это не значит, что sudo достаточно ввести только для первой команды и «переключиться в режим бога», каждая команда, требующая администраторских прав, должна начинаться с sudo.

Редактирование файлов

Иногда вам потребуется отредактировать файлы, которые лежат вне расшаренной папки /vagrant. Вместо того, чтобы копировать их в расшаренную папку, редактировать там из-под Windows и копировать обратно, гораздо проще использовать консольные текстовые редакторы.

В Ubuntu для этого можно использовать nano или vim. Первый практически ничем не отличается от стандартного Блокнота, из второго нужно уметь выйти :)

Обе команды (редакторов) принимают в качестве аргумента полный или относительный путь к файлу. Если он существует, то будет открыт для правки, иначе — будет создан во время первого сохранения, например:

vagrant@precise32:~$ nano notes

или

vagrant@precise32:~$ vim hello.rb

Редактор Nano проще для понимания тем, что открывается сразу в привычном режиме редактирования. Внизу видны подсказки с командами, где ^ обозначает клавишу Ctrl. Таким образом, сохранить изменения можно с помощью Ctrl+O, выйти — Ctrl+X.

Vim горазде сложнее, и я не рекомендую его для новичка, но может так статься, что система принудительно откроет файл именно в нем. В этом случае нужно знать, что переход в режим редактирования выполняется клавишей i. После того, как вы внесли правки, нужно выйти из режима редактирования с помощью клавиши Esc, перейти в командный режим нажатием клавиши : (Shift+;) и ввести wq (write quit — сохранить и выйти). Чтобы выйти без сохранения, в командном режиме нужно набрать q!

Установка программ

TODO

SSH

SSH — это название протокола для безопасного (зашифрованного) соединения двух машин по сети. Обычно под этим подразумевается удаленный доступ к консоли (оболочке, shell; собственно, отсюда и название — Secure SHell) компьютера, но этим возможности SSH не ограничиваются. Например, он же может использоваться для безопасного (с точки зрения перехвата злоумышленником) копирования файлов между двумя машинами; Github, BitBucket, Heroku используют SSH для проверки подлинности пользователя.

Пару в SSH соединении составляют сервер и клиент. На сервере имеется учетная запись (которая обладает определенным набором прав), клиент же проходит процедуру опознания (аутентификации), после чего действует от имени этой учетной записи.

SSH использует аутентификацию на базе системы шифрования с открытым ключом. Клиент предварительно создает особую пару «секретный ключ - публичный ключ», после чего связывает публичный ключ со своей учетной записью на сервере. Эта привязка выполняется не через SSH, например, в случае с Github нужно зайти в браузере на страницу своего профиля и загрузить там содержание своего публичного ключа.

Пара «секретный ключ - публичный ключ» обладает несколькими важными свойствами. Во-первых, она всегда уникальна. Во-вторых, имея на руках зашифрованное публичным ключом сообщение, его практически невозможно расшифровать, даже получив доступ к публичному ключу. Однако, хозяин секретного ключа может выполнить обратное преобразование. На основании этого сервер в процессе «предварительного общения» с клиентом может сделать вывод, что удаленная машина, от которой он получает ответы, действительно та, за кого себя выдает.

Надежность такой системы в том, что секретный ключ не хранится на сервере и не передается в процессе коммуникации с клиентом. Более того, при создании пары генератор ключей позволяет зашифровать и сам секретный ключ. С одной стороны, это обезопасит от возможной кражи секретного ключа, с другой — чтобы SSH клиент смог использовать этот ключ, хозяину придется вводить к нему пароль (passphrase) во время установления сессии. Если уверены, что кроме вас секретным ключом никто не может воспользоваться, пароль для него можно оставить пустым.

Безопасность

Берегите свои секретные ключи как зеницу ока. При малейшем подозрении, что они попали в чужие руки, меняйте публичные ключи на всех серверах (точно так же, как меняете дверной замок, когда теряете ключ).

При этом учтите, что по умолчанию связь между PuTTY и запущенными виртуальными машинами происходит через небезопасную пару ключей, которая создана разработчиками Vagrant. Небезопасна она именно потому, что секретный ключ общедоступен (и, теоретически, может быть использован злоумышленником для доступа к вашей виртуальной машине). Поэтому, если вы планируете работать с важной информацией, нужно убедиться, что порт 2222 недоступен извне, или принять меры по его закрытию (фаервол).

TODO