Мега-Підручник Flask, Частина 17: Розгортання на Linux (і навіть на Raspberry Pi!)

Це сімнадцята стаття в серії, де я описую свій досвід написання веб-додатки на Python з використанням микрофреймворка Flask.

Мета даного посібника — розробити досить функціональний додаток-мікроблог, яке я за повною відсутністю оригінальності вирішив назвати microblog.

ЗмістЧастина 1: Привіт, Світ!
Частина 2: Шаблони
Частина 3: Форми
Частина 4: База даних
Частина 5: Вхід користувачів
Частина 6: Сторінка профілю і аватари
Частина 7: Unit-тестування
Частина 8: Передплатники, контакти і друзі
Частина 9: Пагинация
Частина 10: Повнотекстовий пошук
Частина 11: Підтримка e-mail
Частина 12: Реконструкція
Частина 13: Дата і час
Частина 14: I18n and L10n
Частина 15: Ajax
Частина 16: Налагодження, тестування і профілювання
Частина 17: Розгортання на Linux (і навіть на Raspberry Pi!)(дана стаття)
Частина 18: Розгортання на Heroku Cloud


Сьогодні знакова подія в житті нашої програми. Ми збираємося представити його широкої громадськості і розглянемо різні способи розгорнути додаток і зробити його доступним нашим користувачам.

У цій статті я досліджую традиційні способи розміщення програми в мережі Інтернет, а тому зосереджуся на використанні Linux серверів, а також на досить популярному миникомпьютере Raspberry Pi. Хмарні сервіси ми розглянемо в наступній статті.

Для початку ми розглянемо, мабуть, самий усталений вид хостингу. Ми встановимо наш додаток на виділеному хості, що працює під управлінням веб-сервера.

Де ж нам знайти хост для розміщення? На сьогоднішній день існує багато пропозицій недорогого хостингу. Найменш затратним варіантом є використання VPS (virtual private server) — віртуальної машини, виглядає для нас як виділений сервер, однак насправді розділяє фізичні ресурси з іншими користувачами хостингу. Ви можете вивчити пропозиції на lowendbox.com, якщо хочете орендувати VPS для експериментів (зауважте, посилання не реферальная, а значить я не отримаю ні цента з вашого кліка по посиланню).

Ще один простий спосіб роздобути хост для установки нашого додатки — установка віртуальної машини на ваш власний домашній комп'ютер. Якщо ви користувач Windows або Mac і хотіли б придбати досвід розгортання програми на сервері, керованому Linux, і при цьому не витратити ні копійки — тоді це ваш варіант. Встановіть VirtualBox, скачайте ISO образ Linux дистрибутива по вашому розсуду, створити Віртуальну Машину (VM) і встановіть на неї ОС за допомогою раніше завантаженого образу.

Давайте трохи поговоримо про вибір ОС. Я думаю, що в якості платформи для розміщення веб сервера слід розглядати наступні 4 операційні системи:
  • Linux
  • BSD
  • OS X
  • Windows
З технічної точки зору, ви можете використовувати будь-яку з цих ОС для хостингу свого python програми, так як же зробити вибір?

На мою думку, вибір зробити зовсім не складно. Для мене важливо, щоб платформа була відкритою, оскільки велика спільнота розробників і користувачів справляється із завданням підтримання надійності та безпеки продукту набагато краще, ніж одна компанія може зробити, працюючи поодинці над своїм закритим продуктом. Крім того, ми б хотіли мати доступ до великої кількості софту для установки, т. до. у разі виникнення проблем, в цьому випадку у нас буде більше шансів вирішити їх. Грунтуючись на наведених вище критеріях, я вважатиму за краще використовувати сервер під управлінням Linux або BSD сервера, який працює на Windows і OS X.

Отже кількість варіантів скоротилася до двох. А от вибір між Linux і BSD, як по мені, і зовсім елементарний: немає ніякої різниці, що використовувати. Обидва є відмінними варіантами для розміщення веб сервера. В залежності від хостинг-провайдера, ви, швидше за все, будете мати можливість вибрати Linux або BSD, тому я просто використовую те, що є в наявності.

Крім того, існують різні дистрибутиви Linux і BSD, як вибрати з них? Це, здебільшого, справа особистих уподобань, але якщо ми хочемо використовувати найбільш популярний дистрибутив, ми можемо розбити всі дистрибутиви на групи відповідно до основним характеристикам, а вже потім вибрати найбільш популярний з відібраної групи:
  • побудовані на базі RPM (RedHat, CentOS, Fedora)
  • побудовані на базі Debian (Debian, Ubuntu, Mint)
  • побудовані на базі BSD (FreeBSD, NetBSD, OpenBSD)
  • інші
Напевно, моя дуже спрощена класифікація дистрибутивів залишила деякі дистрибутиви без уваги. Я також упевнений, що багато хто вважатиме своїм обов'язком нагадати, що Mac OS Х також належить сімейства BSD і повинна бути додана в мій список. Пам'ятайте, це моя власна класифікація і я не розраховую, що всі навколо з нею погодяться.

В якості вправи, при підготовці цієї статті, я протестував кілька дистрибутивів Linux (справа в тому, що на моєму VPS відсутня опція установки BSD). Я випробував Fedora, Ubuntu, Debian і CentOS. Жоден з цих дистрибутивів не виявився простим в установці, але з них усіх, установка і настройка CentOS пройшла найбільш гладко, так що далі мова піде саме про CentOS.

Якщо раніше ви ніколи не займалися первісної налаштування сервера, ви можете знайти це заняття досить стомлюючим. І будете праві. Однак, після налаштування сервера, підтримання його працездатності вимагає мінімуму зусиль.

Готові? Тоді почнемо!

Хостинг на CentOS 6

Я припускаю, що у нас є свежеустановленный дистрибутив CentOS 6 на виділеному сервері або на VPS. Віртуальна машина на вашому PC також підійде, але перш ніж продовжити, встановіть ОС.

Налаштування клієнтської сторони
Ми будемо управляти сервером віддалено з нашого домашнього ПК, тому нам потрібно інструмент для реєстрації в системі і запуску команд. Якщо ваш ПК працює під управлінням Linux або OS X, то у вас вже встановлений OpenSSH. Якщо ж ви користувач ОС від Microsoft, тоді у вас є вибір з двох варіантів:
  • Cygwin (виберіть пакет OpenSSH в інсталятор)
  • Putty
Cygwin це набагато більше ніж просто SSH, він надає Linux подібне оточення всередині Windows. Putty, з іншого боку, є просто клієнтом SSH. Тому я планую висвітлити самі основи, інструкції нижче будуть для користувачів Linux, OS X і Cygwin. Якщо ви вирішите використовувати Putty з Windows, тоді може знадобитися деяка адаптація представлених нижче інструкцій.

Давайте почнемо з авторизації на нашому новенькому CentOS 6 сервері. Відкрийте командний рядок на вашому ПК (або Cygwin консоль якщо ви використовуєте Windows) і запустіть команду:

$ ssh root@<your-server>

Ця команда означає, що ви хочете увійти на сервер під обліковим записом користувача root, адміністратора системи. Ви повинні замінити <your-server> на IP-адресу або ім'я вашого сервера. Зверніть увагу, що ви не повинні вводити символ $, це всього лише запрошення командного рядка.

Далі вам буде запропоновано ввести пароль користувача root. Якщо це виділений сервер (VPS, то ви вводили пароль під час процесу установки. Якщо це ваша власна віртуальна машина, то ви встановили пароль під час інсталяції.

Встановлення пакунків з програмним забезпеченням
Тепер, коли ми увійшли в систему, нам необхідно встановити все необхідне програмне забезпечення, яке напевно буде включати Python і веб сервер. Крім того, ми замінимо sqlite на більш надійну СУБД — MySQL.

Команда, використовувана для установки в CentOS називається yum. Ми можемо встановити всі необхідні пакети однією командою:

$ yum install python python-devel httpd httpd-devel mysql-server, mysql-devel git gcc sudo

Деякі з пакетів можуть бути вже встановлені, в цьому випадку yum пропустить їх і встановить тільки ті пакети.

Ми тільки що встановили наступні пакети:
  • perl і python-devel: інтерпретатор Python та його інструменти розробника (відмінності файли та статичні бібліотеки)
  • httpd і httpd-devel: веб-сервер Apache та його інструменти розробника
  • mysql-server і mysql-devel: сервер СУБД MySQL та його інструменти розробника
  • git: розподілена система керування версіями файлів (ми будемо використовувати її для завантаження і оновлення програми)
  • gcc: компілятор C/C++ (потрібен для компіляції розширення Python)
  • sudo: інструмент для запуску команд від імені іншого користувача.
Створення окремого користувача для нашого додатка
Тепер ми налаштуємо окремий обліковий запис, під яким і буде запускатися наш додаток. Якщо причини цього не ясні, поясню — користувач root має максимальні права, т.ч. ми легко може видалити або пошкодити важливі компоненти системи в результаті помилки. Якщо ж ми будемо працювати під обмеженим (користувача) акаунтом, то важливі компоненти системи будуть недосяжні для нас, а це захистить нас від помилок. І друга, можливо, більш істотна причина не використовувати обліковий запис root полягає в тому, що якщо зловмисник заволодіє цим обліковим записом, він отримає повний контроль над сервером. Ми збираємося приховати обліковий запис root так, як це тільки можливо, я волію взагалі відключати можливість віддаленого входу під вашим обліковим записом адміністратора.

Ми назвемо новий аккаунт apps, припускаючи, що з часом у нас буде працювати кілька додатків на цьому сервері. Тому програми будуть запускатися під обліковим записом веб сервера, ми додамо наш аккаунт apps в групу веб сервера (яка була створена під час інсталяції Apache), таким чином, веб сервер буде мати права на читання і запис файлів нашої програми. Якщо ви не знайомі з системою прав користувача в Unix, тоді короткий посібник може бути знайдено в Вікіпедії.

Команда створення користувача apps в CentOS виглядає так:

$ adduser-g apache apps

Ключ-g робить головною групою створюваного користувача групу apache, яка на CentOS є групою apache. Далі, у вас запитають пароль для нового користувача.

Команда adduser створить домашню теку для нового аккаунта, розташовану за адресою /home/apps. Однак, якщо перевірити права доступу цієї папки, ми виявимо, що вона доступна тільки своєму власнику:

$ ls /home-l
total 7
drwx------ 2 apps apache 4096 Apr 7 11:46 apps

Ми вирішили, що користувачі групи apache повинні мати доступ до цієї папки, тому видамо їм максимальні права:

$ chmod 775 /home/apps

Звертайтеся до документації команди chmod для отримання більш детальної інформації. Права 775 дозволяють повний доступ до папки власникові і членам його групи, а всім іншим дають всі права, крім права на запис.

Вхід без пароля
Наступний крок — дозволити вхід під цим обліковим записом з нашого домашнього ПК без використання пароля. SSH підтримує ще один спосіб аутентифікації, публічного ключа. Якщо ви використовуєте ОС відмінну від Windows, то досить імовірно, що у вас вже є встановлені в системі ключі.

Тепер відкрийте термінал на вашому ПК (користувачі Windows — bash-консоль Cygwin-а). Для перевірки наявності ключів, запустіть наступну команду:

$ ls ~/.ssh
id_rsa id_rsa.pub

Якщо в папці є файли id_rsa і id_rsa.pub, як показано вище, ви можете рухатися далі. Якщо цих файлів немає, тоді виконайте наступну команду:

$ keygen-t rsa

У вас буде запитано кілька речей, для яких я рекомендую застосувати значення за замовчуванням натисненням клавіши Enter у відповідь на всі питання. Якщо ви хочете вчинити інакше і при цьому впевнені в тому, що робите — робіть це.

Після виконання цієї команди, у вас з'являться файли, перераховані вище. Файл id_rsa.pub — це ваш публічний ключ, їм ви можете вільно обмінюватися з іншими користувачами, якщо це не піддаючись погрозам безпеки. Файл id_rsa — це ваш приватний ключ, яким ви ні в якому разі не повинні ділитися з ким би то не було.

Тепер ми додамо наш публічний ключ на наш сервер, щоб він міг дізнатися нас за нього. У терміналі нашого ПК виведемо вміст публічного ключа:

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjwak4jvuy6pzar8hoccioszrlizzcjo0xlt9zkfnkvvpp1b92u3jvwwiagqr+k0kHih2SmYnycmXjAcE60tvu+sIDA/7tEJZh4kO4nUYM5PJ17E+qTqUleBXQM74eITydq/USkOqc5p++qUUgA60gUUuNum3igbZiNi71zK4m8g/IDywWYk+5vzNt2i7Sm8NEuauy/xWgnWhCBXZ/tXfkgWgC/4HzpmsfO+nniNh8VgTZp8Q+y+4psSE+p14qUg7KdDbf0Wo/D35wDkMvto96bIT8RF0np9dTkFj8TgNW8inp+6MC+4vCd8F/NpESCVt8hRlBVERMF8Xv4f/0+7WT miguel@miguelspc

Тепер ми повинні скопіювати ці дані в буфер обміну, а потім перемкнутися в CentOS, де виконати наступну команду:

$ mkdir /home/apps/.ssh
$ echo <paste-your-key-here> > /home/apps/.ssh/authorized_keys

Для моєї комбінації сервера і публічного ключа, потрібно виконати наступні команди:

$ mkdir /home/apps/.ssh
$ echo ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjwak4jvuy6pzar8hoccioszrlizzcjo0xlt9zkfnkvvpp1b92u3jvwwiagqr+k0kHih2SmYnycmXjAcE60tvu+sIDA/7tEJZh4kO4nUYM5PJ17E+qTqUleBXQM74eITydq/USkOqc5p++qUUgA60gUUuNum3igbZiNi71zK4m8g/IDywWYk+5vzNt2i7Sm8NEuauy/xWgnWhCBXZ/tXfkgWgC/4HzpmsfO+nniNh8VgTZp8Q+y+4psSE+p14qUg7KdDbf0Wo/D35wDkMvto96bIT8RF0np9dTkFj8TgNW8inp+6MC+4vCd8F/NpESCVt8hRlBVERMF8Xv4f/0+7WT miguel@miguelspc > /home/apps/.ssh/authorized_keys

В результаті виконання цих команд, ваш публічний ключ буде записаний у файл authorized_keys на сервері. Таким чином, ми зробили наш публічний ключ відомим OpenSSH на сервері. Наступним завданням є забезпечення безпеки папки .ssh і файлу authorized_keys всередині неї:

$ chown-R apps:apache /home/apps/.ssh
$ chmod 700 /home/apps/.ssh
$ chmod 600 /home/apps/.ssh/authorized_keys

Ці команди змінять власника цих файлів на аккаунт apps, а потім зроблять папку і файл доступними лише новому власнику.

Вхід без пароля вже повинен працювати. Тепер ми вийдемо з-під облікового запису root нашого сервера, і знову увійдемо на сервер, але вже під обліковим записом користувача apps:

$ ssh apps@<your-server>

Якщо все пройшло гладко, вам не доведеться вводити пароль для доступу.

Установка програми
Тепер ми використовуємо git щоб завантажити та встановити microblog на сервер. Якщо ви не знайомі з git, рекомендую вам ознайомитися з керівництвом git для початківців.

Додаток повинно бути розташоване на git сервері, доступному з нашого сервера. Я буду використовувати свій репозитарій на github. Ви також можете використовувати його, або, якщо ви віддаєте перевагу, ви можете клонувати репозитарій і зробити його своїм власним.

Для установки microblog на наш сервер, нам буде достатньо команди git clone:

$ git clone git://github.com/miguelgrinberg/microblog.git
$ cd microblog

Остання версія програми містить деякі зміни в порівнянні з тим, що ми бачили в кінці попередньої статті.

Перше, є кілька нових файлом на самому верхньому рівні — runp-sqlite.fcgi, runp-mysql.fcgi and killpython. Файли *.fcgi являють собою стартові скрипти, які використовуються веб-серверів, які працюють з FastCGI протоколом. Скрипт killpython буде перезапускати програму після оновлення. Ми розглянемо це пізніше.

Інша визначна зміна міститься у файлі config.py. До поточного моменту, ми ініціалізувати нашу базу даних так:

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')

Тепер будемо це робити так:

if os.environ.get('DATABASE_URL') is None:
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db')
else:
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']

Це просте зміна дозволить нам змінювати базу даних програми, простий установкою змінної оточення. В наступному розділі, ви побачите як можна це використовувати.

Ще одна зміна є у файлі setup.py, який займався налаштуванням віртуального оточення. Тепер цей скрипт встановлює також пакет mysql-python, який необхідний SQLAlchemy для роботи з СУБД MySQL. Крім того, пакет Flask-WhooshAlchemy тепер встановлюється з мого власного форк, т. к. у мене не вийшло зв'язатися з автором оригінального пакету домовитися про включення моїх виправлень в основний дистрибутив.

Налаштування MySQL
База даних sqlite, яку ми використовували весь цей час чудово підходить для простих додатків, але коли ми перебираємося на повноцінний сервер, який може обслуговувати кілька одночасних запитів, краще буде використовувати більш надежнуюю СУБД. Тому ми налаштуємо MySQL для нашого microblog-а.

Ми вже встановили MySQL, так що нам залишилося лише створити базу даних та користувача із правами на цю базу. Для управління сервером бази даних ми використовуємо консоль mysql:

$ mysql-u root-p
Enter password: (enter the mysql root password, or empty if one is not defined)
Welcome to the MySQL monitor. Commands end with ; or \g.
Your Uninstaller connection id is 11
Server version: 5.1.67 Source distribution

Copyright © 2000, 2012, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

І тепер, в командному рядку mysql, ми створимо базу даних apps і з тим же ім'ям:

mysql> create database apps character set utf8 collate utf8_bin;
mysql> create user 'apps'@'localhost' identified by 'apps';
mysql> grant all privileges on apps.* to 'apps'@'localhost';
mysql> flush privileges;
mysql> quit;

Зауважте, що ви повинні вказати пароль користувача apps в секції identified by. Для простоти, я встановив пароль apps, але при реальній налаштування БД необхідно використовувати більш надійні паролі. Не плутайте користувача apps бази даних з користувачем apps системи.

Ініціалізація програми
Тепер, коли база даних готова, ми можемо ініціалізувати наш microblog.

Для початку створимо віртуальне оточення:

$ ./setup.py

Потім створюємо базу даних:

$ DATABASE_URL=mysql://apps:apps@localhost/apps ./db_create.py

Зауважте, як ми встановили змінну оточення DATABASE_URL. Тепер додаток буде використовувати MySQL базу даних замість sqlite.

Далі ми компілюємо всі повідомлення в нашій базі перекладів:

$ ./tr_compile.py

І в кінці, ми даємо право на запис в групі дві папки, які повинні бути доступні веб сервера:

$ chmod-R g+w search.db tmp

Папка search.db використовується нашою базою повнотекстового пошуку Whoosh. Папка ж tmp повинна бути доступна для запису, для чого стане ясно пізніше.

Налаштування Apache
Останнє, що потрібно зробити — налаштувати веб-сервер Apache.

Ми будемо використовувати модуль mod_fcigd для обробки FastCGI діалогу з нашим додатком. Багато дистрибутиви пропонують готові пакети для підтримки mod_fcgid, але, на жаль, CentOS не належить до їх числа, тому ми просто зберемо цей модуль з исходников.

Ось список команд, які зберуть і встановлять поточний випуск mod_fcgid:

$ wget http://mirror.metrocast.net/apache//httpd/mod_fcgid/mod_fcgid-2.3.7.tar.gz
$ tar xvzf mod_fcgid-2.3.7.tar.gz
$ cd mod_fcgid-2.3.7
$ APXS=/usr/sbin/apxs ./configure.apxs
$ su
(enter root password)
$ make install

Ви можете звіритися з документацією mod_fcgid, якщо вас цікавлять деталі представлених вище команд.

Встановивши цей модуль, ми приступаємо безпосередньо до налаштування нашого сервера. Для цього ми повинні відредагувати файл конфігурації Apache. Різні дистрибутиви Linux так і не прийшли до єдиної думки з приводу розташування та іменування цього файлу, т.ч. вам доведеться розібратися з цим питанням самостійно. Наприклад, в CentOS, конфігураційний файл розташований за адресою /etc/httpd/conf/httpd.conf.

Сюди ми просто додамо визначення нашого сервера. В кінці файлу додайте наступні рядки (робіть це від імені адміністратора root, т. до. цей файл доступний на запис для простих користувачів):

FcgidIPCDir /tmp
AddHandler fcgid-script .fcgi
<VirtualHost *:80>
DocumentRoot /home/apps/microblog/app/static
Alias /static /home/apps/microblog/app/static
ScriptAlias / /home/apps/microblog/runp-mysql.fcgi/
</VirtualHost>

Параметр FcgidIPCDir вказує на папку, де будуть створюватися файли сокетів. Я виявив, що за замовчуванням вони створюються в папці, в якій користувач apache не має права на запис, тому я вирішив розміщувати ці файли в /tmp.

Потім ми вказуємо AddHandler, щоб повідомити apache що всі файли з розширенням .fcgi повинні сприйматися як файли FastCGI і виконуватися через модуль mod_fcgid, який ми тільки що встановили. Пам'ятайте новий файл runp-mysql.fcgi який розташований в нашій кореневої директорії? Цей файл використовують python модуль flup, як адаптера щоб наше додаток змогло взаємодіяти з FastCGI протоколом. Давайте поглянемо на цей файл:

#!flask/bin/python
import os
os.environ['DATABASE_URL'] = 'mysql://apps:apps@localhost/apps'

from flup.server.fcgi import WSGIServer
from app app import

if __name__ == '__main__':
WSGIServer(app).run()

Apache буде виконувати цей файл для запуску додатку. Зауважте, як ми помістили назва бази MySQL в оточення, щоб Apache міг пізнати його.

Секція визначає хост який буде обслуговувати веб сервер. Позначення *:80 означає, що всі запити надійшли сервера на будь-який хост на 80-й порт, будуть обслуговуватися цим віртуальним сервером. В конфігураційному файлі можуть бути визначені кілька секцій, кожна з яких визначає інший сервер. Для того, щоб відрізняти сервера один від одного, ви можете використовувати різні IP адреси, домен або субдомен або порти.

Визначення нашого віртуального хоста досить просте. Оператор DocumentRoot повідомляє Apache де шукати статичні файли. Всі запити файлів, будуть обслуговуватися з цієї папки, так наприклад, коли браузер запитає файл /favicon.ico, для відображення маленької іконки поряд з полем вводу адреси в браузері, Apache буде шукати його саме тут. Однак, всі статичні файли, використовувані в нашому додатку, будуть мати префікс /static, тому щоб Apache не шукав іншу папку static, ми застосовуємо оператор Alias, який означає, що всі запити, які починаються з /static повинні потрапляти в нашу папку зі статикою. І нарешті, оператор ScriptAlias повідомляє Apache, що отримавши запит починається з / (взагалі-то, це все запити крім запитів статики) необхідно викликати скрипт зазначений другим аргументом, а це і є наш .fcgi скрипт.

Конфігураційний файл Apache підтримує набагато більше опцій, ніж були згадані мною. Рекомендую вам ознайомитися з документацією Apache, щоб вирішити, які ще опції має сенс задіяти для вашого сервера.

Для активації зроблених змін, ми повинні перезапустити сервер з-під облікового запису root:

# service httpd restart

Тепер, перейшовши за адресою <your-server> у вашому браузері, ви повинні переглянути сторінки нашого мікроблогу.

Установка оновлень додатка
Останній момент, який ми розглянемо, це викочування оновлення нашого застосування.

Припустимо, ми розгорнули додаток і воно успішно пропрацював якийсь час на нашому сервері. І ось настав час викотити оновлення, яке повинно виправити деякі помилки або просто додати нові можливості.

Ми використовуємо git і наш власний інструментарій для цього. Якщо ми авторизовані на сервері під обліковим записом apps, ми можемо оновитися до останнього релізу в репозитарії за допомогою команд:

$ cd microblog
$ git pull
$ DATABASE_URL=mysql://apps:apps@localhost/apps ./db_upgrade.py
$ ./tr_compile.py

Команда git pull скачає все нові і оновлені файли з нашого сервера git. Потім, ми оновимо нашу базу даних і перекомпилируем файли перекладу, якщо вони змінилися. І це все!

Тепер коли всі оновлення отримано, необхідно перезапустити FastCGI процеси, і це трохи важко, оскільки ми ввійшли під користувачем apps, непривелигированным користувачем, у той час як процеси FastCGI належать користувачу apache.

І в цьому випадку нам знадобиться sudo. Команда sudo дозволяє користувачам запускати програми від імені іншого користувача. Ми не хотіли б давати нашому користувачеві apps занадто багато прав, тому дамо йому тільки право відправляти сигнали зупинки FastCGI процесів, запущеним користувачем apache.

Скрипт killpython з нашої папки microblog, робить саме це:

killall /home/apps/microblog/flask/bin/python

Заковика в тому, що якщо ми запустимо цей скрипт від імені користувача apps, у нас не буде необхідних привілеїв для зупинки процесів, належать користувачу apache. Щоб дозволити користувачеві apps переривати ці процеси, ми повинні внести невеликі зміни в файл /etc/sudoers:

apps ALL=(apache) NOPASSWD:/home/apps/microblog/killpython
Defaults: apps !requiretty

Зауважте, що ці зміни ви повинні вносити від імені користувача root, т. к. /etc/sudoers це системний файл.

Перша трудночитаемая команда дає користувачеві apps право запускати killpython від імені користувача apache без необхідності вводити пароль. Друга рядок дозволяє користувачеві apps використовувати команду sudo викликаючи її з скрипта, а не тільки з консолі. Ви можете ознайомитися з керівництвом по файла sudoers для отримання детальної інформації про синтаксис кофигурационного файлу sudo.

Тепер, увійшовши під обліковим записом користувача apps, ми можемо переривати процеси python виконавши команду:

$ sudo-u apache ./killpython

Якщо процеси FastCGI будуть перервані, Apache перезавантажить їх, отримавши такий запит до microblog-у.

Щоб ще трохи спростити оновлення нашого сервера, ми могли б створити спеціальний скрипт, який би об'єднав процеси оновлення і перезапуску. Сам скрипт виглядав би приблизно так:

ssh apps@<your-server> "cd microblog;git pull;sudo-u apache ./killpython;DATABASE_URL=mysql://apps:apps@localhost/apps ./db_upgrade.py;./tr_compile.py"

Якщо ви збережете цю команду в скрипт, то ви зможете викочувати оновлення на сервер однією командою!

Що ще можна додати
Я не розглянув кілька звичайних операцій, які рекомендуються до застосування для забезпечення ще більшої безпеки сервера в умовах «ворожого середовища Інтернету». Це такі операції як:
  • Заборона віддаленого входу користувача root
  • Відключення всіх невикористовуваних сервісів, на зразок FTP, CIFS, і т.д.
  • Налаштування брандмауера.
  • Своєчасна установка оновлень безпеки для сервера.
  • Деякі інші.
Я залишу ці теми в якості вправи для зацікавленого читача, оскільки вони мають опосередковане відношення до теми цієї статті.

Хостинг на Raspberry Pi

Raspberry Pi це революційний мініатюрний комп'ютер, який працює під управлінням Linux, вартістю близько $35. Він володіє дуже низьким енергоспоживанням, що робить його чудовим пристроєм для хостингу домашніх веб додатків, доступних онлайн в режимі 24/7 без необхідності постійно тримати включеним великий ПК.

Існує кілька дистрибутивів, призначених для Raspberry Pi. Ми встановимо наш додаток на Raspbian, офіційний дистрибутив.

До речі, зауважте, що Raspbian є відгалуженням дистрибутиву Debian, а це значить що наведені нижче інструкції будуть застосовні (можливо, з мінімальними доповненнями) і для серверів на базі Debian/Ubuntu.

Тепер ми повторимо ті ж кроки, які ми пройшли для CentOS, щоб налаштувати RPi сервер.

Налаштування клієнтської сторони
Raspberry Pi являє собою повноцінний комп'ютер. Ви можете підключити HDMI монітор, клавіатуру, мишу і працювати прямо на ньому для налаштування серверного ПО. На зразок того, як ми робили на CentOS (та й взагалі на будь-якому дистрибутиві Linux), ви можете просто підключити Raspberry Pi до мережі, а потім підключитися до неї за допомогою ssh. Дивіться розділ «Налаштування клієнтської сторони» вище, щоб налаштувати ssh на своєму ПК.

Зауважте, що я не торкнувся установку і настройку самої Raspberry Pi, т. к. про це написана безліч статей. Я припускаю, що Raspberry Pi вже запущена і підключена до мережі.

Встановлення пакунків з програмним забезпеченням
Тому Pi все ж являє собою машину з обмеженою потужністю, ми не буде встановлювати повноцінний Apache/MySQL стек, як ми зробили це на CentOS. Замість цього, ми застосуємо легкий підхід. В якості веб-сервера ми використовуємо Lighttpd, невеликий веб сервер з дуже хорошою і ефективним реалізацією FastCGI. В якості СУБД ми залишимо sqlite.

Для CentOS ми використовували yum для установки пакетів. В дистрибутивах ж сімейства Debian, використовується менеджер пакунків apt-get:

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install python python-dev lighttpd git

Команда update завантажує і оновлює список пакетів на ваш Pi. Команда upgrade оновлює всі встановлені пакети до їх останніх версій. Рекомендується запускати ці команди періодично, щоб зберігати актуальність використовується. І, нарешті, команда install встановлює необхідні нам пакети.

Створення окремого користувача для нашого додатка
Ми вирішили, що наш Raspberry Pi сервер буде розташований у довіреної мережі. Тому безпека не є нашим головним пріоритетом в цих умовах, і ми не будемо створювати окремого користувача, а замість цього використовуємо запис за замовчуванням — pi.

Якщо ви плануєте тримати Raspberry Pi підключеного до Інтернет, то ви повинні застосувати підхід, використаний нами для CentOS і створити окремий обмежений аккаунт, щоб у разі злому облікового запису, нанесений збиток був обмежений.

Вхід без пароля
Заклад публічних ключів також не дуже важлива процедура якщо додаток буде працювати в локальній мережі, але якщо вам знадобиться ця функціональність — процедура буде повністю аналогічна тій, що ми використовували на CentOS.

Установка програми
Додаток встановлюється за допомогою git:

$ git clone git://github.com/miguelgrinberg/microblog.git
$ cd microblog

Ініціалізація програми
Тому ми плануємо використовувати sqlite на цьому хості, ми можемо ініціалізувати microblog так, як ми це робили в попередніх статтях для нашого сервера розробки:

$ ./setup.py
$ ./db_create.py
$ ./tr_compile.py

Зауважте, що setup.py спробує встановити підтримку для MySQL і ця спроба буде провалена, але це і не страшно, тому що ми не використовуємо MySQL.

Всі файли належать користувачу pi. Але як ми побачили у випадку з CentOS, веб сервер буде запущений від імені іншого користувача. Тому забезпечення безпеки не є необхідністю на цьому сервері, ми зробимо простіше:

$ chmod-R 777 *

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

Я хотів би пояснити, що Raspberry Pi is прекрасно сумісна з конфігурацією, що грунтується на групах і права доступу, подібно тій що ми використовували для сервера під керуванням CentOS. Ми обрали спрощену схему установки, т. до. ми будемо використовувати цей сервер у повністю контрольованому оточенні.
Налаштування Lighttpd
Lighttpd має вбудовану підтримку FastCGI, а значить нам не доведеться займатися встановленням окремого модуля для цих цілей.
Все що нам потрібно зробити — додати наш сайт в конфігураційний файл, розташований за адресою /etc/lighttpd/lighttpd.conf:

fastcgi.server = ("/microblog" =>
((
"socket" => "/tmp/microblog-fcgi.sock",
"bin-path" => "/home/pi/microblog/runp-sqlite.fcgi",
"check-local" => "disable",
"max-procs" => 1
))
)

alias.url = (
"/microblog/static/" => "/home/pi/microblog/app/static/",
)

І після цього наше додаток вже повинна бути доступна он-лайн за адресою http:// <IP адреса Raspberry Pi>.

Проте, потрібно відзначити кілька моментів у представленій конфігурації, а також кілька речей які спочатку не працюють і вимагають внесення деяких змін на стороні програми.

Вираз fastcgi.server визначає поведінку нашого FastCGI сервера, доступного за адресою /microblog. Причина, по якій ми не розмістили додаток за адресою / проста, можливо пізніше ми запустимо більше одного додатка, і в такому разі розміщення всіх адрес нашого застосування в /microblog буде грати роль простору імен.

Усередині визначення FastCGI ми задаємо розташування сокет файлу у папку /tmp і шлях до нашого файлу runp-sqlite.fcgi, який Lighttpd буде запускати для старту FastCGI процесів. Опція check-local повідомляє Lighttpd про необхідність відправляти запити FastCGI сервера, навіть якщо запитаний шлях відповідає файл на диску. max-procs обмежує кількість процесів FastCGI до 1, що для невеликого сервера цілком достатньо, а також допоможе уникнути потенційних проблем при декількох одночасних запитів на запис в базу sqlite.

Секція alias.url відображає запити до статиці на локальний шлях до відповідного файлу…

Скрипт runp-sqlite.fcgi дуже схожий на той, що ми використовували на CentOS, тільки без перезапису налаштувань бази даних:

from flup.server.fcgi import WSGIServer
from app app import

if __name__ == '__main__':
WSGIServer(app).run()

Деякі необхідні виправлення
Тестування цієї установки позначить кілька проблем в роботі нашого пріложнія.

По-перше, наші файли javascript і css не завантажуються. Проблему легко вирішити, заглянувши у вихідний код сторінки на сторінці входу. В шаблоні base.html ці файли задані абсолютними шляхами, які починаються з /static, проте ж ми додали префікс /microblog до наших адресами. Наприклад, ось як вказано посилання на файл CSS:

В той час, коли насправді ми б хотіли бачити тут /microblog/static/bootstrap.min.css, і, звичайно ж, ми не можемо просто додати /microblog в шаблон base.html тому що це призведе до непрацездатності нашої програми на сервері розробки, запущеному на нашому ПК. Рішенням є генерація цих адрес автоматично за допомогою url_for:

<link href="{{ url_for('.static', filename = 'css/bootstrap.min.css') }}" rel="stylesheet" media="screen">

Після оновлення, все js і css файли будуть завантажуватися коректно.

Але спроба залогінитись, виявить нову проблему. Відразу після авторизації, ми отримуємо помилку 500. На щастя для нас, у нас включено логгирование, тому швидке вивчення /home/pi/microblog/tmp/microblog.log приводить нас до наступного помилку:

ProgrammingError: (ProgrammingError) SQLite objects created in a thread can only be used in that same thread.The object was created in thread id -1260325776 and this is thread id -1243548560

Це ще що? Ми не запускаємо кілька потоків, але очевидно, що наш додаток все ж використовує кілька потоків. Єдина відмінність між сервером для розробки і цим полягає в тому, що тут ми використовуємо flup для FastCGI сервера. Заглянувши у вихідний код цього модуля, ми дізнаємося, що за замовчуванням flup запускає багатопоточний сервер.

Можливим рішенням може бути використання одного потоку сервера FastCGI, що надається flup. Однак, це може зашкодити продуктивності у випадку декількох конкуруючих підключень. Іншим, більш перспективним шляхом вирішення цієї проблеми може стати дозвіл багатопоточності в sqlite (яка, здається, повністю підтримується). Багатопоточність можна вирішити в SQLAlchemy, встановивши check_same_thread параметр в False в нашому конфигурационом файлі config.py:

SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db') + '?check_same_thread=False'

Цим зміною ми дозволили запускати багато потоків для внесення змін в базу даних, синхронізацію ж множинного доступу бере на себе бібліотеку sqlite.

І, нарешті, ми запустии наш додаток на Raspberry Pi!

Установка оновлень додатка
Для установки оновлень ми можемо просто увійти на Raspberry Pi і викликати команди, що виконують оновлення вихідного коду, бази даних і файлів перекладу:

$ cd microblog
$ git pull
$ ./db_upgrade.py
$ ./tr_compile.py

Якщо ви налаштували безпарольный вхід на вашу Pi, то ви без проблем можете написати скрипт, який виконує це все в одну команду.

Висновок

Оновлене додаток доступно, як завжди, на github. Або ж ви можете завантажити його у вигляді zip-архіву за посиланням:
Завантажити microblog 0.17.

У наступній статті ми розглянемо розгортання на хмарному сервісі, як альтернативу традиційному підходу, розглянутому нами сьогодні.

Побачимося!

Miguel

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.