Деплоим на Raspberry, или пилим бэкенды для поделок. Часть 1: сервер в локальной сети.

Всем привет!

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

В воображении сразу вырисовывались какие-то стойки с blade-ами, аренда виртуалки на Digital Ocean, или, на худой конец, круглосуточно гудящий компьютер под столом.

А ведь хочется чего-то тихого, изящного, бесшумного, и желательно бесплатного…

Стоп! Но ведь все уже изобретено до нас!

Сегодня я хочу рассказать про то, как можно за копейки, обладая минимальным количеством знаний, запилить машину, которая обеспечит 90% ваших (ну, моих — точно) потребностей в бэкенде.
Рассказ будет нести характер записей для самого себя — чтобы не забыть что делать, повторяя это в следующий раз, например)

Кому интересно — го под кат (кстати, обратите внимание, как бутербродом напаяны чипы на плате).
Raspberry Pi - 1

Итак, как вы уже догадались, речь пойдет о Raspberry Pi.
Фффи — скажет кто-то из вас — она ведь ниче не может!
Я тоже так думал, но в спецификации на новую Raspberry Pi-2 написано, что в ней 4 ядра по 1Ghz каждое, и гиг оперативки на борту. Норм? Конечно норм!

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

И вот погуглил я цены и характеристики, и заказал Raspberry B — 2 за 2500 рублей с Aliexpress (уже после скачка курса).
Плюс microSD-карта (обязательно тип 10!) на 8 гигабайт — 600 рублей.
И блок питания c разъемом USB-micro — зарядное устройство для мобильных гаджетов в ближайшей Евросети — еще 500 рублей за самый дорогой.
Итого: 3600 рублей за железки.

Вот так выглядит вторая версия (которая, к слову, пришла в красивой коробочке вместе с корпусом, и парой медных радиаторов: на процессор и ethernet-контроллер).

Raspberry Pi - 2 в корпусе

А пока шла Raspberry 2, товарищ на работе подогнал первую версию — в которой всего лишь одно ядро на 700 Mhz, и 512 Mb RAM, и сейчас работает именно она, а 2-ая версия ждет своего часа для освещения в следующей статье.

Что будем делать
Итак, давайте договоримся, что мы получим под завершение этой статьи.
Сервер на linux, к которому можно подключиться по SSH, удобную и привычную (для меня) CLI на борту, окружение для старта серверов, написанных на Node.js (и Coffee script туда же). И, конечно же, возможность разворачивать и поднимать несколько сервисов а одной машине.

Исходные данные
Железо, на котором я работаю — MacBook Pro, Mac OS X 10.10, почти всё (или даже вообще всё) будем делать из терминала, у меня это iTerm и oh-my-zsh в качестве shell.

Сама плата в примере — Raspberry первой версии, но для второй, думаю, никак отличий не будет.

Итак, начнем.

Raspberry setup
1. Качаем Raspbian здесь: www.raspberrypi.org/downloads/raspbian/
На момент написания там 2 дистрибутива, основанные на разных сборках Debian. Я скачал посвежее: RASPBIAN JESSIE.

2. Пихаем sd-карту в комп, пишем:
$ diskutil list

Находим свою карту (например, /dev/disk4)

3. Отмонтируем карту (здесь и далее пример на /dev/disk4, хотя у вас номер может отличаться):
$ diskutil unmountDisk /dev/disk4

4. Идем в папку со скачанным zip-архивом с образом OS. У меня был в Downloads.
$ cd ~/Downloads

5. Копируем образ на карту (название файла с образом актуально на момент написания статьи, потом может отличаться, естессно):
$ sudo dd bs=1m if=2015-09-24-raspbian-jessie.img of=/dev/rdisk4

6. Вставляем карточку в слот. Подключаем питание и сеть напрямую к компу (ну или через роутер, хотя я напрямую подключал). Ждем, пока загрузится плата — лампочки помигают-помигают, и станут мигать менее интенсивно.

7. В Raspbian уже почти все предварительно настроено, и даже поднят zeroconf, поэтому наша плата доступна. Попингуем raspberrypy.local — и удостоверимся, что пакетики побежали.
$ ping raspberry.local
...видим как пакетики доставляются...

8. Заходим на плату:
$ sudo ssh pi@raspberrypi.local

Вводим пароль для супер-пользователя на вашей машине, на вопрос системы о внесении неизвестного хоста в список известных — говорим yes, вводим дефолтный пароль для пользователя pi на плате: raspberry.

9. Конфигурируем распберри, не мудрствуя лукаво, встроенной утилитой. Эту команду мы выполняем уже не на локальной машине, а на raspberry по ssh, здесь и далее буду писать pi@`hostname`$, когда мы должны запустить команду на будущем сервере:
pi@raspberrypi$ raspi-config

1. Expand file system (надо, чтобы плата умела работать со всей sd-карточкой)
2. Change password (два раза вводим новый пароль)
8. Advanced Options -> hostname (вводим новый hostnamr — у меня это ratm, и дальше примеры будут с этим именем)
8. Advanced Options -> Finish (да, хотим перезагрузить)

10. Reboot. Просто ждём, пока система перезагрузится.

Здесь последует небольшое лирическое отступление.

В нашей локальной сети DHCP довольно умен и выдает не только IP, но и домен.
Поэтому, когда я подключил плату не напрямую к компу, а к локальной сети на работе, искать плату нужно уже не по: raspberry.local (мы же сменили hostname), но и не по ratm.local (ибо DHCP умен и выдал нам чуть другой хостнейм) — пинговать мне уже нужно было по адресу ratm.domen.local, у вас нового домена может не появиться, если роутер не умеет в такой DHCP.

11. Далее убеждаемся что все хорошо (естественно, это мы выполняем на локальной машине):
$ ping ratm.domen.local
...побежали пакетики...

12. Снова заходим на плату, но уже на на другой hostname:
$ ssh pi@ratm.domen.local
[возможно shell спросит спросит вас, включить ли hostname в список доверенных: yes]
password:...

Написать простейший сервер очень легко на Node.js — кто не знает, это такой фреймфорк для JavaScript, который позволяет запускать JS не только внутри браузера, где вообще ему и место, но и снаружи браузера.
JS, конечно, довольно неказист, но когда нужно быстро написать простенький сервачок для своих целей — это то что нужно)

Поднимаем окружение для ноды
13. На всякий случай подтягиваем новые зависимости для менеджера пакетов.
pi@ratm$ sudo apt-get update

14. Устанавливаем ноду.
pi@ratm$ sudo apt-get install nodejs

15. Устанавливаем менеджер пакетов для ноды — без него мы не сможем подтягивать нужные фреймворки для приложений на node.js. Если кто знает про yotta для mbed, то она как раз сделана по образу и подобию npm)
pi@ratm$ sudo apt-get install npm

16. Проверим что все ок.
pi@ratm$ npm -v 
(видим версию)

Делаем красиво — Oh-My-Zsh
Я очень люблю, когда командная строка помогает работать, и выглядит привычно.
Поэтому стараюсь там где можно использовать Oh-My-Zsh. Шаг необязательный, но это очень удобный инструмент с автокомплитом, отображением веток репозиториев, сразу предзабитыми алиасами и вообще очень удобная вещь, так что рекомендую не проходить мимо. Есть, конечно, и минусы, но скорее всего вы с ними не столкнетесь, а вот удовольствия от работы получите — факт.

17. Шаг супер-стандартный — качаем zsh
pi@ratm$ sudo apt-get install zsh

18. На всякий случай удостоверяемся, что git у вас уже есть.
pi@ratm$ apt-get install git-core

19. Подтягиваем oh-my-zsh.
pi@ratm$ wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | zsh

20. Меняем текущий shell нв zsh.
pi@ratm$ chsh -s `which zsh`

21. Перезагружаем систему.
pi@ratm$ sudo shutdown -r now

22. Ждем и заходим снова на raspberry по ssh уже традиционным способом.
Видим, что shell стал минималистичен, красив, и вообще няшка. Вот как на картинке:

Няшный минималистичный oh-my-zsh

НО!
Лично у меня точно такой же shell локально на машине, и чтобы однозначно понимать, где мы находимся — локально или на удаленной машине, сделаем небольшой модик — будем отображать в приглашении строчку [username@hostname] и уже потом приглашение.

Делаем следующие шаги.

23. Устанавливаем vim (это текстовый редактор, тоже шаг не обязательный — если вам удобно работать в другом редакторе — ваш выбор).
pi@ratm$ sudo apt-get install vim

24. Идем модифицировать наш шелл.
pi@ratm$ cd ~/.oh-my-zsh/themes

25. Чтобы корректно вести себя, создадим новую ветку для изменений.
pi@ratm$ gco -b pi-mod

26. Открываем файл, описывающий дефолтный вид командной строки:
pi@ratm$ vim robbyrussell.zsh-theme

27. Заменяем полностью строчку PROMPT на эту:
PROMPT='$FG[141][%n@%m]%{$reset_color%} ${ret_status}%{$fg_bold[green]%}%p %{$fg[cyan]%}%c %{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%} % %{$reset_color%}'

Если вы никогда не работали с vim'ом, у вас возможно немного сломается мозг, потому что сделать нужно в окне редактора вот что:
— нажать i (при это внизу появится надпись, означающая, что вы в режиме редактирования: — INSERT --).
— стереть строчку со старым PROMPT.
— просто вставить (CMD+V) новую строчку на место старой.
— выйти из редактора с записью: для этого нажать ESC, потом `:` (двоеточие — появится двоеточие), написать wq — значит выйти с записью, и нажать ENTER — все просто)

28. Закоммитать изменения на всякий случай:
pi@ratm$ git add -A
pi@ratm$ git commit -m "[PI-#] Change default appearance in robbyrussell theme."
Коммит месседж может быть любым)

29. Перезагружить систему, зайти в неё, и удостовериться, что теперь наше приглашение содержит надпись [username@hostname]. Ура!
pi@ratm$ sudo shutdown -r now
$ ssh pi@ratm.domen.local

У меня это выглядит вот так (с замазанными участками выглядит не так красиво, но все равно примерно понятно — сверху картинки приглашение командной строки моей локальной машины, ниже, когда мы зашли на raspberry — уже её приглашение, которое спутать с локальным довольно сложно):
Еще более няшный oh-my-zsh

Чуть не забыл! Алиас для ноды.
30. Нода запускается командой nodejs, а хотелось бы запускать ее командой node. Создадим нужный симлинк:
pi@ratm$ sudo ln -s /usr/bin/nodejs /usr/bin/node

В принципе, теперь мы можем спокойно запускать сервера, написанные на node.js просто командой:
pi@ratm$ node server.js

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

Для этого есть несколько способов.
Один из них — сконфигурять и использовать Linux Service, в Raspbian это, например, System V.
Но мы пока что пойдем другим — поставим специальный пакет для node.js, который называется forever, и позволяет, к тому же, например, рестартовать сервер поле его падения. Это удобная функция)

31. Устанавливаем forever:
pi@ratm$ sudo -i npm install forever -g

Может потребоваться время. У меня — около 10 минут.

Если forever не встал или не заработал, то возможно поможет пересобрать ноду — это очень просто, но у меня заняло целый день (то есть не у меня, а у Raspberry Pi, 1-ой её версии).
Если вам также не повезло, то делается это вот так:
pi@ratm$ sudo npm uninstall forever -g
pi@ratm$ sudo npm cache clean
pi@ratm$ apt-get install python g++ make
pi@ratm$ mkdir ~/nodejs && cd $_
pi@ratm$ wget -N http://nodejs.org/dist/node-latest.tar.gz
pi@ratm$ tar xzvf node-latest.tar.gz && cd `ls -rd node-v*`
pi@ratm$ ./configure
pi@ratm$ make install
...после оччень долгой сборки (часов 7, например)...
pi@ratm$ sudo npm i forever -g

Запускаем сервер фоновым процессом!
32. И вот, наконец то, ради чего весь сыр-бор. Запускаем наш ненаглядный сервер работать в фоне.
pi@ratm$ forever start server.js

Или для coffee-script:
pi@ratm$ forever start -c coffee server

Помотреть список крутящихся сервисов:
pi@ratm$ forever list

Там же можно найти и название файла, куда пишутся логи.

Стопнуть процесс:
pi@ratm$ forever stop server

Где server — это имя сервиса.

Собственно, это пока всё.
Мы подняли в локальной сети машину, со своим hostname, подняли на ней окружение для сервера, и научились стартовать серверы на node.js (и на coffee-script). При этом стОит она копейки, жрёт мало электричества и не гудит.

А в следующей статье, я попробую описать, как вытащить вашу пишечку наружу — прямо в интернет, прикрутить к белому айпишнику выбранный hostname, да ещё так, чтобы она не стала жертвой какого-нибудь ботнета + поднимем какой-нибудь http-сервер со страничкой и простейшим API.

Кому тема интересна, пишите в комментариях вопросы, постараюсь на них ответить.
У кого есть замечания — тоже не молчите)

Комментарии (14)

RSS свернуть / развернуть
microSD-карта (обязательно тип 10!)
Есть ли смысл использовать 12 или 16?
0
Про типы 12 и 16 ничего не слышал, но есть опыт использования типа 6, и, например, если поднимать сервер minecraft, то лагает) С 10 — таких проблем не чувствуется.
То есть, фразу про тип 10 лучше читать, как `не ниже типа 10`)
0
Правильно они называются mark 1 и mark 3. Вроде как запись в районе 30 MB/s.
Your text to link...
0
Хмм, ну если работать, например, с видеопотоками, то, думаю, можно поставить что-то максимально быстрое, особенно если работать со второй версией Raspberry — будет обидно, если ядра будут простаивать из-за flash IO.
0
Допустим я сделал себе такой сервер и на нем работает мой сайт. Спустя время, сайт стал популярным и нагрузка возросла, теперь одна плата Raspberry не справляется. Как туда прицепить еще несколько таких же, что бы нагрузка равномерно распределилась по нескольким платам?
0
Если трафик подрос до такой степени, что плата не справляется — лучше подумать о платном хостинге, перекинув на него hostname. Пока новый ip не рассосется по DNS-серверам, лучше похостить ресурс и на пишечке, чтобы пользователи ничего не ощутили.

Есть еще вариант поднять nginx и всю статику отдавать им, вместо того чтобы дергать node.js — приложение — но если аудитория и дальше будет расти, то это поможет ненадолго)

Есть, конечно, вариант, за одним айпишником спрятать несколько, и динамически распределять нагрузку (хоть даже, например, классическим round robin), но в таком формате это будет скорее нести характер обучения масштабированию серверов) Легче просто взять платный хостинг, если уж проект до этого дорос.

Как мне видится, применение пишечки уместно для хостинга маложрущих сервисов, тестирования сервисов (прежде чем выкатить на бой — тестируем на удаленном слабеньком сервере — на ней рОдной), разработки сервисов (у меня на ней сейчас крутится slack-бот, который ходит на несколько других сервисов, имеет базу данных и все такое, в планах поднять еще пару сервисов с API, чтобы можно было ходить туда по http).
0
Собрать из распи кластер и поднять балансировщик нагрузки?)
0
Так иногда делают разработчики микросервисов для тестирования)
Как минимум про одного такого человека я слышал — пишет на scala, и тестирует на кластере из pi.
Почему нет)
0
Можно ли поднять ntp сервер на pi?
0
  • avatar
  • foxit
  • 25 октября 2015, 00:03
Вот тут я не знаю, потому что никогда чет не интересовался, как они работают.
С другой стороны, скорее всего они работают тоже по linux.
Raspbian, как видно из названия, это собранный для этих плат Debian, и менеджер пакетов (apt-get) подтягивает пакеты, которые тоже уже предварительно собраны под Raspbian.
Если linux умеет в ntp, но при этом нужных пакетов не будет, то можно просто собрать весь необходимый софт прямо на pi. Процесс это небыстрый и, наверняка, потребует погружения в проблему, но, повторюсь, если ntp-сервер работает на linux, то скорее всего и на pi-шке его можно поднять.
0
Легко.
0
и парой медных радиаторов: на процессор и ethernet-контроллер
А на фото они как-то не похожи на медные…
0
  • avatar
  • Vga
  • 25 октября 2015, 00:20
Да, это фотка из интернетика)
Могу сфотать те, что пришли с моей, как в офисе окажусь)
0
Хорошая статья. Из личного опыта: не все вайфай адаптеры однаково полезны. С ралинками у меня через 5-10 минут шла жуткая потеря пакетов — до 50% и в конце концов вафля отваливалась.
+1
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.