Устанавливаем Debian buster на сервер, часть вторая
debianeach
Опубликован: | 2019-08-13T05:20:51.615051Z |
Отредактирован: | 2019-08-13T05:20:19.858156Z |
Во второй части демонстрации рассмотрены вопросы подключения к серверу по ssh, установка специализированного серверного программного обеспечения, настройка и развёртывание web-приложения, настройка web-сервера и необходимых ему системных служб. В результате описанных действий в локальной виртуальной сети начнёт функционировать сайт на основе выбранного web-приложения.
1. В предыдущей серии
Первая часть описания доступна в предыдущем выпуске этого блога, который находится по этой ссылке, в ней я создал виртуальный сервер и установил на него базовую систему Debian buster. Далее мне необходимо развернуть и настроить на этом виртуальном сервере web-приложение - основу сайта. Этим я и займусь в этой части изложения.
Важное замечание: все выполненные в этой части описания действия предполагают, что виртуальный сервер включен, а окно его виртуальной машины находится на втором рабочем столе моего десктопа.
2. Настраиваем ssh-сервер
Когда базовая операционная система на сервер установлена, сеть настроена, а виртуальная машина включена и слушает сеть, можно попробовать попинговать заданный для сервера IP-адрес по заданному доменному имени. Открываю терминал на своём десктопе и ввожу команду.
ping -c 3 auriz.net
Как видно на снимке экрана, сервер откликается. Управлять сервером можно удалённо по сети, для этого на виртуальной машине установлен ssh-сервер. Сейчас я буду его настраивать.
Замечание: необходимо обратить внимание, как выглядит приглашение командной строки терминала моего десктопа, оно содержит имя пользователя - newbie
, и имя компьютера - desktop
.
SSH-подключение можно осуществить с разными методами авторизации пользователя, наиболее удобный метод предполагает подключение с помощью зашифрованного ключа. Для этого мне понадобится пара ключей, наиболее выгодным и надёжным на сегодняшний день считается ключ ED25519
. Создаю такой ключ в терминале десктопа.
ssh-keygen -t ed25519
Создание ключа осуществляется в интерактивном режиме, программа запрашивает адрес файла ключа и пароль. Пароль нужен, чтобы злоумышленник, получивший в своё распоряжение ключ не смог по нему подключиться к серверу, - мера вполне обоснованная и необходимая.
Замечание: в каталоге хранения может быть несколько ключей к разным ssh-серверам, как раз мой случай, поэтому при подключении необходимо будет указывать конкретный ключ, об этом далее.
Для подключения к ssh-серверу по ключу необходимо скопировать публичную часть ключа на сервер, к которому запланировано подключение по этому ключу.
ssh-copy-id -i ~/.ssh/aur.pub sadmin@auriz.net
Программа копирования ключа в интерактивном режиме запрашивает подтверждение, а затем ввод пароля. Необходимо ввести пароль зарегистрированного на сервере пользователя - sadmin
.
Подключаюсь к серверу.
ssh sadmin@auriz.net
Так как в каталоге хранения ключей у меня имеется несколько разных ключей, а конкретный ключ в команде подключения я не указал, подключение осуществляется по паролю пользователя sadmin
, при вводе пароль не отображается.
Следует обратить внимание, что после подключения приглашение командной строки изменило свой вид, теперь в нём указано имя пользователя - sadmin
, и имя компьютера - server
, теперь этот терминал управляет сервером, а все введённые в нём команды выполняются на сервере. Открываю в текстовом редакторе Nano файл /etc/ssh/sshd_config
, этот файл управляет настройками демона ssh.
В этом файле я изменю несколько ключевых параметров:
Port 2271
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
Сохраняю файл и покидаю текстовый редактор. Чтобы изменения вступили в силу делаю рестарт сервиса.
sudo systemctl restart sshd.service
Чтобы убедиться, что всё прошло успешно, выхожу командой exit
и пробую снова подключиться к серверу, на этот раз с указанием порта и конкретного ключа для идентификации.
ssh sadmin@auriz.net -p 2271 -i ~/.ssh/aur
С этого момента все попытки подключения по паролю будут отклонены, а подключение возможно только с указанием конкретного порта опцией -p
. Сервер настроен.
Важное замечание: при развёртывании сервера на VDS в сети Интернет я столкнулся с довольно странным поведением ssh-сервера, он запускался не сразу, - это известный баг, лечится установкой пакета haveged, воспроизводится не везде, следует иметь ввиду.
sudo apt install -y haveged
SSH-сервер настроен, и теперь у меня на десктопе есть терминал, который управляет сервером, в этом терминале я и буду осуществлять настройку web-сервера и необходимых моему web-приложению служб.
3. Устанавливаем программное обеспечение
Для правильного и эффективного обустройства моего сервера понадобятся дополнительные пакеты и программы из иных источников, которые я сейчас и буду поэтапно устанавливать.
Сначала установлю Git и Unzip, первый необходим, чтобы получить код web-приложения с git-сервера, а второй - для распаковки некоторых статических библиотек.
sudo apt install -y git unzip
Дожидаюсь полного завершения установки всех пакетов. Создаю каталог, в котором будут храниться файлы моего web-приложения, и вхожу в этот каталог.
mkdir -p workspace/auriz.net
cd workspace/auriz.net
Клонирую git-репозиторий своего приложения.
git clone https://github.com/newbie-c/auriz.git
Замечание: приложение, которое я сейчас буду разворачивать на сервер, хранится в приватной репе, поэтому описанные здесь действия можно повторить только имея доступ к этому репозиторию, если обе части этого описания получат по 5000 лайков на сайте auriz.ru, я буду готов открыть доступ к коду. Чтобы поставить "лайк/дизлайк" необходима регистрация.
Вхожу в каталог приложения auriz
и устанавливаю все перечисленные в соответствующем файле проекта пакеты.
cd auriz/ sudo apt install -y $(cat deployment/deps/dependencies.txt)
Опять дожидаюсь полного завершения процесса установки всех запрошенных пакетов. После этого добавляю текущего пользователя sadmin
в группы adm и redis.
sudo usermod -a -G adm,redis sadmin
Уже на этом этапе можно убедиться, что мой сервер откликается на запросы Интернет-браузера по заданному доменному имени.
Прогресс. Ещё чуточку терпения, сейчас всё будет...
4. Настраиваем PostgreSQL
В рамках этой демонстрации я покажу только минимально-необходимые для работы приложения настройки сервера PostgreSQL, полная настройка этой службы не вписывается в цели данной демонстрации, поэтому будет опущена.
На сервере PostgreSQL мне необходимо создать пользователя, для этого вхожу с помощью sudo как пользователь postgres
.
sudo -i -u postgres
И создаю новую роль с именем sadmin
.
createuser sadmin -P -d --interactive
После создания новой роли нужно покинуть сессию пользователя postgres
.
exit
Теперь от имени пользователя sadmin
я могу создать базу данных для своего приложения.
createdb auriz
Так как в операционной системе моего сервера настроена русскоязычная локаль ru_RU.UTF-8
, все созданные базы данных в дефолте будут иметь такую же локаль, что и требуется. Проверить локаль созданной базы данных можно подключившись к базе в клиенте psql.
psql -d auriz
Просмотреть список баз данных можно командой \l
, а покинуть клиент командой \q
.
Предпринятых действий достаточно, чтобы подключить web-приложение к серверу PostgreSQL. Тонкую настройку сервера в этом описании я рассматривать не буду, так как это тема для отдельной большой статьи.
5. Восстанавливаем окружение web-приложения
Приложение auriz разработано и отлажено на языке программирования Python3, и для его правильного функционирования на сервере мне необходимо правильно восстановить виртуальное окружение. Создаю новое виртуальное окружение.
python3 -m venv ../venv
Следует обратить внимание, что созданное виртуальное окружение будет храниться в родительском каталоге ~/workspace/auriz.net/
. Сразу после создания нужно это виртуальное окружение активировать.
source ../venv/bin/activate
Ещё один важный момент: при активации виртуального окружения приглашение командной строки меняет свой вид и получает префикс с именем активного виртуального окружения. Устанавливать пакеты можно только когда виртуальное окружение активно. Обновляю это виртуальное окружение.
pip install --upgrade wheel
Теперь мне необходимо установить в это виртуальное окружение все зависимости приложения. Начинаю с файла requirements-first.txt.
pip install -r requirements-first.txt
Следующим этапом устанавливаю пакеты из файла requirements.txt, последовательность имеет значение.
pip install -r requirements.txt
Пакетов много, исполнение этой команды завершится сообщением об успешной установке всех запрошенных модулей.
Для полного и безусловного счастья мне понадобится ещё пара модулей: gunicorn и gevent. Устанавливаю их.
pip install gunicorn gevent
Теперь у меня есть всё необходимое, чтобы запустить приложение на сервере.
6. Восстанавливаем конфигурацию web-приложения
Конфигурация web-приложения auriz хранится в файле config.py - в начальном состоянии репозитория этот файл отсутствует, но его можно восстановить из шаблона.
cp config.template.py config.py
Теперь файл конфигурации можно открыть в текстовом редакторе Nano и отредактировать. Вот содержание моего файла конфигурации:
import os from datetime import timedelta name = 'айтишные Блоги auriz.net' about = """{0} - сервис для ведения тематических IT-блогов и обсуждения затронутых тем с гостями сайта в общих комментариях или приватно.""".format(name).replace('\n', ' ') class Config: SECRET_KEY = 'v9G3JqaVVHFox4s@h^d)+F4bgbCk1E!leo4*KBQ)DQ&*M%mFB+' SITE_NAME = name SITE_DESCRIPTION = about PERMANENT_SESSION_LIFETIME = timedelta(hours=2) SQLALCHEMY_COMMIT_ON_TEARDOWN = True SQLALCHEMY_TRACK_MODIFICATIONS = False CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CELERY_BROCKER_URL = 'redis://localhost:6379/0' CELERY_IMPORTS = ('auriz.tasks',) CELERY_TASK_RESULT_EXPIRES = timedelta(hours=1) MAIL_SERVER = 'smtp.yandex.ru' MAIL_PORT = 465 MAIL_USE_SSL = True MAIL_USERNAME = 'noreply@auriz.ru' MAIL_PASSWORD = '###############' AURIZ_SUBJECT_PREFIX = '[Auriz] ' AURIZ_SENDER = 'robot <noreply@auriz.ru>' TOKEN_LENGTH = 12 REQUEST_INTERVAL = 24 MAX_CONTENT_LENGTH = 5 * pow(1024, 2) @staticmethod def init_app(app): pass class Development(Config): DEBUG = True ASSETS_DEBUG = True SEND_FILE_MAX_AGE_DEFAULT = 0 SESSION_PROTECTION = None CACHE_HOST = '192.168.56.102' # WTF_CSRF_TIME_LIMIT = 10 MAIL_DEBUG = True MAIL_SUPPRESS_SEND = True TOKEN_LENGTH = 0.1 REQUEST_INTERVAL = 0.12 SQLALCHEMY_DATABASE_URI = \ 'postgresql+psycopg2://{0}:{1}@192.168.56.102/auriz_dev'.format( os.getenv('SDBU', 'sadmin'), os.getenv('SDBP', 'aa')) class Testing(Config): TESTING = True SQLALCHEMY_DATABASE_URI = \ 'postgresql+psycopg2://{0}:{1}@192.168.56.102/auriz_test'.format( os.getenv('SDBU', 'sadmin'), os.getenv('SDBP', 'aa')) class Production(Config): SEND_FILE_MAX_AGE_DEFAULT = int(timedelta(days=28).total_seconds()) USERS_PER_PAGE = 30 LINKS_PER_PAGE = 30 LABELS_PER_PAGE = 30 ALBUMS_PER_PAGE = 10 POSTS_PER_PAGE = 30 COMMENTS_PER_PAGE = 25 ANNOUNCEMENTS_PER_PAGE = 10 FRIENDS_PER_PAGE = 10 PM_PER_PAGE = 30 SQLALCHEMY_DATABASE_URI = \ 'postgresql+psycopg2://sadmin:#######@localhost/auriz' config = {'development': Development, 'testing': Testing, 'production': Production, 'default': Production}
Все параметры спецификации я описывать не буду, важно обратить внимание на свойство SECRET_KEY
класса Config, соответствующие свойства отвечающие за сервис отправки регистрационных писем, а также свойство SQLALCHEMY_DATABASE_URI
класса Production, в нём я вписал параметры созданной для приложения базы данных. Кроме этого в словаре config в ключе default я вписал класс Production.
Когда файл конфигурации восстановлен и сохранён, нужно обновить базу данных.
python manage.py db upgrade
Создаю администратора сайта.
python manage.py create_root
Потребуется ввести имя пользователя, адрес электронной почты, с помощью которого можно обслуживать аккаунт, и придумать и ввести пароль, с которым администратор сайта сможет войти на сайт.
Остался последний штрих, необходимо заполнить базу данных изображениями для CAPTCHA-теста, для этого нужно подгрузить отладочную консоль приложения.
python manage.py shell
И воспроизвести в этой консоли вызов метода insert_data соответствующего класса.
>>> Captcha.insert_data(1000) >>> exit()
Процесс займёт некоторое время, необходимо дождаться его завершения, а затем выйти из консоли вызовом exit().
С этого момента виртуальное окружение приложения можно деактивировать.
deactivate
Распаковываю статические файлы вендоров.
unzip -d auriz/static deployment static-vendor.zip
Создаю каталог для минимизированных статических файлов таблиц стилей и JS-скриптов.
mkdir auriz/static/generic
И, наконец, восстанавливаю необходимые для правильной работы приложения символические ссылки.
ln -s -T /home/sadmin/workspace/auriz.net/auriz/auriz/static/vendor/bootstrap-3.4.1/fonts/ /home/sadmin/workspace/auriz.net/auriz/auriz/static/generic/fonts ln -s -T /home/sadmin/workspace/auriz.net/auriz/auriz/static/ /home/sadmin/workspace/auriz.net/static
Приложение готово в длительной и эффективной работе, но для этого нужно настроить соответствующие службы сервера, чем я и займусь далее...
7. Настраиваем системные службы сервера
Приложение auriz установлено, настроено и готово к запуску. Чтобы запустить приложение необходимо подготовить операционную систему сервера и настроить ключевые для auriz службы. Начнём с создания новых системных каталогов.
Приложению необходим домашний каталог для временных файлов, его я размещу в системном каталоге /run/
, кроме этого приложение будет собирать логи с двух своих системных служб, для логов создаю в системном каталоге /var/log/
два каталога с именами соответствующих служб, для этого открываю в редакторе Nano файл /etc/tmpfiles.d/workspace.conf
.
sudo nano /etc/tmpfiles.d/workspace.conf
Пишу в этом файле три строчки.
d /run/auriz.net 0755 sadmin sadmin - d /var/log/gunicorn 0750 sadmin sadmin - d /var/log/celery 0750 sadmin sadmin -
Сохраняю изменения и покидаю текстовый редактор, в итоге, при первой перезагрузке сервера все необходимые системе каталоги будут созданы автоматически. Поскольку в системе появятся две службы, собирающие логи, необходимо обеспечить ротацию логов этих системных служб. Открываю в текстовом редакторе Nano файл /etc/logrotate.d/auriz.net
.
sudo nano /etc/logrotate.d/auriz.net
И даю этому файлу следующее содержание.
/var/log/gunicorn/*.log { daily missingok rotate 20 size 256k compress delaycompress notifempty create 0640 sadmin sadmin } /var/log/celery/*.log { daily missingok rotate 20 size 256k compress delaycompress notifempty create 0640 sadmin sadmin }
Сохраняю изменения и покидаю текстовый редактор.
Web-сервер Nginx, который уже установлен в системе, тоже собирает логи, следует слегка подкорректировать ротацию логов и для него. Открываю файл /etc/logrotate.d/nginx
.
sudo nano /etc/logrotate.d/nginx
И привожу его к следующему виду.
/var/log/nginx/*.log { daily missingok rotate 365 size 256k maxsize 512k compress delaycompress notifempty create 0640 www-data adm sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ run-parts /etc/logrotate.d/httpd-prerotate; \ fi \ endscript postrotate invoke-rc.d nginx rotate >/dev/null 2>&1 endscript }
Сохраняю изменения в файл и покидаю текстовый редактор.
Теперь необходимо настроить сервер Nginx. Мне нужно, чтобы сервер слушал запросы и правильно выдавал ответы на трёх различных адресах. Первый адрес - это доменное имя auriz.net
. Второй адрес - это алиас доменного имени www.auriz.net
. И третий адрес - это собственно IP-адрес сервера, прямые запросы на этот адрес мне не нужны, поэтому я их заблокирую и настрою Nginx так, чтобы он выдавал 444
. Начнём с первого адреса. Открываю файл /etc/sites-available/auriz.net
sudo nano /etc/sites-available/auriz.net
И пишу в этот файл следующее:
server { listen 80; server_name auriz.net; client_max_body_size 8M; location /static { alias /home/sadmin/workspace/auriz.net/static; expires 2419200; add_header Cache-Control "public"; } location / { proxy_set_header Host $host; proxy_pass http://unix:/run/auriz.net/auriz.net.socket; } }
Это минимально-необходимая для auriz конфигурация Nginx, по ней видно, что web сервер будет слушать и транслировать заданный сокет, который хранится в созданном только что системном каталоге в /run/
.
Для второго ключевого адреса создаю ещё один файл.
sudo nano /etc/nginx/sites-available/www.auriz.net
server { server_name www.auriz.net; return 301 $scheme://auriz.net$request_uri; }
Все запросы по этому адресу Nginx будет переадресовывать на основной домен сайта. Сохраняю изменения в файл.
Редактирую ещё один файл, который будет отвечать за ответы Nginx на запросы отправленные по IP-адресу сервера.
sudo nano /etc/nginx/sites-available/default
server { listen 80 default_server; listen [::]:80 default_server; server_name ""; return 444; }
Чтобы Nginx начал слушать заданные адреса: auriz.net
и www.auriz.net
, необходимо создать две символические ссылки.
sudo ln -s -T /etc/nginx/sites-available/auriz.net /etc/nginx/sites-enabled/auriz.net sudo ln -s -T /etc/nginx/sites-available/www.auriz.net /etc/nginx/sites-enabled/www.auriz.net
Последний штрих для web-сервера - настройка механизмов сжатия. Открываю файл /etc/nginx/nginx.conf
.
sudo nano /etc/nginx/nginx.conf
Нахожу в нём соответствующую секцию и привожу её к следующему виду:
Все настройки будут применены автоматически при перезагрузке сервера.
Перехожу к настройке служб для очереди задач и wsgi-сервера. Обе службы должны запускаться автоматически при загрузке сервера. Для каждой из них я создам соответствующий юнит systemd.
Открываю в текстовом редакторе файл /etc/systemd/system/celery-auriz.net.service
.
sudo nano /etc/systemd/system/celery-auriz.net.service
Содержание этого юнита.
[Unit] Description=celery worker for auriz.net application After=network.target Requires=redis-server.service After=redis-server.service [Service] User=sadmin Group=sadmin WorkingDirectory=/home/sadmin/workspace/auriz.net/auriz ExecStart=/home/sadmin/workspace/auriz.net/venv/bin/celery worker \ -A celery_worker.celery -l info \ --max-tasks-per-child 100 \ --logfile=/var/log/celery/worker.log \ --pidfile=/run/auriz.net/celery.pid Restart=always RestartSec=3 [Install] WantedBy=multi-user.target WantedBy=gunicorn-auriz.net.service
Сохраняю файл и покидаю текстовый редактор.
Второй юнит будет отвечать за запуск и настройки wsgi-сервера.
sudo nano /etc/systemd/system/gunicorn-auriz.net/service
Содержание этого юнита таково.
[Unit] Description=gunicorn instance to serve auriz.net After=network.target Requires=celery-auriz.net.service After=celery-auriz.net.service [Service] User=sadmin Group=sadmin WorkingDirectory=/home/sadmin/workspace/auriz.net/auriz ExecStart=/home/sadmin/workspace/auriz.net/venv/bin/gunicorn \ --workers 3 -k gevent \ --worker-tmp-dir /run/auriz.net/ \ -p /run/auriz.net/gunicorn.pid \ --access-logfile /var/log/gunicorn/access.log \ --error-logfile /var/log/gunicorn/error.log \ --bind unix:/run/auriz.net/auriz.net.socket celery_worker:app [Install] WantedBy=multi-user.target
Включаю обе службы в систему.
sudo systemctl enable celery-auriz.net.service sudo systemctl enable gunicorn-auriz.net.service
Перезагружаю сервер.
sudo systemctl reboot
Настройка системы завершена, если всё сделано верно, и в системных конфигах не допущено ошибок, то после полной загрузки операционной системы сайт auriz.net
можно посетить в браузере.
8. Настраиваем сайт
Если настройка сервера прошла успешно, и сайт стал доступен для посещений, следует настроить сайт в браузере. Для этого нужно войти системным администратором, который был создан на этапе конфигурации auriz.
В главном меню сайта найти пункт "Сервис".
В этом меню есть параграф "Разрешения", в нём можно настроить разрешения для всех регистрирующихся пользователей, по умолчанию все вновь регистрируемые получат группу "Блогеры", эту настройку можно изменить.
Кроме этого необходимо создать файл для поисковых роботов, для этого в меню "Сервис" имеется соответствующий параграф. Стартовую страницу сайта можно заполнить после перехода по ссылке index.html.
Настройка сервера завершена. Сайт работает в штатном режиме, осталось проверить робота отправки регистрационных писем и можно приступать к наполнению сайта и созданию интересных блогов. Цель этой демонстрации достигнута.
Метки: | papa-debian, auriz, python3x, postgresql, server, redis, web-server, nginx |
Поставил лайк... Я за публикацию кода в открытый доступ. Разверну свой сайт и буду вести свой блог там, а от тебя уйду...
Не уйдёшь. 5000 лайков - цифра практически нереальная в текущем положении дел и посещаемости сайта.
Наверно да... Помечтать не даёшь. (((