Debian stretch, моделируем развёртывание Flask-приложения

avm

Опубликован:  2018-02-10T11:45:50.674901Z
Отредактирован:  2018-02-10T11:44:04.509402Z
1500
Рассмотрено ручное развёртывание web-приложения на базе Flask на сервер под управлением Debian stretch с использованием Nginx и Gunicorn, успешно осуществлён весь процесс в пошаговом режиме на стенде на основе VirtualBox. Описание содержит листинги консоли и выдержки кода.

1. Исходные данные

Для осуществления развёртывания мне потребуется исходное web-приложение. Я буду использовать одно из своих тестовых приложений - минимальный хостинг картинок. Исходный код приложения доступен на github.com. Приложение разрабатывалось в учебных целях и выполнено на Python3 и Flask. Для хранения данных используется PostgreSQL.

Кроме этого мне понадобится стенд, на котором буду производить все действия. В качестве стенда я буду использовать виртуальную машину предоставленную VirtualBox. Установка VirtualBox детально описана в Debian stretch, установка VirtualBox. На используемой виртуальной машине установлен базовый сервер Debian stretch, описание установки сервера можно найти в Debian stretch, установка базового сервера на виртуальную машину. Рекомендуется предварительно ознакомиться с документами по предложенным ссылкам.

На базовом сервере зарегистрирован пользователь с именем sadmin, сервер подключен к виртуальной сети на IP-адресе 192.168.56.101 и доступен для подключения по SSH с паролем пользователя. Операционная система сервера полностью обновлена и имеет минимальный набор предустановленного программного обеспечения.

Управление сервером будет осуществляться из консоли хост-машины, на хост-машине у меня тоже Debian stretch. Для справки, консоль хост-машины имеет вид:

sadmin@debian:~$ 

консоль сервера имеет вид:

sadmin@tester:~$ 

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

2. Настройка хост-машины

Поскольку для своего виртуального web-сервера я буду использовать домен tester.ru, мне необходимо, чтобы моя хост-машина, которая будет соединяться с этим доменом в web-браузере, обращалась к домену по IP-адресу виртуального сервера, а именно 192.168.56.101. Для этого в консоли хост-машины открываю в текстовом редакторе файл:

sadmin@debian:~$ sudo nano /etc/hosts

и привожу его к следующему виду:

etc-hosts

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

sadmin@debian:~$ ping -c 5 tester.ru
PING tester.ru (192.168.56.101) 56(84) bytes of data.
64 bytes from tester.ru (192.168.56.101): icmp_seq=1 ttl=64 time=0.383 ms
64 bytes from tester.ru (192.168.56.101): icmp_seq=2 ttl=64 time=0.336 ms
64 bytes from tester.ru (192.168.56.101): icmp_seq=3 ttl=64 time=0.365 ms
64 bytes from tester.ru (192.168.56.101): icmp_seq=4 ttl=64 time=0.339 ms
64 bytes from tester.ru (192.168.56.101): icmp_seq=5 ttl=64 time=0.380 ms

--- tester.ru ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4093ms
rtt min/avg/max/mdev = 0.336/0.360/0.383/0.028 ms

В первой строчке PING показывает, что искомый домен соответствует заданному IP-адресу виртуального сервера. Этого достаточно.

3. Настройка пользователя на сервере

В консоли хост-машины подключаюсь к серверу:

sadmin@debian:~$ ssh sadmin@192.168.56.101

ssh

Следует обратить внимание, что приглашение командной строки изменилось, и теперь эта консоль удалённо управляет виртуальным сервером.

Чтобы развернуть своё приложение, мне необходимо дать зарегистрированному пользователю возможность совершать административные действия. Для этого вхожу root-ом:

sadmin@tester:~$ su -
Пароль: 
root@tester:~# 

Приглашение командной строки опять изменило свой вид, теперь я управляю виртуальным сервером от имени суперпользователя. Устанавливаю sudo и git:

root@tester:~# apt-get install sudo git
Чтение списков пакетов… Готово
Построение дерева зависимостей       
Чтение информации о состоянии… Готово
Будут установлены следующие дополнительные пакеты:
  git-man liberror-perl patch rsync
Предлагаемые пакеты:
  git-daemon-run | git-daemon-sysvinit git-doc git-el git-email git-gui gitk
  gitweb git-arch git-cvs git-mediawiki git-svn ed diffutils-doc
НОВЫЕ пакеты, которые будут установлены:
  git git-man liberror-perl patch rsync sudo
обновлено 0, установлено 6 новых пакетов, для удаления отмечено 0 пакетов, и 0 пакетов не обновлено.
Необходимо скачать 7 178 kБ архивов.
После данной операции, объём занятого дискового пространства возрастёт на 35,1 MB.
Хотите продолжить? [Д/н] 

Соглашаюсь и дожидаюсь установки пакетов, а затем добавляю пользователя sadmin в группы sudo и adm:

root@tester:~# usermod -a -G sudo,adm sadmin
root@tester:~# 

Здесь нужно отметить, что участие в группе sudo позволит пользователю sadmin выполнять действия администратора с собственным паролем, а adm позволит просматривать логи Nginx.

Перезагружаю сервер:

root@tester:~# shutdown -r now
Connection to 192.168.56.101 closed by remote host.
Connection to 192.168.56.101 closed.
sadmin@debian:~$ 

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

sadmin@debian:~$ ssh sadmin@192.168.56.101

Проверяю пользователя:

sadmin@tester:~$ sudo pwd

Мы полагаем, что ваш системный администратор изложил вам основы
безопасности. Как правило, всё сводится к трём следующим правилам:

    №1) Уважайте частную жизнь других.
    №2) Думайте, прежде что-то вводить.
    №3) С большой властью приходит большая ответственность.

[sudo] пароль для sadmin: 
/home/sadmin
sadmin@tester:~$ 

Отлично, можно двигаться дальше.

4. Настройка ssh

Поскольку данный виртуальный сервер доступен только в виртуальной сети моей хост-машины, тонкая настройка ssh-сервера практически не имеет смысла, поэтому детально описывать её сейчас я не буду. Просто напомню, что для настройки сервера выполняются следующие действия:

  • создаётся пара ключей на клиенте, который будет подключаться к серверу;
  • публичный ключ клиента копируется на сервер;
  • на сервере редактируется файл /etc/ssh/sshd_config, после чего ssh-сервер перезапускается.

Пару ключей на клиенте можно создать с помощью ssh-keygen, например:

ssh-keygen -t ed25519

Скопировать публичный ключ с клиента на сервер можно при помощи ssh-copy-id, например:

ssh-copy-id -i ~/.ssh/id_ed25519.pub sadmin@192.168.56.101

при этом публичный ключ должен существовать.

После редактирования конфигурации ssh-сервера, его можно перезапустить командой:

sudo systemctl restart sshd.service

команда подаётся в консоли сервера.

5. Установка на сервере дополнительного программного обеспечения

Для правильной установки и функционирования исходного web-приложения на сервере необходимо установить следующие дополнительные пакеты:

sadmin@tester:~$ sudo apt-get install python3-venv python3-dev libpq-dev gcc postgresql postgresql-client postgresql-client-common
Чтение списков пакетов… Готово
Построение дерева зависимостей       
Чтение информации о состоянии… Готово
Будут установлены следующие дополнительные пакеты:
  binutils cpp cpp-6 gcc-6 libasan3 libatomic1 libc-dev-bin libc6-dev libcc1-0
  libcilkrts5 libexpat1-dev libgcc-6-dev libgomp1 libisl15 libitm1 liblsan0
  libmpc3 libmpfr4 libmpx2 libpq5 libpython3-dev libpython3.5 libpython3.5-dev
  libquadmath0 libsensors4 libtsan0 libubsan0 libxslt1.1 linux-libc-dev
  manpages-dev postgresql-9.6 postgresql-client-9.6 postgresql-common
  postgresql-contrib-9.6 python-pip-whl python3.5-dev python3.5-venv ssl-cert
  sysstat
Предлагаемые пакеты:
  binutils-doc cpp-doc gcc-6-locales gcc-multilib make autoconf automake
  libtool flex bison gdb gcc-doc gcc-6-multilib gcc-6-doc libgcc1-dbg
  libgomp1-dbg libitm1-dbg libatomic1-dbg libasan3-dbg liblsan0-dbg
  libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libmpx2-dbg libquadmath0-dbg
  glibc-doc postgresql-doc-9.6 lm-sensors postgresql-doc locales-all
  libdbd-pg-perl openssl-blacklist isag
НОВЫЕ пакеты, которые будут установлены:
  binutils cpp cpp-6 gcc gcc-6 libasan3 libatomic1 libc-dev-bin libc6-dev
  libcc1-0 libcilkrts5 libexpat1-dev libgcc-6-dev libgomp1 libisl15 libitm1
  liblsan0 libmpc3 libmpfr4 libmpx2 libpq-dev libpq5 libpython3-dev
  libpython3.5 libpython3.5-dev libquadmath0 libsensors4 libtsan0 libubsan0
  libxslt1.1 linux-libc-dev manpages-dev postgresql postgresql-9.6
  postgresql-client postgresql-client-9.6 postgresql-client-common
  postgresql-common postgresql-contrib-9.6 python-pip-whl python3-dev
  python3-venv python3.5-dev python3.5-venv ssl-cert sysstat
обновлено 0, установлено 46 новых пакетов, для удаления отмечено 0 пакетов, и 0 пакетов не обновлено.
Необходимо скачать 76,3 MБ архивов.
После данной операции, объём занятого дискового пространства возрастёт на 212 MB.
Хотите продолжить? [Д/н] 

Соглашаюсь и дожидаюсь установки всех пакетов.

6. Настройка PostgreSQL

Вхожу пользователем postgres:

sadmin@tester:~$ sudo -i -u postgres
postgres@tester:~$ 

Создаю нового пользователя базы данных:

postgres@tester:~$ createuser sadmin -P -d --interactive
Введите пароль для новой роли: 
Повторите его: 
Должна ли новая роль иметь полномочия суперпользователя? (y - да/n - нет) n
Новая роль должна иметь право создавать другие роли? (y - да/n - нет) n
postgres@tester:~$

и выхожу:

postgres@tester:~$ exit
выход
sadmin@tester:~$ 

Поскольку сервер стендовый и не рассчитан на реальную работу, тонкая настройка PostgreSQL не имеет особого смысла. Оставляю этот сервис в дефолтном состоянии, создаю базу данных и вхожу вновь-созданным пользователем:

sadmin@tester:~$ createdb images_dev
sadmin@tester:~$ psql -U sadmin -d images_dev
psql (9.6.4)
Введите "help", чтобы получить справку.

images_dev=> 

Для приложения мне понадобится ещё две базы данных, создаю их и покидаю сессию psql:

images_dev=> CREATE DATABASE images_test;
CREATE DATABASE
images_dev=> CREATE DATABASE images;
CREATE DATABASE
images_dev=> \q
sadmin@tester:~$ 

Важное замечание: на текущий момент я имею пользователя базы данных, его пароль, принадлежащие ему три пустые базы данных: images_dev, images_test и images, которые буду использовать далее при развёртывании приложения и создании конфигурационного файла в п.9 этого описания.

7. Создание рабочего пространства приложения и настройка виртуального окружения

Создаю рабочий каталог в котором будет жить исходный код приложения и необходимые для его правильного функционирования файлы и каталоги:

sadmin@tester:~$ mkdir -p workspace/tester.ru
sadmin@tester:~$ 

Вхожу в этот каталог:

sadmin@tester:~$ cd workspace/tester.ru/
sadmin@tester:~/workspace/tester.ru$ 

Создаю виртуальное окружение:

sadmin@tester:~/workspace/tester.ru$ python3 -m venv venv
sadmin@tester:~/workspace/tester.ru$ 

и активирую его:

sadmin@tester:~/workspace/tester.ru$ source venv/bin/activate
(venv) sadmin@tester:~/workspace/tester.ru$ 

Следует обратить внимание на внешний вид приглашения командной строки, в нём появился префикс venv - это имя активного виртуального окружения. Чтобы подготовить его к использованию, осталось обновить wheel:

(venv) sadmin@tester:~/workspace/tester.ru$ pip install --upgrade wheel
Collecting wheel
  Downloading wheel-0.30.0-py2.py3-none-any.whl (49kB)
    100% |████████████████████████████████| 51kB 297kB/s 
Installing collected packages: wheel
Successfully installed wheel-0.30.0
(venv) sadmin@tester:~/workspace/tester.ru$ 

На данный момент всё готово к установке зависимостей развёртываемого web-приложения.

8. Получение кода приложения с github.com и установка зависимостей

Копирую исходный код своего web-приложения при помощи git:

(venv) sadmin@tester:~/workspace/tester.ru$ git clone https://github.com/tgi-f/imagestore.git
Клонирование в «imagestore»…
remote: Counting objects: 994, done.
remote: Total 994 (delta 0), reused 0 (delta 0), pack-reused 994
Получение объектов: 100% (994/994), 248.11 KiB | 298.00 KiB/s, готово.
Определение изменений: 100% (604/604), готово.
(venv) sadmin@tester:~/workspace/tester.ru$ 

Вхожу в репозиторий:

(venv) sadmin@tester:~/workspace/tester.ru$ cd imagestore/
(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ 

Устанавливаю зависимости приложения в виртуальное окружение:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ pip install -r requirements.txt

При этом консоль покажет длинный выхлоп и успешная установка всех необходимых пакетов завершится сообщением:

Successfully installed Flask-0.11.1 Flask-Login-0.4.0 Flask-Migrate-2.0.2 Flask-Moment-0.5.1 Flask-SQLAlchemy-2.1 Flask-Script-2.0.5 Flask-WTF-0.13.1 Jinja2-2.8 Mako-1.0.6 MarkupSafe-0.23 Pillow-3.4.2 SQLAlchemy-1.1.4 WTForms-2.1 Werkzeug-0.11.11 alembic-0.8.9 click-6.6 itsdangerous-0.24 psycopg2-2.6.2 python-editor-1.0.3

Для развёртывания мне потребуется установить в виртуальное окружение ещё пару дополнительных пакетов:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ pip install gunicorn gevent
Collecting gunicorn
  Downloading gunicorn-19.7.1-py2.py3-none-any.whl (111kB)
    100% |████████████████████████████████| 112kB 286kB/s 
Collecting gevent
  Downloading gevent-1.2.2-cp35-cp35m-manylinux1_x86_64.whl (1.7MB)
    100% |████████████████████████████████| 1.7MB 286kB/s 
Collecting greenlet>=0.4.10 (from gevent)
  Downloading greenlet-0.4.12-cp35-cp35m-manylinux1_x86_64.whl (42kB)
    100% |████████████████████████████████| 51kB 65kB/s 
Installing collected packages: gunicorn, greenlet, gevent
Successfully installed gevent-1.2.2 greenlet-0.4.12 gunicorn-19.7.1
(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ 

С почином нас!

9. Создание файла конфигурации приложения

В состоянии "из коробки" успешно скопированный git-репозиторий не содержит файла конфигурации приложения, его нужно создать, для этого в репозитории есть шаблон, который нужно скопировать:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ cp config.tmpl.py config.py
(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ 

Теперь файл config.py можно открыть в текстовом редакторе (в консоли лучшим вариантом будет nano) и привести к следующему виду:

from datetime import timedelta


class Config:
    SECRET_KEY = 'BF)J+%OWmz@a1&^1(!MOjRFzeKm3AdAKIo8w!UX!Mo3MnHJu$0'
    PERMANENT_SESSION_LIFETIME = timedelta(hours=2)
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    MAX_CONTENT_LENGTH = 5 * 1024 * 1024 + 1
    USERS_PER_PAGE = 30
    ALBUMS_PER_PAGE = 10
    PICTURES_PER_PAGE = 50

    @staticmethod
    def init_app(app):
        pass


class Development(Config):
    DEBUG = True
    SESSION_PROTECTION = None
    SQLALCHEMY_DATABASE_URI = \
        'postgresql+psycopg2://sadmin:aa@localhost/images_dev'
    USERS_PER_PAGE = 3
    ALBUMS_PER_PAGE = 3
    PICTURES_PER_PAGE = 3


class Testing(Config):
    TESTING = True
    WTF_CSRF_ENABLED = False
    SERVER_NAME = 'localhost'
    SQLALCHEMY_DATABASE_URI = \
        'postgresql+psycopg2://sadmin:aa@localhost/images_test'
    USERS_PER_PAGE = 3
    ALBUMS_PER_PAGE = 3
    PICTURES_PER_PAGE = 3


class Production(Config):
    SESSION_PROTECTION = 'basic'
    SQLALCHEMY_DATABASE_URI = \
        'postgresql+psycopg2://sadmin:aa@localhost/images' 


config = {
    'development': Development,
    'testing': Testing,
    'production': Production,
    'default': Production}

Замечание: вариант генерации секретного ключа описан в Python3, генерируем ключи для конфигурации Flask-приложения.

Важное замечание: свойство SQLALCHEMY_DATABASE_URI имеет вид:
postgresql+psycopg2://sadmin:aa@localhost/images - здесь sadmin - пользователь базы данных, aa - пароль пользователя базы данных, images - имя базы данных используемое для этого типа конфигурации приложения; подробности их возникновения в п.6 этого описания.

10. Настройка базы данных и установка суперпользователя

Создаю таблицы базы данных images, которая будет работать в приложении в режиме default в соответствии с созданным файлом config.py, для этого просто делаю апгрейд:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ python manage.py db upgrade
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 7acd1a042fe4, Create auth models
INFO  [alembic.runtime.migration] Running upgrade 7acd1a042fe4 -> ebb88f51889d, Create Album
INFO  [alembic.runtime.migration] Running upgrade ebb88f51889d -> 675f3bf42ec2, Add a new column to Album
INFO  [alembic.runtime.migration] Running upgrade 675f3bf42ec2 -> 75fbb4afcbb5, Modify Album, add suffix
INFO  [alembic.runtime.migration] Running upgrade 75fbb4afcbb5 -> 289ba96f4838, Modify Album, suffix cannot be null
INFO  [alembic.runtime.migration] Running upgrade 289ba96f4838 -> 8d4e94bc6fef, Create Picture
INFO  [alembic.runtime.migration] Running upgrade 8d4e94bc6fef -> cfeabae527a8, Modify Picture
INFO  [alembic.runtime.migration] Running upgrade cfeabae527a8 -> 7efcb8d0d743, Modify Picture, add uploaded datetime
INFO  [alembic.runtime.migration] Running upgrade 7efcb8d0d743 -> b86f8f597365, Modify Album
INFO  [alembic.runtime.migration] Running upgrade b86f8f597365 -> 0f16ee0d85a1, Modify Picture and Album
INFO  [alembic.runtime.migration] Running upgrade 0f16ee0d85a1 -> f6b6418eacd0, Modify Album
INFO  [alembic.runtime.migration] Running upgrade f6b6418eacd0 -> eacf94de92ec, Change Picture: remove suffix
INFO  [alembic.runtime.migration] Running upgrade eacf94de92ec -> 7cf294426055, Change Picture: restore suffix
INFO  [alembic.runtime.migration] Running upgrade 7cf294426055 -> a8b633161021, Modify Album, remove volume
INFO  [alembic.runtime.migration] Running upgrade a8b633161021 -> 3fe56b368470, Modify Album, add volume
(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ 

Затем подгружаю служебный shell приложения и устанавливаю группы и разрешения пользователей:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ python manage.py shell
>>> Group.insert_groups(permissions, groups, Permission)
>>> exit()

Создаю суперпользователя приложения:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ python manage.py create_superuser
Enter a username: support
Enter a password: 
Confirm the password: 

С этим именем пользователя и паролем я первый раз войду в сервис, когда приложение будет доступно в браузере.

11. Настройка временного каталога приложения

Создаю новый файл в каталоге /etc/tmpfiles.d:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ sudo nano /etc/tmpfiles.d/workspace.conf

И привожу его к следующему виду:

tmpfiles

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

12. Установка и настройка web-сервера Nginx

Деактивирую виртуальное окружение:

(venv) sadmin@tester:~/workspace/tester.ru/imagestore$ deactivate
sadmin@tester:~/workspace/tester.ru/imagestore$ 

Перехожу в домашний каталог пользователя sadmin:

sadmin@tester:~/workspace/tester.ru/imagestore$ cd ~
sadmin@tester:~$ 

Устанавливаю Nginx:

sadmin@tester:~$ sudo apt-get install nginx
Чтение списков пакетов… Готово
Построение дерева зависимостей       
Чтение информации о состоянии… Готово
Будут установлены следующие дополнительные пакеты:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0
  libjpeg62-turbo libnginx-mod-http-auth-pam libnginx-mod-http-dav-ext
  libnginx-mod-http-echo libnginx-mod-http-geoip
  libnginx-mod-http-image-filter libnginx-mod-http-subs-filter
  libnginx-mod-http-upstream-fair libnginx-mod-http-xslt-filter
  libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6 libxpm4 nginx-common
  nginx-full
Предлагаемые пакеты:
  libgd-tools fcgiwrap nginx-doc
НОВЫЕ пакеты, которые будут установлены:
  fontconfig-config fonts-dejavu-core libfontconfig1 libgd3 libjbig0
  libjpeg62-turbo libnginx-mod-http-auth-pam libnginx-mod-http-dav-ext
  libnginx-mod-http-echo libnginx-mod-http-geoip
  libnginx-mod-http-image-filter libnginx-mod-http-subs-filter
  libnginx-mod-http-upstream-fair libnginx-mod-http-xslt-filter
  libnginx-mod-mail libnginx-mod-stream libtiff5 libwebp6 libxpm4 nginx
  nginx-common nginx-full
обновлено 0, установлено 22 новых пакетов, для удаления отмечено 0 пакетов, и 0 пакетов не обновлено.
Необходимо скачать 4 072 kБ архивов.
После данной операции, объём занятого дискового пространства возрастёт на 9 025 kB.
Хотите продолжить? [Д/н] 

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

nginx

Отлично, сервер откликнулся. Создаю новый конфигурационный файл:

sadmin@tester:~$ sudo nano /etc/nginx/sites-available/tester.ru

и привожу его к следующему виду:

tester.ru

Сохраняю файл и выхожу из текстового редактора. Создаю ссылку на вновь созданный файл в соответствующей директории Nginx:

sadmin@tester:~$ sudo ln -s -T /etc/nginx/sites-available/tester.ru /etc/nginx/sites-enabled/tester.ru
sadmin@tester:~$ 

Удаляю дефолтный линк:

sadmin@tester:~$ sudo rm -f /etc/nginx/sites-enabled/default 
sadmin@tester:~$ 

И наконец создаю ссылку на статику:

sadmin@tester:~$ ln -s -T /home/sadmin/workspace/tester.ru/imagestore/imgstore/static/ /home/sadmin/workspace/tester.ru/static
sadmin@tester:~$ 

C Nginx всё!

13. Настройка автостарта Gunicorn

Создаю новый файл:

sadmin@tester:~$ sudo nano /etc/systemd/system/gunicorn-tester.ru.service

И привожу его к следующему виду:

gunicorn-unit

Сохраняю файл и выхожу из текстового редактора. Включаю новый сервис в автостарт при загрузке системы:

sadmin@tester:~$ sudo systemctl enable gunicorn-tester.ru.service 
Created symlink /etc/systemd/system/multi-user.target.wants/gunicorn-tester.ru.service → /etc/systemd/system/gunicorn-tester.ru.service.
sadmin@tester:~$ 

Перезагружаю сервер:

sadmin@tester:~$ sudo shutdown -r now
Connection to 192.168.56.101 closed by remote host.
Connection to 192.168.56.101 closed.
sadmin@debian:~$ 

Дожидаюсь загрузки сервера и стучусь в искомый хост в web-браузере:

home

Welcome Home! Приложение развёрнуто и исполняется. На текущий момент в приложении зарегистрирован единственный пользователь - суперпользователь support, можно войти с его именем и паролем:

login

support

Можно создавать альбомы, загружать и хранить изображения, публиковать ссылки на них.

 
Осталось: 111
Комментарии: