Сервер для разработки веб-приложений

О статье
Здесь описывается пример установки виртуального сервера в среде виртуализации KVM/QEMU, предназначенного для разработки веб-приложений на базе PHP, с использованием MySQL. Требования, предъявляемые к серверу:
- отдельные виртуальные диски для размещения кода и баз данных;
- доступ разработчиков по ssh и sftp в пользовательские пространства (chroot).
Исходные параметры виртуальной машины:
- RAM: 1024MB
- HDD0: 16GB
- HDD1: 64GB
- HDD2: 64GB
В качестве операционной системы будет установлена FreeBSD (используется версия 14.1). Также будут установлены: веб-сервер apache 2.4, сервер баз данных mariarb 11.4 и интерпретатор php 8.3. Установка необходимых дополнений, библиотек и модулей будет описываться далее в тексте.
Установка операционной системы
Операционная система устанавливается на HDD0. Создайте следующие разделы:
| Тип | Размер | Точка монтирования | Метка |
|---|---|---|---|
| freebsd-boot | 512K | ||
| freebsd-ufs | 2G | / | rootfs |
| freebsd-swap | 2G | swapfs | |
| freebsd-ufs | 2G | /var | varfs |
| freebsd-ufs | 2G | /tmp | tmpfs |
| freebsd-ufs | 2G | /home | homefs |
| freebsd-ufs | 6G | /usr | usrfs |
Диски HDD1 и HDD2 будут проинициализированы позднее.
Во время установки откажитесь от создания учетной записи пользователя - это будет сделано позднее.
При первом перезапуске, в меню загрузки выберите Single Mode (клавиша 2). Система загрузится в однопользовательском режиме от имени root (вам потребуется ввести соответствующий пароль). Затем, введите ls /dev/gpt, чтобы убедиться в том, что все метки созданных разделов корректны и доступны. Если все корректно, введите exit и система загрузится в обычном режиме.
Примечание
Если метки разделов отображаются некорректно или они есть не все, обратитесь к документации по установке меток или запустите установку операционной системы заново.
Загрузившись в обычном режиме от имени root (вам потребуется ввести соответствующий пароль) отредактируйте файл монтирования файловых систем /etc/fstab командой:
Замените имена разделов на метки следующим образом:
/dev/gpt/rootfs / ufs rw 1 1
/dev/gpt/homefs /home ufs rw 2 2
/dev/gpt/tmp /tmpfs ufs rw 2 2
/dev/gpt/usr /usrfs ufs rw 2 2
/dev/gpt/var /varfs ufs rw 2 2
/dev/gpt/swapfs none swap sw 2 2
Для проверки перезагрузите систему:
После загрузки убедитесь, что файловые системы смонтированы корректно:
и
Вывод команды должен содержать список смонтированных файловых систем. При этом имена файловых систем должны соответствовать меткам.
Подключение к Интернет
Предполагается, что на этапе установки операционная система была подключена к локальной сети. Чтобы проверить это, выполните команду:
В выводе вы должны увидеть список сетевых адаптеров (один из которых lo0 и он нас пока не интересует). Для каждого из адаптеров должно быть указано поле inet, содержащее IP-адрес вашей системы.
Если из вашей локальной сети разрешен прямой доступ к Интернет, дальнейший текст этого параграфа можно пропустить. Если же доступ из вашей локальной сети к Интернет возможен только через прокси-сервер, выполните действия, описанные далее.
Замените в файле /etc/pkg/FreeBSD.conf строку:
на
Установите переменные среды:
export http_proxy="http://username:password@proxy_ip:proxy_port"
export https_proxy="http://username:password@proxy_ip:proxy_port"
Об использовании переменных среды
В целях безопасности мы не автоматизируем установку этих переменных и их нужно устанавливать каждый раз после перезагрузки сервера, если требуется доступ к Интернет.
Выполните установку и обновление менеджера бинарных пакетов:
Установите дополнительные пакеты:
Хорошей практикой является установка обновлений операционной системы. Для этого установите переменные среды:
Примечание
Установка этих переменных требуется каждый раз после перезагрузки сервера, когда необходимо выполнить обновление операционной системы.
Примечание
Установка этих переменных помешает работе менеджера бинарных пакетов. Для возобновления его работы потребуется заново установить переменные среды http_proxy и https_proxy, как было показано выше.
Затем выполните:
Создание локального администратора
Использование встроенной учетной записи root является небезопасной практикой и может привести к различным негативным последствиям. Поэтому создайте учетную запись и пароль пользователя, которому будет разрешено применять повышенные привилегии, равные root только когда это будет необходимо:
pw user add -n administrator -c 'Local Administrator' -d /home/administrator -G wheel -m -s /bin/sh
passwd administrator
Установка веб-сервера
Примечание
Помните, что для установки бинарных пакетов необходим доступ к Интернет. Установите необходимые переменные среды, если вы используете доступ к Интернет через прокси.
Установите веб-сервер apache:
Раскомментируйте строки ServerName ... и Include etc/apache24/extra/httpd-vhosts.conf в файле /usr/local/etc/apache24/httpd.conf.
Закомментируйте все строки в файле /usr/local/etc/apache24/extra/httpd-vhosts.conf.
Активируйте автозапуск веб-сервера и запустите его:
Установка сервера баз данных
Установите пакеты сервера баз данных:
Активируйте автозапуск сервера баз данных, скопируйте файл конфигурации сервера из шаблона и запустите сервер баз данных:
sysrc mysql_enable=yes
cp /usr/local/etc/mysql/my.cnf.sample /usr/local/etc/mysql/my.cnf
service mysql-server start
Выполните инициализацию сервера и установку пароля суперпользователя:
Установка PHP
Установите интерпретатор PHP, а также библиотеки для интеграции с веб-сервером и сервером баз данных:
Скопируйте файл конфигурации PHP из шаблона:
Инициализация дополительных дисков
Для обеспечения возможности увеличения емкости хранилищ исходного кода и баз данных, к виртуальной машине подключены два дополнительных диска. Один из них будет использоваться в качестве персональных изолированных пользовательских пространств, содержащих все необходимые файлы пользователей. На втором диске будут размещены все файлы сервера баз данных.
Вы можете просмотреть список дисков командой:
В списке будут перечислены все подключенные диски. В зависимости от контроллера дисков, используемого в вашей среде виртуализации, имена дисков могут отличаться. В используемой среде виртуализации KVM/QEMU диски называются da0, da1 и da2. Диск da0 используется самой операционной системой. Диск da1 используем для пользовательских пространств, а диск da2 - для сервера баз данных.
Выведите схему разделов диска da1 (если вы используете только что созданный диск, она должна быть пустой):
Если схема разделов не пустая, ее нужно очистить командой:
Создайте схему разделов типа gpt:
Добавьте в схему раздел (он будет один и займет всю доступную емкость диска):
,где LABEL - метка раздела (введите ее в соответствии с назначением раздела).
Создайте на добавленном разделе файловую систему:
Проделайте такие же действия для диска da2.
Проверьте наличие и корректность меток созданных разделов командой:
Вывод команды должен содержать список всех меток всех разделов на всех дисках. Предположим, метки созданных разделов называются chrootfs и mariadbfs.
Теперь нужно смонтировать созданные разделы и скопировать на них необходимые данные. Так как копировать данные будем из имеющихся директориев, новые разделы смонтируем пока во временные директории /dir1 и /dir2:
Диск с разделом для пользовательских пространств будет содержать все данные, связанные с веб-сервером. Скопируйте содержимое директории /usr/local/www в директорию /dir1:
Теперь скопируем файлы сервера баз данных. В целях недопущения потери каких-либо данных, временно остановим сервер, после чего скопируем все файлы:
В завершение, добавьте в файл /etc/fstab строки для автоматического монтирования разделов в директории, которые используются веб-сервером и сервером баз данных:
Отмонтируйте и удалите временные директории dir1 и dir2, затем проверьте монтирование разделов:
Установите права владения на директорию сервера баз данных, принадлежащие самому серверу:
Запустите сервер баз данных и проверьте его работоспособность, выполнив поключение к нему:
Проверьте соединение с веб-сервером:
Вывод должен содержать код начальной страницы веб-сервера.
Настройка удаленного доступа
Сохраните резервную копию файла конфигурации сервера SSH:
Замените содержимое файла конфигурации сервера SSH на следующее:
AddressFamily inet
AllowAgentForwarding no
AllowStreamLocalForwarding no
AllowTcpForwarding no
# Следующая строка может использоваться для ограничения доступа пользователя с определенного IP-адреса
# AllowUsers user@127.0.0.*
AuthenticationMethods publickey
AuthorizedKeysFile /etc/ssh/authorized-keys/%u
Banner none
Ciphers aes128-ctr,aes192-ctr,aes256-ctr
ClientAliveCountMax 1
ClientAliveInterval 300
DisableForwarding yes
KbdInteractiveAuthentication no
KexAlgorithms ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256
# Следующая строка может использоваться для ограничения прослушиваемых локальных IP-адресов (если на сервере несколько сетевых адаптеров или IP-адресов)
# ListenAddress 192.168.0.3
LoginGraceTime 20
LogLevel VERBOSE
MACs hmac-sha2-256,hmac-sha2-512,hmac-sha1
MaxAuthTries 3
PermitEmptyPasswords no
PermitRootLogin no
PubkeyAuthentication yes
SyslogFacility AUTHPRIV
Subsystem sftp /usr/libexec/sftp-server
X11Forwarding no
X11UseLocalhost no
Compression no
MaxSessions 2
Port 2414
TCPKeepAlive no
UseDNS no
PubkeyAcceptedAlgorithms ssh-rsa,ssh-ed25519
Создайте директорию для файлов открытых ключей пользователей:
Если у вас есть файл открытого ключа созданного ранее пользователя administrator, то пропустите рекомендацию о создании ключа. Иначе, создайте ключевую пару:
Во время генерации ключа будет запрошена парольная фраза. Рекомендуется не игнорировать эту возможность и задать какое-то значение. Это усилит защищенность ключа.
В результате генерации будут созданы два файла administrator administrator.pub. Первый из них - файл секретного ключа (он должен находиться только у пользователя). Второй - файл открытого ключа, который можно передавать другим пользователям или использовать для прохождения аутентификации на серверах, как в данном случае.
Скопируйте файл открытого ключа и установите минимально необходимые права:
cp /home/administrator/administrator.pub /etc/ssh/authorized-keys/administrator
chown administrator:administrator /etc/ssh/authorized-keys/administrator
chmod 400 /etc/ssh/authorized-keys/administrator
Перезагрузите конфигурацию сервера SSH:
Создание пользователей
Создайте учетную запись пользователя с указанием его домашней директории, командной оболочки и установите пароль:
Создайте корневую директорию пользовательского пространства:
Так как создается изолированное пользовательское пространство, то для каждого сеанса пользователя директория /usr/local/www/USERNAME будет являться корневой. В корневой директории обычной файловой системы размещаются директории, содержащие все необходимые утилиты, приложения и конйигурационные файлы. Соответственно, в корневой директории пользовательского пространства должны быть созданы такие же директории и они должны быть наполнены такими же файлами. Однако, в рамках изолированного пользовательского пространства нужно создать только те директории и записать в них только те файлы, которые необходимы пользователю для выполнения требуемых функций. Например, чтобы пользователь смог открывать удаленный сеанс командной строки, необходим файл командной оболочки, размещенный в соответствующей директории. Фактически, речь идет о создании имитации корневой файловой системы в директории пользовательского пространства.
Создайте в корневой директории пользовательского пространства директорию bin и скопируйте файл командной оболочки:
Получение списка зависимостей
Для других операционных систем и/или других программ могут потребоваться другие файлы или директории с файлами. Чтобы узнать, от каких файлов зависит та или иная программа, выполните:
Вывод этой команды будет содержать список файлов, которые необходимы для работы указанной программы. Эти файлы нужно также скопировать в соответствующие директории пользовательского пространства. Если таких директорий нет, их нужно будет создать.Создайте в корневой директории пользовательского пространства директорию home/USERNAME и разрешите пользователю полные права на нее. В этой директории пользователь будет размещать файлы кода проектов. Эта же директория должна быть настроена в качестве корневой для виртуального хоста веб-сервера (об этом - далее).
mkdir -p /usr/local/www/USERNAME/home/USERNAME
chown USERNAME:USERNAME /usr/local/www/USERNAME/home/USERNAME
После подготовки файловой системы, настройте сервер SSH. Найдите в файле конфигурации sshd_config строку Subsystem sftp .... и замените ее на строку:
Теперь добавьте в файл конфигурации следующие строки:
Match User USERNAME
ChrootDirectory /usr/local/www/USERNAME
X11Forwarding no
AllowTcpForwarding no
AuthenticationMethods password publickey
PasswordAuthentication yes
Перезагрузите конфигурацию сервера SSH:
Настройте виртуальный хост веб-сервера. Для этого в файл /usr/local/etc/apache24/extra/httpd-vhosts.conf добавьте следующие строки:
<VirtualHost *:80>
Alias /USERNAME /usr/local/www/USERNAME/home/USERNAME
<Directory /usr/local/www/USERNAME/home/USERNAME>
AllowOverride all
Require all granted
<IfModule dir_module>
DirectoryIndex index.php index.html
<FilesMatch "\.php$">
SetHandler application/x-httpd-php
</FilesMatch>
<FilesMatch "\.phps$">
SetHandler application/x-httpd-php-source
</FilesMatch>
</IfModule>
</Directory>
</VirtualHost>
Перезагрузите конфигурацию веб-сервера:
Проверьте подключения к серверу от имени созданного пользователя при помощи SSH, SFTP и HTTP.
Дополнительные утилиты
Как уже упоминалось выше, пользовательское пространство можно дополнить любыми необходимыми программами и утилитами. Рассмотрим пример добавления клиента сервера баз данных и интерпретатора PHP с некоторым набором расширений.
Определите путь к бинарному файлу клиента сервера баз данных:
Вывод команды будет содержать абсолютный путь к файлу: /usr/local/bin/mysql. Это означает, что необходимо создать соответствующую директорию в пользовательском пространстве и затем скопировать в нее файл:
mkdir -p /usr/local/www/USERNAME/usr/local/bin
cp /usr/local/bin/mysql /usr/local/www/USERNAME/usr/local/bin
Большинство бинарных файлов имеют зависимости от различных библиотек. Чтобы узнать, какие зависимости есть у mysql выполните:
Вывод команды будет содержать список файлов библиотек, необходимых для работы mysql. Обратите внимание, что в списке также будут указаны пути к необходимым файлам. Создайте все необходимые пути относительно корневой директории пользовательского пространства и скопируйте файлы.
После этого запуск клиента сервера баз данных будет возможен из сеанса пользователя.
Проделайте действия, аналогичные указанным выше, для интерпретатора PHP.
Так как многие приложения на PHP требуют наличия необходимых расширений (работа с XML, JSON, MySQL и т.п.), нужно добавить файлы этих расширений в пользовательское пространство.
Чтобы вывести список загруженных расширений, выполните:
Например, необходимо добавить расширение Phar (оно должно быть установлено в самой системе). Для этого найдите все файлы, относящиеся к Phar:
Вывод команды будет содержать список файлов, которые необходимо продублировать в пользовательское пространство.
Примечание
Многие утилиты могут использовать для временного хранения файлов директорию /tmp. Создайте такую директорию в пользовательском пространстве и установите полный набор разрешений для всех пользователей:
О создании баз данных
Если пользователю требуется работать с базами данных, необходимо скопировать в пользовательское пространство файл /usr/local/bin/mysql и все его зависимости.
После необходимо создать пользователя на сервере баз данных:
Настройка сервера баз данных
По-умолчанию, сервер баз данных (MySQL или MariaDB) разрешает только локальные подключения. Однако, для локальных подключений требуется доступ к файлу /var/run/mysql/mysql.sock, которого нет в пользовательском пространстве и создать его там не получится, т.к. это не обычный файл. Чтобы обойти это ограничение, отредактируйте файл /usr/local/etc/mysql/conf.d/server.cnf таким образом, чтобы значение параметра bind-address было 0.0.0.0, вместо 127.0.0.1. После этого необходимо перезапустить сервер баз данных.
Чтобы разрешить пользователю создание определенной БД выполните:
Синхронизация времени
Добавьте автозагрузку службу синхронизации:
Проверьте доступность точки синхронизации времени:
, где IP - адрес сервера времени.
Вывод должен быть примерно таким:
server 194.190.168.1, stratum 1, offset -0.020765, delay 0.07323
19 Feb 20:18:26 ntpdate[25639]: adjust time server 194.190.168.1 offset -0.020765 sec
Приведите конфигурационный файл /etc/ntp.conf к такому виду:
server IP1 iburst maxpoll 9 prefer
logfile /var/log/ntp.log
restrict default ignore
restrict localhost
restrict IP1
prefer- указывает приоритетность сервера;iburst- ускоряет синхронизацию;IP1- адрес сервера синхронизации времени;restrict default ignore- запрещаем от нас брать синхронизацию.
Запустите службу и проверьте синхронизацию:
Вывод команды будет примерно таким:
remote refid st t when poll reach delay offset jitter
==============================================================================
*ntp.ix.ru .GPS. 1 u 59 64 377 47.866 10.595 0.898
+ntp2.aas.ru .GPS. 1 u 195 64 374 37.953 13.761 1.414
+server.gigelf.f 145.238.203.10 3 u 64 64 377 6.293 15.401 1.287
remote- имя удаленного сервера;refid- с этим сервером в данный момент происходит синхронизация;st- stratum (уровень) удаленного сервера (1 - высокий, эти сервера для вычисления времени используют специальное оборудование, 16 - обычный компьютер клиента);t- режим работы сервера: u unicast, b broadcast, m multicast, - manycast;when- время прошедшее с последнего момента ответа сервера в секундах или - если сервер ни разу не ответил;poll- интервал синхронизации сервера в секундах;reach- состояние доступности сервера, значение стабилизируется на уровне 377 после 8 последних удачных попыток;delay- задержка ответа сервера;offset- различие локального (системного) времени и времени на удаленном сервере;jitter- показывает смещение времени на удаленном сервере;*- в настоящий момент с этим сервером выполняется синхронизация времени;+- пригодный для обновления сервер;#- отобранный сервер слишком далеко для синхронизации времени;x- некорректный сервер (не отвечает на запросы);o- сервер добавлен в список для синхронизации используя сигнал PPS;-- плохой сервер, отвергнут по каким-то причинам;.- сервер выбран с конца списка синхронизаций.
Проверьте доступность для локальной синхронизации (синхронизация заработает примерно через 5 минут):
Вывод должен быть примерно таким:
server 127.0.0.1, stratum 2, offset 0.000004, delay 0.02563
20 Feb 09:05:43 ntpdate[48420]: adjust time server 127.0.0.1 offset 0.000004 sec
Настройка параметров безопасности
Сервер, настроенный "по-умолчанию" может содержать уязвимости конфигурации, которые способны нарушить состояние защищенности. Здесь будут рассмотрены базовые рекомендации, позволяющие повысить уровень защищенности сервера.
Загрузите данные об актуальных уязвимостях:
Закомментируйте учетную запись пользователя toor, т.к. он является дубликатом пользователя root, а также учетную запись uucp. Для этого запустите vipw - это откроет файл /etc/passwd в редакторе vi. Закомментируйте строки пользователей toor и uucp.
Установите следующие права на следующие файлы:
chmod 600 /etc/crontab
chmod 644 /etc/group
chmod 644 /etc/hosts.allow
chmod 655 /var/run/motd
chmod 644 /etc/passwd
chmod 600 /etc/ssh/sshd_config
chmod 644 /etc/hosts.equiv
chmod 700 /etc/cron.d
Добавьте в файл /etc/sysctl.conf следующие строки:
net.inet.tcp.rfc1323=0
net.inet.icmp.drop_redirect=1
net.inet.tcp.icmp_may_rst=0
net.inet.icmp.tstamprepl=0
net.inet.icmp.bmcastecho=0
hw.kbd.keymap_restrict_change=4
net.inet.ip.process_options=0
net.inet.ip.random_id=1
net.inet.ip.redirect=0
net.inet.tcp.always_keepalive=0
net.inet.tcp.blackhole=2
net.inet.tcp.drop_synfin=1
net.inet.tcp.path_mtu_discovery=0
net.inet.udp.blackhole=1
net.inet6.icmp6.rediraccept=0
net.inet6.ip6.redirect=0
security.bsd.hardlink_check_gid=1
security.bsd.hardlink_check_uid=1
Активируйте пакетный фильтр (более тонко его можно будет настроить в ходе установки сервисов):
Создайте файл /usr/local/etc/ipfw.rules, предоставьте для него право на исполнение:
Добавьте в созданный файл следующие строки:
#!/bin/sh
/sbin/ipfw -f flush
/sbin/ipfw add check-state
/sbin/ipfw add allow ip from any to any via lo0
/sbin/ipfw add deny ip from any to 127.0.0.0/8
/sbin/ipfw add deny ip from 127.0.0.0/8 to any
/sbin/ipfw add deny icmp from any to any frag
/sbin/ipfw add allow icmp from me to any
/sbin/ipfw add allow icmp from any to me
/sbin/ipfw add allow ip from me to any
/sbin/ipfw add allow ip from any to me
Измените маску для файлов по-умолчанию, отредактировав в файле /etc/login.conf строку :umask=022, заменив значение маски на 027.
Установите модули веб-сервера:
Замените значение expose_php в файле /usr/local/etc/php.ini на expose_php = Off.
Замените значение allow_url_fopen в файле /usr/local/etc/php.ini на allow_url_fopen = Off.
Добавьте в файл /etc/hosts адрес и полное доменное имя сервера:
Здесь были даны только базовые рекомендации по повышению уровня защищенности сервера. В процессе эксплуатации требуется периодическое выполнение следующих действий:
- обновление пакетов:
- обновление операционной системы:
- обновление данных об уязвимостях:
- проверка текущего состояния сервера:
- актуализация параметров безопасности веб-сервера, сервера баз данных, интерпретатора PHP и сервера SSH.
Подключение к серверу
Опишу способ подключения к проекту на установленном сервере при помощи IDE NetBeans.
Об используемых версиях
На момент написания, актуальной версией NetBeans является 23.
Откройте NetBeans и выберите File → New Project...:

В открывшемся окне 'New Project' выберите последовательно PHP → PHP Application from Remote Server и нажмите Next >:

Далее, в поле Project Name: введите имя проекта, выберите версию PHP и нажите Next >:

Укажите URL проекта и директорию для загрузки файлов и нажмите Manage... для настройки подключения к серверу:

Для добавления подключения к серверу введите имя подключения и тип соединения SFTP:

Заполните поля формы для подключения к серверу (имя хоста, порт, имя пользователя, пароль и путь к директории проекта в домашней директории пользователя). Для проверки соединения нажмите Test Connection. Для завершения настройки подключения нажмите OK:

После настройки подключения к серверу имеющиеся в указанной директории файлы (если они есть) будут загружены в локальную директорию проекта. Нажмите Finish для завершения настройки:

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