Помогите расставить точки над и.
Какой существует бестпрактис при разворачивании lemp стека с точки зрения пользователей?
Вот только что я на vps поставил nginx, указал в конфиге, что он работает от www-data.
Поставил php-fpm, пул www которого, аналогично работает от www-data.
Установил mysql, redis, supervisor, certbot.
Далее, через rsync (пока не смотрю на ci\cd), я залил файлы проекта (php\laravel) в var/www/app
и всему содержимому папки var/www/app поставил пользователя и группу www-data:www-data (проверил через ls -la).
Потом у меня есть крон, вот с этого момента я начал беспокоиться, что делаю что-то не так.
Мне же нужно кое-какие скрипты запускать через крон (шедулер ларавела, бекапы через mysqldump и тд и тп), а доступ у меня сейчас ssh root (через ключ, а не пароль), те мне нужно crontab вызвать не для себя (рута) а для www-data, ну я так и сделал командой crontab -u www-data -e ....
Вообще, все у меня работает.
Все руками сделал, далее буду прикручивать ci\cd через gitlab, раскатывать через ansible.
Но не могу в голове уложить все по кирпичикам на счет юзеров, вычитал, что кто-то создает специального юзера для сайта, типа laravel, deployer, summy называют его, добавляют в группу www-data и работают (ларавел, кстати, так не заведется на сколько я понимаю, тк не сможет файлы сессий, логов, кеша писать в файловую систему, прав не хватит по умолчанию, но это фиксится и, наверное, косвенно относится к вопросу, хотя хз.. велосипедом из костылей пахнет).
А в одном тг чатике сказали, что делают своего юзера, пусть будет app, через него запускают nginx и php-fpm и его же назначают владельцем и группой для файлов сайта (var/www/app), дают ssh авторизацию. Те можно спокойно входить что-то править, через тот же rsync заливать, с правами траблов не будет, НО и надо помнить, что теперь нет нигде www-data и копипаст каких-то решений\конфингов может не завестись.
Погуглил и как-то решения "железобетонного" не нашел, подскажите пожалуйста как делайте вы и почему именно так?
Еще раз повторю, что как я в самом начале описал - у меня все работает, но, возможно, я не вижу какой-то ошибки, которая потом, в ci\cd, jenkinse, ansible или еще где-то мне ногу отстрелит.
Какой существует бестпрактис при разворачивании lemp стека с точки зрения пользователей.
Обязательно нужен отдельный пользователь для работы веб-сервера, субд, php-fpm, redis итд - каждому из них выдать доступ только к тем директориям и файлам, к которым им доступ необходим.
Нельзя чтобы они работали от рута или имени обычного пользователя, тк таким образом ты увеличиваешь площадь для атаки.
А одном тг чатике сказали, что делают своего юзера, пусть будет app, через него запускают nginx и php-fpm и его же назначают владельцем и группой для файлов сайта (var/www/app), дают ssh авторизацию.
Не вижу смысла выдавать app-юзеру права на логин по ssh. Все настройки можно делать и от имени административного пользователя - главное потом проверить что права выданы корректно.
НО и надо помнить, что теперь нет нигде www-data и копипаст каких-то решений\конфингов может не завестись.
Не вижу в этом никаких проблем - лишний раз включишь мозг чтобы понять, что ты там в конфигах воротишь => будешь сам знать где может быть потенциальная дыра или ошибка.
у меня все работает, но, возможно, я не вижу какой-то ошибки, которая потом, в ci\cd, jenkinse, ansible или еще где-то мне ногу отстреллит.
Значит потом для cicd / jenkins / ansible также заведёшь пользователя с нужными правами, как и у тебя, чтобы ворочать конфиги и файлы.
Спасибо за комментарий, а можете на примере показать, не очень понял про
Обязательно нужен отдельный пользователь для работы веб-сервера, субд, php-fpm, redis итд - каждому из них выдать доступ только к тем директориям и файлам, к которым им доступ необходим
Вот зашел я первый раз на сервер (под рутом)
- ставлю веб-сервер nginx, поставил, создаю юзера webserver и в конфигах nginx говорю ему запускаться от этого юзера webserver
- ставлю php-fpm, поставил, создаю юзера phpfpm и в конфигах пула говорю ему запускаться от этого юзера phpfpm
- а как с mysql не могу нагулить (или вы имеете ввиду внутренний юзер не должен быть рут? (если да, то тут я все понимаю, всегда создаю отдльного для своей БД)
- а redis как, можно пример, редиска же "в мир" мир никак не смотрит, я даже аутенитифкаци ни разу включенной не видел и на докладах говорили что не нужно особо это...
Просто вот nginx от "первого" юзера, fpm от "второго", файлы сайта лежат от "третьего"..
как это заставить все работать потом, через общие группы? сложнаааа
- а как с mysql не могу нагулить (или вы имеете ввиду внутренний юзер не должен быть рут? (если да, то тут я все понимаю, всегда создаю отдльного для своей БД)
Также как и с nginx - сам процесс mysql должен запускаться от выделенного пользователя.
Ну и внутри самого mysql тоже следует создать пользователя, у которого не будет лишних прав, а только те, которые нужны твоему приложению. Условно - только INSERT и UPDATE и только в таблицы в рамках конкретной SCHEMA (или как там оно в mysql называется)
- а redis как, можно пример, редиска же "в мир" мир никак не смотрит, я даже аутенитифкаци ни разу включенной не видел и на докладах говорили что не нужно особо это...
Даже если в интернет не смотрит - всё равно следует паролем хотябы защитить. Ну и тоже должен запускаться не от рута.
Практик очень много, тут лучше идти в сторону лучших практик от devops, это большая тема, но полезная.
Но если упрощенно и по старинке и быстро.
1. Доступ на сервер только по ssh ключам, никаких паролей.
2. Отдельный момент по sudo
2.1 Для пользователя админа в целом оставляем запрос пароля на sudo
2.2 Для сервисных аккаунтов(условные www-data и компашка,которые для служб, сервисов, автоматика того же ларавел) делаем sudo без пароля для избранных команд/программ. Таким образом автоматизация будет работать сама, независимо и стабильно.
3. Бонус пункт. Подумать о переходе на докер контейнеры на сервере, многие штуки упрощаются. Можно начать с интеграции того же laradock как самый быстрый и лёгкий старт.
PS почему rsync? Почему хотя бы не скрипты которые фетчат гит репо. rsync для некоторых сценариев бекапа еще понятно, но для деплоя кода ну не знаю. Более прозрачная схема через гит и билд на сервере. В крайнем случае в тот же гит можно и сбилженные релизы добавлять и их разворачивать на сервере.
на локалке докер, приватный реджестри на селектеле, стейджинги через докер поднимаю, с базой внутри контейнереа (все руками без автоматизации, максимум Makefile), на проде все нативно, без докера. Хотя собирать контейнеры мултистейджингом для меня тоже оказалось странно, куча телодвижений, особенно когда фронт и бек разные, тут исключить папку, тут cобрать фронт через vite, тут его подклбчить, все за собой почистить, чот туда-сюда погонять, с композером и его кешем тоже приколы всякие, чот геморрой такой кажется.. хотя пишется один раз и все... это да.
а так на 99% проектов git pull
rsync - так учебный проект на коленке, разворачиваю супер простой crud, просто учусь делать это "как взрослые", на проекте пока даже репозитория нет
Александр Талалаев у меня выходят вот такие больше докерфайлы (пугают меня) если собирать для стейдижнга, хз нормально ли это, коллег нет, чтобы спросить..
1) ставим композер и качаем все пакеты
2) ставим vite и собираем ассеты для фронта
3) ставим php-cli и extensions
4) и в него уже из 1 и 2 пункта копируем файлы + файлы ларавела
Да и база (mysql/postgres) в докере все говорят - не надо, спрашиваю почему.. и не получаю внятного ответа, ну не надо так не надо значит
PS почему rsync? Почему хотя бы не скрипты которые фетчат гит репо. rsync для некоторых сценариев бекапа еще понятно, но для деплоя кода ну не знаю. Более прозрачная схема через гит и билд на сервере.
А что не так с rsync? На мой взгляд наоборот тягать бинари через гит или собирать их на продуктивном сервере - это что-то странное, да и тратить ресурсы сервера на что-то кроме обслуживания запросов от пользователей - ну такое как по мне.
Александр Панков, докер не про нативно/виртуально. Докер в линуксе вполне себе нативно работает. Прямая и общая производительность практически такая же как и без докера. Там есть некоторые нюансы, можете почитать здесь. Но всё это мелочи по сравнению с удобством более быстрой и предсказуемой разработки и деплоя. У вас изолированные программы работают и не мешают друг другу. Нет проблемы со сменой версий(php например), не будут конфликтов и лишних библиотек в системе и тп. а так же на локалке и на сервере вам гораздо легче организовать одинаковое окружения для приложения, что критично важно во время поимки тех же багов.
Что касается rsync - всё таки странно, почти как по старинке по ftp. Может я ошибаюсь, но лучше уж если хочется билдить на локалке, то пусть в репо будет хранится сбилженное приложение.
Насчёт пункта про sudo:
Для админа, который ручками будет хотет заходить на сервер, оставляем пароль на sudo полностью.
А для сервисных пользователей, под которыми работают скрипты мы установим в /etc/sudoers для них NOPASSWORD не для всех команд, а только для избранных, которые нужны им в работе(ну и для которых нужен sudo)
Александр Панков,
"Да и база (mysql/postgres) в докере все говорят - не надо, спрашиваю почему.. и не получаю внятного ответа, ну не надо так не надо значит"
здесь сложно что-то комментировать, может там какой-то конкретный кейс. Базу вообще нередко выносят в совершенно отдельный сервис, вне того места где код запускается, чтобы не мешали другу другу. Так что чем там сам докер мешает. Может только если неверной настройкой
Александр Панков, да, обычно внутри сетки. Есть ещё куча mysql as service. Даже у того же DigitalOcean.
Удобно когда хочется уйти от админских заморочек и настроек всяких оптимальных.
В целом mysql нередко первым становится бутылочным горлышком(вместе с пользовтельскими файлами которые выводят на отдельное хранилище) в производительности, поэтому и первым попадает под масштабирование, тем или иным способом.
А с другой стороны вот есть такие истории успеха https://twitter.com/levelsio/status/1445331843176271874
Нужны отдельные unix-пользователи на сервис/проект/сайт, иначе в случае взлома сайта А будет возможность читать и модифицировать файлы сайта Б, т.к. все файлы принадлежат www-data.
Отдельные пользователи нужны всем сервисам, которые так или иначе взаимодействуют с файлами. В случае PHP это php-fpm (или другой исполнитель) — у каждого сайта должен быть свой пул со своим пользователем. Всё, с чем взаимодействие ведётся только по сети/сокету и имеет правильное разделение привилегий (базы данных), должны работать от своего (стандартного) пользователя.
В случае веб-сервера также уместно разделить статические данные от кода: картинкам и .js-файлам следует назначить www-data, чтобы веб-сервер мог их прочесть и раздать, а php-код любого сайта при этом не мог эти данные модифицировать. Верно и в обратную сторону — веб-сервер не сможет отдать ваши .php-файлы без их исполнения в случае некорректной настройки веб-сервера.
что теперь нет нигде www-data и копипаст каких-то решений\конфингов может не завестись.
И это очень хорошо, потому что бездумная копипаста может попросту сервак убить :)
подскажите пожалуйста как делайте вы и почему именно так?
Стандартный принцип - каждый сервис работает от своего юзера. redis - от юзера redis. mysql - от юзера mysql. apache - от юзера apache. Это на тот случай, если кто-то проломит сервис - он получит не права рута, а права сервиса, которые заметно меньше.
Да, иногда нужно потанцевать с правами, но оно того стоит.
Предложу немного "необычное" решение.
Запускайте все в контейнерах, docker или lxd/lxc, делайте внутреннюю сеть внутри контейнеров и проброс портов наружу для nginx.
Александр Панков, Конечно же все, при должном усердии можно взломать....
Но...
Одно дело, мы попадаем в систему, где, все как на ладони. Второе, мы в контейнере, где есть только данные этого контейнера.
Представим ситуацию, у нас есть типичный сайт: nginx, mysql, redis, php-fpm.
Если все яйца в одной корзине, то чтобы не ломанули, имеем дуступ ко всему. Сломали через php (что чаще всего и происходит), получили доступ и к nginx, и к мускулу, и к самой системе.
Теперь представим ту же ситуацию, но все в контейнерах - пострадает только контейнер с php, плюс уплывут данные из мускула и редиса (данные уплывут в любом случае при взломе). Но при этом ничего серьезно не пострадает. А может быть и данные не уплывут...
Контейнеры конечно же запускать от пользователя, доступ в систему по ssh-ключу, в каждом сервисе заводить столько прав, сколько нужно на решение задачи. Например пользователю mysql не нужно создавать новых баз данных, а возможно и таблиц...
Алексей Черемисин, спасибо.
А подскажите вот какой вопрос, не могу у себя его уложить в голове.
Вот я работаю над проектом, на локалке он у меня в докере, пускай будет на проде тоже в докере.
На прод надо доставлять контейнер с кодом внутри, а не монтировать его с хост машины.
Но в течение дня я могу пушить 10-15-20 коммитов, все они меняют код и поэтому контейнеры надо пересобирать, верно же?
А как должны тогда менять теги образов, не понимаю, сейчас я руками меняю их и перезаписываю один и тот же тег(образ) по много раз, но это же не правильно, нужно прям честное версионирование, в каком месте и как менять теги по 10-20-30 раз за день?
Александр Панков, Обычно настраивают какую нибудь систему CI/DI, которая автоматически собирает образ, когда происходит push в мастер-ветку. И уже по результатам тестирования этот образ развертывается в проде. На прод должно уходить не сразу, а после проверок.
А разработка происходит в отдельных ветках, куда хоть по 100 коммитов делать можно. Можно отдельно держать тестовую версию.
Алексей Черемисин, а внутри контейнера нужно делать своего юзра везде? как я вижу там (возможно не везде) вход в контейнер идет от рута, нужно ли это как-то переопределять? (для прода, когда нет volumes)