Сегодняшняя статья будет посвящена подготовке рабочего места разработчика. А именно — установке и настройке LNMP-окружения на виртуальной машине в windows-среде. Всех заинтересовавшихся приглашаю под кат!
Сразу же возникает пара вопросов:
- Почему не взять готовый Denwer, XAMPP, Open Server?
- Зачем всё делать руками? Есть же Vagrant
Прежде, чем начать описание процесса, отвечу на эти вопросы по порядку.
1. В сети есть много готовых сборок веб-серверов, предназначенных для локальной разработки в windows-средах. Для начинающих разработчиков полезно использовать такие сборки, чтобы овладеть языком программирования и не заморачиваться с системным администрированием. Но очень скоро начинаются первые трудности:
- Большинство хостингов сейчас предлагают linux-среды для размещения сайтов. Соответственно, тут же начинаются проблемы с кодировкой, адресацией и прочим при переносе своего проекта из среды разработки на продакшн.
- Если первые проблемы устранены, то со временем возникает необходимость установки модулей PHP/Apache/NGINX для решения прикладных задач. При портировании с windows на *nix могут возникнуть проблемы с настройкой и поведением приложения.
- PHP 5.5 и выше не умеет работать с Windows XP и ниже
2. Автоматическая сборка сервера — это здорово, удобно, круто и даёт профит при указании в резюме 😉 Разумеется, гораздо легче собрать сервер при помощи того же Vagrant. Но проблема в том, что любая автоматизация без понимания всех стадий технического процесса очень быстро разваливается. Поэтому я расскажу о пошаговой сборке сервера руками, чтобы потом уже можно было говорить об автоматизации.
Итак, начнём.
Шаг №0. Скачиваем дистрибутивы.
- VirtualBox для Windows [ скачать ] — выбирайте соответствующую разрядность для вашей операционной системы. Если Вы используете х64 систему и хотите установить x64 виртуальную машину, то необходимо проверить, что Ваш процессор имеет аппаратную поддержку виртуализации. Если это так, то в BIOS необходимо перейти к секции Processor и включить Intel Virtualization Technology (в некоторых системах может называться Virtualization Extensions) или AMD-V. После этого VirtualBox сможет работать с 64-разрядными виртуалками
- Дистрибутив Linux [ скачать ] — начнём с наиболее простого для изучения дистрибутива : Ubuntu Server 18.04 LTS. Вообще, я предпочитаю CentOS для работы, но его преимущества безопасности и строгости становятся его же минусами для изучения с нуля.
- Клиент для подключения через SSH — PuTTY
Шаг №1. Создаём виртуальную машину и устанавливаем ОС
После запуска программа VirtualBox встретит нас примерно таким окном:
В нём Вам нужно выбрать кнопку «Создать», по нажатию которой система выдаст диалоговое окно мастера создания виртуальных машин
Здесь нужно указать:
- Имя виртуалки (какое больше нравится)
- Выбрать тип ОС (нам нужна Linux)
- Выбрать тип серверного linux-дистрибутива (у наc Ubuntu Server)
- Указать объём доступной оперативной памяти. Тут нужно отталкиваться от требований проектов. Для скриптов при обучении с лихвой хватит 2 ГБ. Если на стадии обучения скрипты будут вылезать за лимит памяти, то что-то точно идёт не так. Можно указать и меньше, но для нашего проекта будет использоваться база данных MySQL, а она довольно прожорливая в плане RAM.
- Дать инструкцию на создание виртуального жёсткого диска. Нам вполне хватит 20 гигабайт для стартовых проектов.
По нажатию на кнопку «Создать», система выдаст ещё одно диалоговое окно — создания виртуального жёсткого диска
Указываем расположение, размер, тип (VDI) по умолчанию. Формату хранения я бы уделил больше внимания.
- Динамический жёсткий диск изначально занимает мало места на физическом носителе, но растёт по мере добавления файлов на виртуальную машину. Растёт он ровно до указанного при создании лимита.
- Фиксированный жёсткий диск на физическом носителе сразу занимает примерно тот же объём памяти, который выделяется ему при установке.
В чём же разница? В целях обеспечения стабильности работы системы лучше использовать виртуальные жёсткие диски фиксированного размера, т.к.
- Быстродействие ввода-вывода будет максимальным для виртуальных жестких дисков фиксированного размера, поскольку для файла не используется динамическое расширение.
- При расширении динамического жёсткого диска на физическом носителе может закончится пространство для хранения данных, что приведёт к сбою записи.
- Данные в файле не будут повреждены вследствие нехватки пространства на диске или прекращения подачи питания.
Итак, мы создали наш жёсткий диск и вернулись в первое диалоговое окно. Наша виртуальная машина готова к запуску. Но не торопитесь стартовать! Нужно внести ещё несколько настроек. Выбираем нашу виртуальную машину и переходим в меню её настроек.
Нам нужно настроить подключение виртуалки к сети, а также указать ей доступ к скачанному образу операционной системы.
- Переходим в меню «Сеть» и выбираем тип подключения «Сетевой мост». При необходимости нужно указать сетевую карту, если у Вас их несколько. В данном варианте соединения адаптер выступает в роли моста между виртуальной и физической сетями. Со стороны внешней сети имеется возможность напрямую соединяться с гостевой операционной системой — это очень удобная опция.
- Переходим в меню «Носители -> Атрибуты -> Оптический привод» и кликаем на иконку компакт диска, чтобы выбрать наш скачанный образ на 0-вом шаге.
Вот теперь можно нажимать «ОК» и запускать виртуальную машину. При первом запуске начнётся установка ОС Ubuntu. Выбираем язык English, а на следующем шаге — Install Ubuntu Server.
Далее Вам будет предложено
- Выбрать язык ОС и временную зону.
Россия находится в Other -> Europe -> Russian Federation.
На шаге configure locales выбираем United States — en_US.UTF-8.
Раскладку клавиатуры (Keyboard layout) можно определить автоматически. - Указать сетевое имя (Hostname) — поставим UbuntuDev.
- Создать вторичного (после root — администратора) пользователя. Создадим пользователя developer с удобным паролем.
- Зашифровать пользовательский раздел — мы пока этого делать не будем
- Подтвердить временную зону сервера
- Разбить диск на разделы. О том, как Linux работает с диском можно прочитать здесь. А мы подробнее рассмотрим процесс разбиения на диски.
Сначала нам нужно выбрать ручное разбиение дисков — Manual
На скриншоте ниже система предлагает выбрать диск, на котором будет создана таблица разделов. Выбираем SCSI3 и на следующем шаге подтверждаем создание новой таблицы разделов.
В следующем диалоге выбираем пункт FREE SPACE
и создаём загрузочный раздел:
- Выбираем Create a new partition
- Указываем new partition size (например, 512 MB)
- Задаём type Primary
- Задаём location Beginning
- Выбираем опцию Mount point и нажимаем Enter -> Указываем mount point /boot
- Устанавливаем bootable flag в on
- Выбираем Done setting up the partition
Теперь создадим логические разделы для данных и файл подкачки (swap). Я рекомендую создать следующие логические разделы:
- /data — здесь у нас будут лежать скрипты и база данных. В больших системах стоит разделять эти вещи.
- /tmp — здесь будут накапливаться временные файлы
- /var/log — для больших систем стоит отделить раздел логов, чтобы он не мешал основной системе, но для нас это некритично.
Выбираем снова FREE SPACE -> Create a new partition. Укажем для раздела данных размер в 8 GB
Тип указываем Logical, location — beginning, Mount point -> Enter manually -> /data . В остальном всё по умолчанию. Заканчиваем создание, выбрав Done setting up the partition.
Точно также создаём раздел /tmp на 512 MB, указав в конце mount point /tmp.
Ещё 10 гигабайт выделим под корневой раздел ( «/» ) — там у нас будут храниться файлы БД.
У нас осталось около немного места. Выделим его под раздел подкачки. Для того, чтобы сделать это, на последнем шаге в пункте Use as выбираем значение swap area
В итоге должна получиться примерно следующая картинка
Разметка завершена, выбираем Finish partitioning and write changes to disk
Далее установщик предложит Вам указать настройки прокси-соединения. Если Вы не используете прокси, то просто пропустите этот шаг (Continue). Если же прокси есть, то заполните поля согласно настройкам Вашего прокси-соединения.
На следующем шаге Вам предложат выбрать автоматическую установку обновлений безопасности. Рекомендую оставить этот пункт в значении «No automatic updates», если Вы не уверены, что обновления не будут мешать Вам жить. Ведь каждое обновление потенциально приносит несовместимость с текущей системой.
Теперь установщик попросит указать пакеты, которые потребуется установить. Выбираем только OpenSSH Server (с помощью пробела). Остальное установим сами в нужных версиях.
Перед завершением установки Ubuntu попросит добавить системный загрузчик GRUB в главную загрузочную запись. Выбираем Yes и продолжаем.
На этом установка закончена. Система предупредит о том, что нужно вынуть (для нас — размонтировать) установочный диск. Это можно сделать из меню VitrualBox -> Настройки -> Носители -> Атрибуты -> Оптический привод.
Нажимаем Continue.
После перезагрузки в том самом окне GRUB выбираем Ubuntu для загрузки.
Система запросит логин и пароль. Входим под пользователем developer, которого мы создали в процессе установки. Мы внутри! 🙂
Шаг №2. Оптимизируем взаимодействие с ОС и устанавливаем пакеты.
Посмотрим, какой IP нам был присвоен с помощью команды
Запустим ssh (если он не запускался) и добавим его к автозапуску
update-rc.d ssh defaults
Теперь можно запустить скачанную на шаге №0 утилиту PuTTy и использовать её для соединения с сервером. Её интерфейс гораздо удобнее работы через VirtualBox.
PuTTy выглядит следующим образом:
Вводим полученный IP в поле Host Name (or IP address). Используем порт 22 — это порт для соединений SSH по умолчанию. Нажимаем Open.
Логинимся под пользователем developer. Теперь можно заниматься установкой нужных нам пакетов.
Нам потребуются:
- NGINX — веб-сервер для обработки пользовательских запросов
- PHP-FPM. Для установленной мной версии Ubuntu 18.04 LTS актуальной версией PHP является 7.2.3
- Percona DB — форк движка MySQL. Более стабильный и производительный
Устанавливаем NGINX
В Ubuntu 18.04 LTS по умолчанию доступен NGINX версии 1.14 (на момент написания статьи), что вполне себе нормально по функционалу, поэтому можно ставить сразу из репозитория.
После установки можем проверить версию
Должно получиться что-то вроде
nginx version: nginx/1.14.0
Устанавливаем Percona DB
Мы будем устанавливать Percona версии 5.7, где InnoDB, как известно, уже умеет делать FullText индексы, а MyISAM уже и не нужен.
Скачиваем пакет репозиториев Percona
И устанавливаем его
Обновляем список репозиториев. Не забываем, что находимся под root-ом!
Теперь можно поставить пакет БД
В процессе установки система запросит пароль root-пользователя для БД
Устанавливаем PHP-FPM
Тут всё достаточно просто
Проверяем установку
Должно получиться
PHP 7.2.3-1ubuntu4.18 (cli) (built: Oct 28 2015 01:34:46)
Copyright (c) 1997-2018 The PHP Group
Заодно добавим PHP-FPM в автозагрузку командой
Обратите внимание на то, что в новых пакетах php-fpm может называться, например, php7.2-fpm.
Шаг №3. Настраиваем пакеты и их взаимодействие
Теперь мы можем приступить непосредственно к настройке установленных пакетов для того, чтобы начать работу.
Настраиваем NGINX
Веб-сервер NGINX многопоточен. Согласно документации NGINX количество дочерних процессов веб-сервера должно быть равно количеству ядер процессора в системе.
Давайте узнаем, сколько ядер процессоров есть у нас
На моей виртуальной машине доступно 1 ядро. Я отредактирую файл nginx.conf
И выставлю значение
В конец файла добавим ссылку на подключение директории виртуальных хостов
Сохраняем файл через Ctrl + O.
Если проект должен быть доступен через браузер, то нужно создать виртуальный хост, который будет обслуживать наш проект.
Создадим директорию проекта в разделе /data
mkdir /data/myproject.com/docs
mkdir /data/myproject.com/logs
chown -R nginx:nginx /data/myproject.com
chmod -R 0775 /data/myproject.com
Обратите внимание на то, какой пользователь выполняет процесс nginx. Это может быть и www-data (посмотреть можно в nginx.conf). Поэтому в командах выше можно заменить nginx на актуального пользователя.
Теперь создаём настройку для нашего виртуального хоста
Ниже я привожу код конфигурации виртуального хоста.
# слушаем стандартный порт HTTP
listen 80;
# здесь нужно указать наш домен
server_name myproject.com www.myproject.com;
# кодировка по умолчанию
charset utf-8;
# для разработки потребуются логи
access_log /data/myproject.com/logs/access.log combined;
error_log /data/myproject.com/logs/error.log;
# корневая директория логики
root /data/myproject.com/docs;
# установим сжатие данных
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types text/plain application/xml
application/javascript
text/css
text/js
text/xml
application/x-javascript
text/javascript
application/json
application/xml+rss;
# настройки размеров и таймаутов
client_max_body_size 100m;
client_body_buffer_size 128k;
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
client_header_buffer_size 1k;
large_client_header_buffers 4 16k;
# правила обработки запросов к домену
location / {
# корневая директория
root /data/myproject.com/docs;
# стартовый скрипт
index index.php;
# правило автозагрузки в порядке следования: файл, папка, скрипт
try_files $uri $uri/ @fallback;
}
# правило для того, чтобы отдавать статические файлы
location ~* \.(jpeg|ico|jpg|gif|png|css|js|pdf|txt|tar|gz|wof|csv|zip|xml|yml) {
access_log off;
try_files $uri @statics;
expires 14d;
add_header Access-Control-Allow-Origin *;
add_header Cache-Control public;
root /data/myproject.com/docs;
}
location @statics {
rewrite ^/(\w+)/(.*)$ /$2 break;
access_log off;
rewrite_log off;
expires 14d;
add_header Cache-Control public;
add_header Access-Control-Allow-Origin *;
root /data/myproject.com/docs;
}
# правила обработки PHP-скриптов
location ~ \.php$ {
root /data/myproject.com/docs;
proxy_read_timeout 120;
fastcgi_read_timeout 120;
try_files $uri $uri/ =404;
# внимательно смотрите на то, какое имя задано у сокета
# это можно узнать в настройках php-fpm
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Активируем виртуальный хост
Если пользователь nginx существует, добавим пользователя nginx в группу www-data, чтобы NGINX мог получить доступ к сокету PHP
Перезапустим NGINX
Настраиваем Percona
Любой MySQL движок использует файл /etc/my.cnf , но у Percona его по умолчанию нет.
Создадим его
Внесём настройки
# порт и сокет для клиента
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
datadir = /var/lib/mysql
# Отдадим под innodb четверть памяти. Настройка эта зависит от объёма данных в формате innodb
# Но в идеале нужно всегда устанавливать значение больше, чем полный объём данных в innodb
innodb_buffer_pool_size = 512M
# У нас один процессор, поэтому будет только 1 поток кэша
innodb_buffer_pool_instances = 1
# Чтобы innodb работал быстрее, отключаем запись резервных данных на жёсткий диск
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = 'O_DIRECT'
Сохраним файл. Для того, чтобы применить более тонкие настройки, можно воспользоваться утилитой mysqltuner.
Зайдём на сервер MySQL. Пароль рута был задан при установке.
Посмотрим, что за пользователи созданы по умолчанию
select * from user;
Как видим, полно всего ненужного.
Удаляем пользователей, оставляя только root@localhost
drop user 'root'@'127.0.0.1';
drop user 'root'@'::1';
drop user ''@'localhost';
drop user ''@'ubuntudev';
flush privileges;
Теперь создадим базу данных и пользователя для нашего PHP-приложения. Разумеется, пароль задаём свой.
create user 'connect'@'localhost' identified by 'password';
grant SELECT, INSERT, UPDATE, DELETE on application_db.* to 'connect'@'localhost';
flush privileges;
Пользователь создан, права обновлены. Теперь можно будет спокойно соединяться с базой и работать с данными.
Настраиваем PHP
Зачастую нужно использовать PHP не только для генерации страниц, но и для выполнения команд из консоли.
При этом используются разные модули PHP и, как следствие, разные конфигурационные файлы. Для удобства сделаем один файл конфигурации и ссылки на него из модулей. Выполним поочерёдно команды
rm /etc/php/fpm/php.ini
rm /etc/php/cgi/php.ini
cd /etc/php/fpm
ln -s /etc/php/php.ini
cd /etc/php/cgi
ln -s /etc/php/php.ini
В файле /etc/php/fpm/php.ini находим параметры и вносим изменения
cgi.fix_pathinfo = 0
date.timezone = Europe/Moscow
Перезагружаем PHP-FPM
Шаг №4. Взлетит?
Теперь попробуем написать что-нибудь на PHP и проверить работоспособность результата нашей долгой работы.
Перейдём в директорию проекта
Создадим там простенький файл index.php с содержимым
echo "Hello, World!"
?>
Теперь пропишем привязку хоста к доменному имени. Если Вы работаете под Windows, то с правами администратора откройте файл
C:\Windows\System32\drivers\etc\hosts
и добавьте туда строчку
Разумеется, нужно заменить 172.20.4.14 на IP, выданный Вам сетью.
Сохраняем файл, открываем браузер и набираем myproject.com.
Если всё сделано правильно, то результатом будет вот такая картинка
Шаг №5. Работа с файлами
А какой прок от виртуалки, если нет возможности удобно работать с файлами на ней?
Можно подключить общий диск или смонтировать USB устройство. Но гораздо удобнее использовать Samba для коннекта между win и *nix.
Установим пакет
Теперь нужно произвести настройки в файле /etc/samba/smb.conf . Добавляем в конец файла строки
comment = My projects
path = /data/
valid users = developer
create mask = 0775
force create mode = 0775
directory mask = 0775
writable = yes
force group = www-data
Теперь нужно создать пользователя samba командой
указав при этом отдельный пароль для него.
Перезагружаем процессы samba
service nmbd restart
Теперь уже в windows в адресной строке проводника можно вбить наш IP
В результате мы увидим вот такую сетевую директорию
Кликнув по ней правой клавишей, мы сможем подключить её как сетевой диск и работать напрямую через любимый редактор файлов или IDE.
За сим всё!
С радостью отвечу на возникшие вопросы в комментариях!
NGINX / PHP-FPM / Percona (MySQL) DB на виртуальной машине Ubuntu: 14 комментариев
Доброго всего. получаю Welcome To Nginx вместо index.php . Что может быть? Спасибо
Приветствую! Было бы здорово увидеть конфиги, логи.
Судя по ответу, у Вас запрос доходит до NGINX, но не смотрит на директорию с PHP-файлами.
Спасибо за статью. Возник вопрос.
В конфиге nginx прописано user www-data;
В php-fpm
/etc/php5/fpm/pool.d/my_user.conf
прописал:
[my_user]
pm = dynamic
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_children = 5
pm.max_spare_servers = 5
php_admin_value[display_errors] = stderr
php_admin_value[log_errors] = On
listen = /var/www/php-fpm/my_user.sock
listen.mode = 0660
listen.owner = www-data
listen.group = www-data
user = www-data
group = www-data
chdir = /
php_admin_value[upload_tmp_dir] = /var/www/my_user/data/mod-tmp
php_admin_value[session.save_path] = /var/www/my_user/data/mod-tmp
php_value[date.timezone] = Europe/Moscow
php_value[max_execution_time] = 300
php_value[post_max_size] = 100M
php_value[memory_limit] = 128M
php_value[upload_max_filesize] = 100M
php_value[error_reporting] = E_ALL & ~E_STRICT & ~E_DEPRECATED
Вопрос, как разрешить, запись, выполнение и чтение файлов владельцем которых является my_user для www-data и наоборот. PHP создает файлы с владельцем и группой www-data:www-data
Внесите my_user в группу www-data.
usermod -a -G www-data my_user
Здравствуйте, я делал все как вы написали и у меня тоже возникли вопросы и проблемы.
Почему nginx, ведь тот-же apache, не плох и легче устанавливается без «танцами с бубнами».
А теперь проблема коротая возник у меня после выхода стати вышли и новые версии но я пробовал сначало ваш вариант, но что странно при скачивание wget https://repo.percona.com/apt/percona-release_0.1-3.$(lsb_release -sc)_all.deb
он пишет что нет такой страницы код 404. А когда поменя версию на самую новую то он скачал мне, но скачал последний .deb, хотя я там видел и другие с тем же название только в конце отличался. Но я продолжил и устанавил его, но после выполнение команды apt-get install percona-server-server-5.6, он пишет что не получилось установить у меня битые пакеты. Я как понимаю это проблема связана запись репозитроий и какие то данные не правильно записались или обновились. Помогите пожалуйста.
Для домашнего проекта — может быть. Но не для серьёзных приложений. Накладные расходы на содержание процессов Apache слишком высоки.
Иными словами, он жрёт на порядок (не шучу, реально на порядок) больше ресурсов, чем NGINX.
Дело в том, что версия файла с момента написания статьи обновилась. Теперь команда вот такая:
GeSHi Error: GeSHi could not find the language shell (using path /data/devenergy.ru/htdocs/wp-content/plugins/codecolorer/lib/geshi/) (code 2)
Доброго времени суток!
Столкнулся с проблемой, самостоятельно никак пока не получается решить.
Идя по инструкции, использовал версию ubuntu-16.04.4-server-amd64.
Завалился на команде apt-get install php5-fpm php5-cli php5-mysql php5-gd (получаю ошибку Package ‘php5-fpm’ has no installation candidate и так для других компонентов).
Как понял из гугла, эта версия ubuntu идет с седьмой версией php.
Вроде бы всё очевидно, можно идти дальше по инструкции, но команда php -v не выполняется, получаю ошибку bash: php: command not found.
Вопрос: как быть дальше? (Я, если что, в Линуксе и back-end совсем-совсем новичок).
Дело в том, что в Ubuntu PHP 7 ставится в пакет php70. Соответственно, и вызов меняется на php70 и php70-fpm
Спасибо за инструкцию. Вроде бы работает но столкнулся с трудностями.
Во первых есть несоответсвие рисунков по размеру диска и по тому, что пишите. 10Гб и 20 Гб, ну это на любителя.
Делал все команды как написано.
Теперь по-порядку:
Под developer пакеты не ставились, ставились по sudo su.
не прошла команда chown -R nginx:nginx /data/myproject.com
не было пользователя. Добавил так:
adduser —system —no-create-home —shell /bin/false —group —disabled-login nginx
service php-fpm restart сработала,
но работает service php7.2-fpm restart
в mysql не было указанных пользователей. Был тjлько root и service.
с nginx пришлось повозиться, потому что была ошибка 502, php файлы не работали, html работали. default показывался нормально))
проблемк оказалась в этой строке конфига
fastcgi_pass unix:/var/run/php-fpm.sock;
ее поменял на
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
(p.s. смотрите что у вас в /var/run/)
немного попутался созданием ссылок, видимо был не в той папке, когда делал ссылку на myproject, пересоздал, defaul удалил.
Да, статью писал ещё при PHP 5.6, так что какие-то вещи менялись.
Спасибо за комментарии, внёс исправления.
Заодно добавим PHP-FPM в автозагрузку командой
update-rc.d php-fpm defaults
Пишет:
error: unable to read /etc/init.d/php7.4-fpm
А вот если указать update-rc.d php7.4-fpm defaults то все нормально. Убунту 20.04
Тут дело в символьной ссылке. php-fpm, по всей видимости, ведёт на ссылку без достаточных прав.
А прямой адрес вызова по версии уже позволяет себя добавлять.
Можете выложить файлом образ убунты?
Боюсь, образ получится слишком большим. Лучше уж двигаться в сторону IaC, и там выкладывать что-то типа Vagrantfile