В прошлую субботу я написал в комментариях на хабре “хорошо, на днях опубликую свой скрипт” и это на днях пришло. ВНЕЗАПНО.
Ссылка на скрипт.
Настройка ВПСа в общих чертах
Перед настройкой я твёрдо решил что мой впс будет оплотом безопасности. Мне хотелось чтобы для каждого домена в системе был свой пользователь. Это очень аккуратно и хоть немного добавляет безопасти. Начал рассматривать варианты, их оказалось 5:
- Проксировать ngingx на одного демона fcgi запущенного из под рута. Это прекрасное решение, но работает только в однодоменных вариантах, мне же хотелось нечто вроде шареда, а тут получалось что через один процесс можно было достучаться до любого домена на сервере. Не подходит.
- Для каждого пользователя в системе запускать свой cgi процесс и постоянно держать их в памяти, проксировать nginx на них. Я засомневался в таком решении и не захотел его реализовывать (возможно у меня были какие-то объективные соображения, но я не помню). Но с другой стороны некто equand сказал мне в комментарии что это решение очень хорошо себя показывает. Поверю ему, но проверять буду на следущем впсе.
- В freebsd, говорят, есть магическая штука “Jail” которая решает все проблемы. Но это ж freebsd. Не подходит.
- Chroot’инг каждого домена. Решил не делать из-за громоздкости и дохлости впса.
- Избрал традиционное и отвратительное по производительности решение с nginx + apache, но под апачем я использую модуль mpm-itk для безопасности. Ведёт себя хорошо, но производительность близится к уровню тыквы: 20 одновременных запросов к динамике серверу уже достаточно :).
Про организацию пользователей и доменов
Nginx пускаю из под nginx:nginx, добавляю пользователя nginx в группу каждому пользователю который создается для домена. На все дирректории в /home/ ставлю права 750, для того чтобы nginx мог читать файлы, а большего ему не надо — он только отдаёт статику.
Для каждого домена создаётся отдельный пользователь. Для того чтобы было удобно смотреть на созданные домены я называю пользователей в обратной нотации, например hshhhhh.hahrahabr.ru превратится в ru_habrahabr_hshhhhh. Это становится крайне удобно когда на серваке заводится по несколько доменов третьего уровня. К сожалению пришёл к этому не сразу и было муторно всё переименовывать.
Apache запускает воркера из под того пользователя которому принадлежит домен, а значит он может видеть только свою домашнюю дирректорию и системные файлы. В любом случае сильно посторонних людей на моём впсе не будет.
Про скрипт
Теперь собственно то ради чего всё затевалось и поэтому сразу оговорюсь:
- Я прекрасно понимаю что я быдлокодер и пхпшник.
- Я писал скрипт для себя и не собирался его вообще никогда никому показывать.
- Исходя из первых двух пунктов я слабовольно решил не мучаться и написал его на пхп вместо баша. В свете последних топиков из ненормального программирования мне стыдно, но переписывать не буду.
- Знание английского у меня на крайне высоком уровне и поэтому ошибки в комментариях неизбежны.
- Я знаю что с кавычками и строками у меня там ад, но переписывать, опять же, не буду.
Скрипт делает следущее:
- Требует ввести имя домена, например “mysite.ru”.
- Выводит будущее имя пользователя, домашнюю дирректорию и имя пользователя в mysql.
- Предлагает создать пользователя, проверяет существует ли такой в системе. Если да — умрёт, а если нет то создаст домашнюю дирректорию, создаст в ней public_html, создаст index.html и напишет туда название домена, а потом присвоит правильного владельца и права на весь домашний каталог.
- Спросит создавать ли правило для nginx. Если да то возьмет шаблон, заменит в нем переменные на правильные пути и положит правило для nginx в sites-availible. Потом спросит включать ли это правило для nginx и если да, то создаст симлинк в sites-enabled и скажет nginx’у перечитать конфигурацию.
- Сделает тоже самое для апача, причем может создать правило для апача даже если отказаться делать правило для nginx. С одной стороны недоработка, а с другой может и пригодится (пока ни разу :)).
- Спросит создавать ли базу данных, обрежет имя пользователя до 16 символов, проверит существование такого в mysql и, если есть, будет пытать пока не введёшь уникальное имя. Создаст базу и пропишет доступы.
- Сохранит все пароли (для ssh и mysql) в файл, потом выйдет.
При этом пароли хранит в открытом виде в домашнем каталоге рута — ну если уж туда будет доступ то зачем уже скрывать пароли?
И этот скрипт не разрешает новосозданному пользователю подключаться по ssh, это надо делать руками и автоматизировать этот процесс я не вижу никакого смысла.
Контрольная ссылка на скрипт.
UPD: забыл добавить 2 полезных конфига в nginx.
UPD2 от некоего mike@danilenko.name про интересную особенность работы mpm-itk:
Я сам хостю у себя на сервере несколько сайтов смежных контор с нашей, и тоже пир переходе с FreeBSD на Ubuntu решил попоробовать mod_itk. даже не смотря на его тормознутость, мне это было не актуально ибо нагрузка на сайты совсем не большая, есть у этого модуля один большой недостаток, он в некторых иностранных ресурсах описан.
При использовании keep-alive в апаче, робот например от яндекса приходящий проиндексировать сайты, ходит по всем сайтом на одном IP за один раз. Но так как права разные, то зайдя на сайт xxx.ru проиндескировав его, он уходит на сайт yyy.ru… а апач не дас ему ибо он уже работает с правами xxx.ru :(
Это решается только отключением в апаче keep-alive… может при работе как бэкэнд это и не так страшно, но например у меня он тогда и статику отдает отдельными форками.
UPD3: А вот Kuzmich говорит что:
Проблема пофиксена с полгода назад, как и описано в документации теперь в этих случаях закрывается соединение.
Прямо как в сериале! Шок! Интриги! Расследования!
2011.10.17 00:52