Локальный веб-сервер под Linux, с автоматическим поднятием хостов и переключением версий PHP
Скорее всего какие-то части этой статьи уже знакомы многим хаброжителям, но в связи с покупкой нового рабочего ноутбука я решил собрать все крупинки воедино и организовать удобное средство для разработки. Мне часто приходится работать со множеством маленьких проектов, с разными версиями PHP, часто переводить старые проекты на новые версии. В далёком прошлом, когда я был пользователем Windows то использовал OpenServer. Но с переходом на Linux мне нехватало той простоты создания хостов и переключений версий которые были в нём. Поэтому пришлось сделать еще более удобное решение на Linux =)
Цели
- Использовать текущий на момент написания статьи софт
- Чтоб разграничить локальные домены, будем использовать специальный домен .loc
- Переключения версий PHP реализуем через поддомен c помощью fast-cgi
- Автоматическое создание хоста с помощью vhost_alias и dnsmasq
будет запущен тот же файл но уже с версией PHP 7.2.7
Другие версии доставляются аналогичным описанным ниже способом.
Для создания еще одного сайта просто создаем в /var/www/ папку имеющую окончание .loc, внутри которой должна быть папка public_html являющаяся корнем сайта
Вот собственно и все. Как без дополнительных мучений, перезапусков, и редактирований конфигов имеем автоматическую систему для работы с сайтами.
Всё это я проверну на LinuxMint19, он на базе Ubuntu18.04, так что с ним все будет аналогично.
Для начала поставим необходимые пакеты
sudo apt update sudo apt install build-essential pkg-config libxml2-dev libfcgi-dev apache2 libapache2-mod-fcgid postfix
Postfix ставим в качестве плюшки, как простое решение(в мастере установки, всё по умолчанию выбираем) для отправки почты с локальной машины.
Так как это локальная разработка и я единственный пользователь. То мне удобней перенести папку с проектами в мою домашнюю дерикторию. Она у меня маунтится отдельным диском и мигрирует при переустановке системы. Самый простой способ это создать ссылку, тогда не нужно менять пути в настройках да и путь привычный для всех.
Скопируем папку созданную апачем в домашний каталог, создадим на ее месте ссылку, не забыв поменять пользователя на себя и обменяться группами с апачем.
sudo mv /var/www/ ~/www sudo ln -s ~/www /var/www sudo chown $USER:$USER -R ~/www sudo usermod -a -G www-data $USER sudo usermod -a -G $USER www-data
Создадим папку в которой будем собирать исходники PHP для разных версий
sudo mkdir /usr/local/src/php-build
Также нам понадобится папки для CGI скриптов
И runtime папка для этих же скриптов, с правами
sudo mkdir /var/run/mod_fcgid sudo chmod 777 /var/run/mod_fcgid
И так как каталог у нас находится в оперативной памяти, добавим его создание при старте системы, для этого добавим в /etc/tmpfiles.d/fcgid.conf
#Type Path Mode UID GID Age Argument d /var/run/mod_fcgid 0755 www-data www-data - -
У меня dnsmasq-base идет с коробки, если нет то его всегда можно доставить.
sudo updatedb locate dnsmasq.conf
Либо если он как и у меня является частью NetworkManager то создать новый файл конфигурации в /etc/NetworkManager/dnsmasq.d/local.conf
Добавим в него строчку для перенаправление нашего локального домена на локальную машину.
Также нужно включить необходимые модули апача
sudo a2enmod fcgid vhost_alias actions rewrite
Предварительная подготовка завершена, приступаем к сборке различных локальных версий PHP. Для каждой версии PHP проделываем следующие 4 шага. На примере 5.6.36
1. Скачиваем исходники нужной версии и распаковываем их
cd /usr/local/src/php-build sudo wget http://pl1.php.net/get/php-5.6.36.tar.bz2/from/this/mirror -O php-5.6.36.tar.bz2 sudo tar jxf php-5.6.36.tar.bz2
2. Cобираем из исходников нужную версию PHP, и помещаем ее в /opt/php-5.6.36
sudo mkdir /opt/php-5.6.36 cd php-5.6.36 sudo ./configure --prefix=/opt/php-5.6.36 --with-config-file-path=/opt/php-5.6.36 --enable-cgi sudo make sudo make install sudo make clean
3. Создаем CGI для обработки этой версии в /var/www/cgi-bin/php-5.6.36.fcgi
#!/bin/bash PHPRC=/opt/php-5.6.36/php.ini PHP_CGI=/opt/php-5.6.36/bin/php-cgi PHP_FCGI_CHILDREN=8 PHP_FCGI_MAX_REQUESTS=3000 export PHPRC export PHP_FCGI_CHILDREN export PHP_FCGI_MAX_REQUESTS exec /opt/php-5.6.36/bin/php-cgi
4. Делаем файл исполняемым
sudo chmod +x /var/www/cgi-bin/php-5.6.36.fcgi
5. Добавляем экшен для обработки каждой версии в /etc/apache2/mods-available/fcgid.conf
AddHandler fcgid-script fcg fcgi fpl Action application/x-httpd-php-5.6.36 /cgi-bin/php-5.6.36.fcgi AddType application/x-httpd-php-5.6.36 .php #Action application/x-httpd-php-7.2.7 /cgi-bin/php-7.2.7.fcgi #AddType application/x-httpd-php-7.2.7 .php FcgidIPCDir /var/run/mod_fcgid FcgidProcessTableFile /var/run/mod_fcgid/fcgid_shm FcgidConnectTimeout 20 AddHandler fcgid-script .fcgi
6. Добавляем правило для обработки каждой версии в /etc/apache2/sites-available/000-default.conf
#Универсальный ServerNamе ServerAlias *.loc #Алиас для CGI скриптов ScriptAlias /cgi-bin /var/www/cgi-bin #Универсальный DocumentRoot VirtualDocumentRoot /var/www/%2+/public_html #Директория тоже должна быть универсальной Options +ExecCGI -Indexes AllowOverride All Order allow,deny Allow from all #Ниже все условия для каждой из версий =~ /56\..*?\.loc/"> SetHandler application/x-httpd-php-5.6.36 #По умолчанию, если версия не указанна, запускаем на последней SetHandler application/x-httpd-php-7.2.7 ErrorLog $/error.log CustomLog $/access.log combined
Ну вот и всё. Осталось только перезапустить apache и dnsmasq и пользоваться
sudo service apache2 restart sudo service network-manager restart
Настройка NGINX + NodeJS на Ubuntu Server
Обновлено: 16.03.2022 Опубликовано: 25.01.2022
Все действия будут пошаговыми — сначала мы развернем сервис на NodeJS, затем подключим NGINX и, на конец, рассмотрим установку веб-приложения.
Установка NodeJS
Установка может быть выполнена из репозитория:
Однако, во встроенном репозитории версия NodeJS может быть очень старой, и наше приложение может работать неправильно. Для продуктивной среды необходимо уточнить у разработчика, какая версия нужна и установить ее.
Чтобы получить другую версию NodeJS, установим curl:
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash —
* в данном примере мы настроим репозиторий для 16-й версии приложения.
Теперь можно установить пакет nodejs нужной нам версии (в данном примере, 16):
А для установки конкретной версии, просто указываем ее в названии пакета, например:
Установка завершена. Проверить запуск и посмотреть версию можно командой:
Можно переходить к первому запуску тестового веб-приложения.
Запуск тестового приложения NodeJS
Для примера мы напишем маленькое веб-приложение, которое будет запускаться на порту 3000 и выводить на экран «Hello, world!».
Создаем каталог, где предполагаем хранить файлы нашего приложения:
const http = require(‘http’);
const server = http.createServer((req, res) =>
res.writeHead(200, ‘Content-Type’: ‘text/plain; charset=UTF-8’
>);
res.end(‘Hello, world!’);
>);
server.listen(3000, ‘0.0.0.0’, () => console.log(‘Start NodeJS Server on http://0.0.0.0:3000/’);
>);
Если в нашей системе используется брандмауэр, откроем порт 3000:
iptables -I INPUT -p tcp —dport 3000 -j ACCEPT
На экране должно появиться:
Start NodeJS Server on http://0.0.0.0:3000/
Открываем браузер на любом компьютере в сети и переходим по адресу http://:3000 — мы должны увидеть:
Наше приложение работает. Идем дальше.
Настройка автозапуска (systemd)
Мы запустили вручную наше приложение. Давайте теперь настроим его автозапуск. Для этого мы создадим юнит в systemd. Мы создадим юнит с @ — это позволит нам передавать имя приложения и папку при запуске.
И так, прерываем работу нашего приложения, которое мы запустили на предыдущем шаге (CTRL + C) и создаем файл:
[Unit]
Description=NodeJS Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/node /var/www/%i/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
* обратите внимание на %i — это переменная, которой мы будем передавать имя нашего приложения, которое соответствует названию каталога, где оно лежит.
Перечитываем конфигурацию systemd:
Разрешаем и запускаем наше приложение:
systemctl enable node@app01 —now
* снова повторимся. app01 — имя приложения в нашем примере и ему соответствует каталог /var/www/app01.
Посмотреть состояние службы можно командой:
systemctl status node@app01
Переходим по адресу http://:3000 — мы, снова, должны увидеть:
Наше приложение запускается как сервис.
Установка и настройка NGINX
Приступим к добавлению веб-сервера nginx. Его можно установить из репозитория командой:
Сразу разрешим автозапуск:
Разрешим 80 порт в брандмауэре (если в нашей системе он используется):
iptables -I INPUT -p tcp —dport 80 -j ACCEPT
Переходим по адресу http:// (без указания порта) — мы увидим приветствие от веб-сервера:
В разделе location внесем изменения, приведя его к виду:
.
location / proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
>
.
* в нашем примере мы упростили настройку, чтобы сосредоточиться на связке NGINX + NodeJS. В продуктивной среде стоит использовать виртуальные домены. Подробнее про настройку полноценного веб-сервера можно почитать в инструкции Как настроить полноценный веб-сервер на Ubuntu.
Проверяем корректность настройки nginx:
Мы должны получить что-то на подобие:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Переходим по адресу http:// (без порта 3000) и видим:
Наше приложение открывается через nginx.
Удаляем лишнее
1. Так как мы настроили запросы через nginx, нужно поменять некоторые настройки. Открываем файл:
server.listen(3000, ‘0.0.0.0’, () => console.log(‘Start NodeJS Server on http://0.0.0.0:3000/’);
>);
server.listen(3000, ‘127.0.0.1’, () => console.log(‘Start NodeJS Server on http://127.0.0.1:3000/’);
>);
* мы поменяли 0.0.0.0 на 127.0.0.1, чтобы наш сервер не слушал на всех интерфейсах — нам достаточно только локальной петли. Это более безопасный вариант работы.
Перезапустим наше приложение node:
systemctl restart node@app01
Проверим, что наше приложение слушает на порту 3000 и уже на адресе 127.0.0.1:
tcp LISTEN 0 128 127.0.0.1:3000 0.0.0.0:* users:((«node»,pid=2503,fd=10))
2. Теперь удалим лишнее правило в брандмауэре (открытый порт 3000, если мы его создавали). Смотрим список добавленных правил:
Находим правило с открытым портом 3000:
2 ACCEPT tcp — anywhere anywhere tcp dpt:3000
* в данном примере оно имеет порядковый номер 2.
apt install iptables-persistent
Установка приложения
В установке приложений есть множество нюансов, но мы опишем типовой подход.
Нам нужен будет менеджер пакетов node. Ставим его командой:
Получаем проект от разработчика и копируем его в наш каталог app01. После переходим в каталог:
Как правило, разработчик поставляет приложение с файлом package.json. В этом файле описаны пакеты, необходимые для работы приложения. Установим их:
npm прочитает файл package.json и выполнит установку — после в нашем каталоге с приложением появятся папка node_modules и файл package-lock.json.
Также обратите внимание, что файл для запуска сервиса node может иметь другое имя. Уточните это у разработчика и, при необходимости, отредактируйте systemd.
Готово. Наше приложение должно работать.