В Интернете десятки, а может даже и сотни статей о настройке Linux серверов для хостинга Web-сайтов, что же такого нового в этой статье?
Все просто — эта статья наиболее актуальна на текущий момент, все что в ней описано было сделано на реальном сервере который вводился в эксплуатацию для хостинга небольшого Интернет-магазина (суточная посещаемость — примерно 2000 уникальных посетителей).
Итак приступим к настройке.
Исходные данные:
VPS сервер, арендованный в ihor.ru (4 CPU, 3 GB RAM, 40 GB SSD)
На сервере установлена ОС Debian 9 (minimal)
Задача:
Настроить сервер для Web-хостинга сайта Интернет-магазина, в качестве Web-сервера использовать Nginx, в качестве бэкенда — php-fpm7, в качестве ftp-сервера — pure-ftpd с локальной базой пользователей, из дополнительного софта для разработчиков развернуть phpMyAdmin.
1. Базовая настройка Debian 9.
Обновляем систему до последней версии:
apt-get update apt-get upgrade
Устанавливаем правильную часовую зону (Asia/Yekaterinburg):
dpkg-reconfigure tzdata
Устанавливаем вспомогательные пакеты (все они понадобятся нам в дальнейшем):
apt-get -y install binutils vim dirmngr git net-tools dnsutils wget curl unzip sudo
Добавим настройки среды для пользователя root (опционально, Вы можете это не делать):
sed -i 's/.*"syntax on.*/syntax on/' /etc/vim/vimrc echo 'vnoremap :w !xsel -b' >> ~/.vimrc cat <<EOT >> ~/.bashrc export HISTSIZE=10000 export HISTFILESIZE=10000 export HISTCONTROL=ignoreboth:erasedups PROMPT_COMMAND='history -a' export HISTIGNORE='ls:ps:history*' export HISTTIMEFORMAT='%d.%m.%Y %H:%M:%S: ' alias vi='vim' PS1='\n\[\e[0;33m\][\D{%d.%m.%Y %H:%M:%S}] \[\e[01;31m\]\u@\h \[\e[1;34m\]\w\n\\$ \[\e[0;32m\]\[\e[0m\]' EOT source ~/.bashrc
Указанные выше настройки среды делают следующее (Многие из них описаны в моей статье про ведение истории команд):
1. Включают подсветку синтаксиса в vim;
2. Включают возможность копировать текст открытый в vim с помощью выделения его мышкой в терминале Putty.
3. При вызове vi будет запускаться редактор vim;
4. Устанавливают настройки хранения и вывода истории команд в консоле;
5. Изменяют командную строку терминала;
Идем далее.
Добавляем пользователя под которым будем входить на сервер в дальнейшем:
adduser --gecos "Mikhail Grigorev" mgrigorev
Настраиваем sudo для нашего пользователя:
echo "mgrigorev $(hostname)=(root) PASSWD: $(which su)" >> /etc/sudoers
Хочу обратить Ваше внимание на формат добавляемой строки в файл /etc/sudoers, обычно многие администраторы добавляют такую строку:
mgrigorev ALL=(ALL) NOPASSWD: ALL
Это неправильно и нарушает безопасность сервера, никогда так не делайте!
Обязательно указывайте вместо первого ALL имя сервера, а вместо второго ALL логин пользователя с правами которого Вы запустите команду из sudo.
Так же не следует указывать NOPASSWD, т.к. таким образом для выполнения sudo не будет запрошен пароль пользователя, а значит — это потенциальная возможность для злоумышленника получить полные привилегии на сервер без знания вашего пароля.
И вместо последнего ALL всегда указывайте какую конкретно команду Вы разрешаете выполнить пользователю с повышеными привилегиями, не нужно давать пользователю право на все команды, дайте только на те, которые действительно нужны.
Итак, наша правильная строка выглядит так:
mgrigorev $(hostname)=(root) PASSWD: /bin/su
$(hostname) будет заменено на имя сервера и в файл /etc/sudoers добавиться строка:
mgrigorev myserver.ru=(root) PASSWD: /bin/su
то есть, мы дали пользователю mgrigorev право выполнить команду su с правами пользователя root и только с нашего сервера myserver.ru и обязательно с запросом пароля пользователя mgrigorev.
Проверяем коректность настроек sudo:
visudo -c
Результат:
/etc/sudoers: parsed OK /etc/sudoers.d/README: parsed OK
Теперь заходим на наш сервер через Putty под пользователем mgrigorev и добавляем свой публичный ssh-ключ:
mkdir .ssh echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOaFVMOr2pRv7FnjjJhDpS2yf1haCP9GD6yupi2E+cWW mikhail.grigorev.ed25519" > ~/.ssh/authorized_keys
Разлогиневаемся и пробуем зайти по ssh-ключу, если после подключения к серверу у Вас не был запрошен пароль и в окне Putty при подключении было написано:
Using username "mgrigorev". Authenticating with public key "mikhail.grigorev.ed25519" from agent ...
то Вы авторизовались по ssh-ключу.
Пробуем перейти в привилигерованный режим выполнив команду:
sudo su -
Обратите вниание на знак ‘-‘ после su, он не просто так написан, указав ‘-‘ при получении доступа под root мы установим все переменные среды именно пользователя root.
Если мы не укажем знак ‘-‘ , то некоторые переменные среды унаследуются от нашего пользователя mgrigorev, что в последствии может сыграть злую шутку.
Будет запрошен пароль пользователя mgrigorev, вводим его и мы должны увидеть приглашение вида:
root@myserver:~#
Если все получилось, то отключаем возможность входа на сервер под пользователем root:
sed -i "s/PermitRootLogin yes/PermitRootLogin no/g" /etc/ssh/sshd_config
Так же желательно отключить авторизацию по ssh с использованием паролей, таким образом мы обезопасим себя от варианта атаки на сервер с подбором паролей, у нас будет вход только по нашему ssh-ключу.
sed -i "s/#PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config
Перезапустим sshd:
/etc/init.d/ssh restart
2. Установка БД MariaDB 10.3
Я не буду останавливаться на установке и первоначальной настройки MariaDB 10.3, т.к. у меня в блоге есть отдельная полная статья на эту тему, на данном сервере я все делал как в статье.
3. Установка и базовая настройка Nginx
Скачиваем и добавляем ключ Nginx Inc. на нашу систему:
wget --quiet -O - http://nginx.org/keys/nginx_signing.key | apt-key add -
Если нужно установить Nginx из ветки Stable, то выполняем:
echo "deb http://nginx.org/packages/debian/ $(lsb_release -sc) nginx">/etc/apt/sources.list.d/nginx.list echo "deb-src http://nginx.org/packages/debian/ $(lsb_release -sc) nginx">>/etc/apt/sources.list.d/nginx.list
Если нужно установить Nginx из ветки Mainline, то выполняем:
echo "deb http://nginx.org/packages/mainline/debian/ $(lsb_release -sc) nginx">/etc/apt/sources.list.d/nginx.list echo "deb-src http://nginx.org/packages/mainline/debian/ $(lsb_release -sc) nginx">>/etc/apt/sources.list.d/nginx.list
Обновляем список пакетов:
apt-get update
Устанавливаем Nginx и OpenSSL (опционально):
apt-get -y install nginx apt-get -y install openssl
Запускаем Nginx:
systemctl start nginx
Проверим:
root@myserver:~# systemctl status nginx ● nginx.service - nginx - high performance web server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2018-07-21 23:40:38 +05; 4s ago Docs: http://nginx.org/en/docs/ Process: 25891 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 25892 (nginx) Tasks: 2 (limit: 4915) CGroup: /system.slice/nginx.service ├─25892 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf └─25893 nginx: worker process
Проверим открытые порты:
netstat -ltupn | grep nginx tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 25892/nginx: master
Теперь займемся базовой настройкой Nginx.
Создадим директорию для хранения SSL сертификатов и DH-ключей, а также создаем файл с параметрами для DHE-шифров:
mkdir /etc/nginx/ssl/ openssl dhparam -out /etc/nginx/ssl/dhparams.pem 2048
2048 бит выбраны не случайно, это разумный компромисс между безопасностью, оптимальной нагрузкой на CPU и скоростью работы. Если Вы думаете, что 2048 бит недостаточно, то Вы ошибаетесь, авторы атаки Logjam говорят, что простое число размеров 2048 бит и более не взламываемое при текущем уровне развития техники.
Создадим директории для хранения настроек Web-сайтов:
mkdir /etc/nginx/sites-available mkdir /etc/nginx/sites-enabled
Я приведу базовый эталонный файл настроек который использую я на 99% серверов, рекомендую использовать его с дополнительными Вашими правками под конкретные нужды. В файле присутствуют комментарии для многих параметров.
Скачать уже готовый файл для Nginx версии 1.13.x (1.15.x) и выше Вы можете командой:
wget https://gist.githubusercontent.com/CHERTS/8e9ecf4fbfb765556311a88e5106174b/raw/nginx.conf -O /etc/nginx/nginx.conf
После того, как мы сохранили наш новый файл настроек nginx.conf проверим конфигурацию Nginx:
nginx -t
Если ошибок нет, то выполняем (это заставит Nginx перечитать конфигурацию):
nginx -s reload
Меняем системные лимиты на кол.открытых файлов.
Т.к. мы указали в nginx.conf параметр worker_rlimit_nofile = 10000, то будем исходить из него.
Традиционно во всех статьях в Интернет все меняют лимиты через редактирование файла /etc/security/limits.conf, но это неправильно, т.к. для Debian 8 и Debian 9 этот файл не работает.
В Debian 8 и Debian 9 используется система инициализации systemd и поэтому лимиты на максимальное количество открытых файлов нужно настроить для systemd, для этого выполняем:
mkdir -p /lib/systemd/system/nginx.service.d/ echo "[Service]" >/lib/systemd/system/nginx.service.d/limit.conf echo "LimitNOFILE=10000" >>/lib/systemd/system/nginx.service.d/limit.conf systemctl daemon-reload systemctl restart nginx
Теперь проверим лимиты, для этого смотрим строку «Max open files» в выводе:
root@myserver:~# cat /proc/$(cat /var/run/nginx.pid)/limits Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 11960 11960 processes Max open files 10000 10000 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 11960 11960 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us
Все отлично! Nginx работает, лимит открытых файлов мы поменяли.
4. Установка и базовая настройка PHP 7.0 и PHP-FPM
Установим все необходимые пакеты:
apt-get -y install php-fpm php-mysql php-curl php-gd php-imagick php-imap php-intl php-mcrypt php-mbstring php-memcache php-memcached php-xml php-zip php-bz2
Отредактируем некоторые настройки PHP (cli):
PHPVER=7.0 sed -i "s/error_reporting = .*/error_reporting = E_ALL/" /etc/php/${PHPVER}/cli/php.ini sed -i "s/display_errors = .*/display_errors = On/" /etc/php/${PHPVER}/cli/php.ini sed -i "s/memory_limit = .*/memory_limit = 128M/" /etc/php/${PHPVER}/cli/php.ini sed -i "s/;date.timezone.*/date.timezone = Europe\/Moscow/" /etc/php/${PHPVER}/cli/php.ini
Отредактируем некоторые настройки PHP (fpm):
PHPVER=7.0 sed -i "s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/" /etc/php/${PHPVER}/fpm/php.ini sed -i "s/memory_limit = .*/memory_limit = 128M/" /etc/php/${PHPVER}/fpm/php.ini sed -i "s/upload_max_filesize = .*/upload_max_filesize = 64M/" /etc/php/${PHPVER}/fpm/php.ini sed -i "s/post_max_size = .*/post_max_size = 64M/" /etc/php/${PHPVER}/fpm/php.ini sed -i "s/;date.timezone.*/date.timezone = Europe\/Moscow/" /etc/php/${PHPVER}/fpm/php.ini
Мы установили следующие базовые настройки для php (cli):
error_reporting = E_ALL display_errors = On memory_limit = 128M date.timezone = Europe/Moscow
И установили базовые настройки для php (fpm), которые будут применяться для всех php-fpm пулов по умолчанию:
cgi.fix_pathinfo=0 memory_limit = 128M upload_max_filesize = 64M post_max_size = 64M date.timezone = Europe/Moscow
Вы можете дописать необходимые Вам настройки.
5. Создание и настройка площадки для сайта
Далее следовало бы написать огромную кучу команд для создания отдельного пользователя и группы для работы отдельного пула php-fpm от имени этого пользователя, создания php-fpm пула с минимумом настроек, создания иерархии каталогов для размещения сайта, выставления правильных прав на эти каталоги, настройка файла конфигурации нашего сайта для Nginx, создания файла для ротации логов Nginx и т.д.
Но для автоматизации всей этой рутины я написал 2 простых скрипта на bash, они открыты и размещены у меня на github.com
Скачиваем мои скрипты и распаковываем:
wget https://github.com/CHERTS/linux-scripts/archive/master.zip unzip master.zip && rm -f master.zip cd linux-scripts-master/nginx/ chmod a+x *.sh
Теперь создадим все необходимое для хостинга сайта mysite.ru (у Вас будет другой домен):
./nginx-create-vhost.sh -d mysite.ru
Результат работы скрипта:
Detecting your OS Linux (x86_64) Detecting Linux distrib Debian (SYSTEMD) Detecting your php-fpm Found php-fpm7.0 Detecting nginx owner Found www-data Set new username: web1 Set new groupname: client1 Set nginx hostname: mysite.ru Set nginx vhost ip: 194.XX.XX.XX:80 Adding new user web1... Done Adding new group client1... Done Adding user web1 to group client1... Done Adding user www-data to group client1... Done Create a home directory... Done Create web,log,tmp,private directory... Done Create index.html... Done Create robots.txt... Done Set permition to directory... Done Set protected attribute to directory... Done Create php-fpm config file web1.conf... Done Configtest php-fpm... Done Restart php-fpm... Done Create nginx config file... Done Activate nginx config file... Done Nginx configtest... Done Reload nginx... Done Create logrotate rule... Done
Что делает этот скрипт ?
Он выполняет вот такие команды на основе введенных данных и файла настройки /etc/nginx/settings.conf:
# Создание пользователя web1 и группы client1 useradd -d /var/www/mysite.ru -s /bin/false web1 addgroup client1 usermod -a -G client1 web1 usermod -a -G client1 www-data # Создания дерева каталогов для размещения web-сайта, логов nginx и временного каталога # для php-fpm и копирование заглушки сайта (index.html и robots.txt) mkdir -p /var/www/mysite.ru mkdir -p /var/www/mysite.ru/{web,log,private,tmp} cp template/index.html.template /var/www/mysite.ru/web/index.html sed -i 's/!SITENAME!/mysite.ru/g' /var/www/mysite.ru/web/index.html cp template/robots.txt.template /var/www/mysite.ru/web/robots.txt # Выставление нужных прав на каталоги web-сайта chmod -R 755 /var/www/mysite.ru chmod -R 770 /var/www/mysite.ru/tmp chmod -R 755 /var/www/mysite.ru/web chmod -R 710 /var/www/mysite.ru/private chown -R web1:client1 /var/www/mysite.ru chown root:root /var/www/mysite.ru chown root:root /var/www/mysite.ru/log chattr +a /var/www/mysite.ru # Создание типового файла настроек пулы php-fpm на основе шаблона, перезапуск php-fpm cp template/php_fpm.conf.template /etc/php/7.0/fpm/pool.d/web1.conf sed -i 's/!SITEDIR!/\/var\/www\/mysite.ru/g' /etc/php/7.0/fpm/pool.d/web1.conf sed -i 's/!USERLOGINNAME!/web1/g' /etc/php/7.0/fpm/pool.d/web1.conf sed -i 's/!GROUPNAME!/client1/g' /etc/php/7.0/fpm/pool.d/web1.conf sed -i 's/!PHPFPMSOCKDIR!/\/run\/php/g' /etc/php/7.0/fpm/pool.d/web1.conf /usr/sbin/php-fpm7.0 -t systemctl restart php7.0-fpm # Создание типового файла настроек nginx на основе шаблона, перезапуск nginx cp template/nginx_virtual_host.template /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!SERVERIP!/195.XX.XX.XX/g' /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!SERVERPORT!/80/g' /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!SITENAME!/mysite.ru/g' /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!SITEDIR!/\/var\/www\/mysite.ru/g' /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!PHPFPMSOCKDIR!/\/run\/php/g' /etc/nginx/sites-available/mysite.ru.vhost sed -i 's/!USERLOGINNAME!/web1/g' /etc/nginx/sites-available/mysite.ru.vhost ln -s /etc/nginx/sites-available/mysite.ru.vhost /etc/nginx/sites-enabled/100-mysite.ru.vhost nginx -t nginx -s reload # Создания правила ротации логов nginx cat <<EOT > /etc/logrotate.d/web2 /var/www/mysite.ru/log/access.log /var/www/mysite.ru/log/error.log { create 0644 www-data root daily rotate 10 missingok notifempty compress sharedscripts postrotate [ ! -f /var/run/nginx.pid ] || kill -USR1 \`cat /var/run/nginx.pid\` endscript } EOT
Как видите, скрипт делает довольно много работы, а главное делает он ее с предварительной проверкой многих параметров системы. А после выполнения практический каждой команды он проверяет результат ее выполнения и если что-то пойдет не так, то выполнение будет остановлено.
Именно из-за необходимости выполнения большого числа рутиных команд я и написал скрипт автоматизации nginx-create-vhost.sh
Скрипт ./nginx-create-vhost.sh создает следующую иерархию каталогов для размещения web-сайта:
/var/www - это корневой каталог для размещения всех сайтов | |- mysite.ru | |-web - каталог для размещения файлов сайта mysite.ru (php-скрипты, js,css и другие файлы) | |-log - каталог в котором будут лежать лог-файлы web-сервера nginx (acces.log и error.log) | |-tmp - каталог для размещения временных файлов php (файлы сессий и прочее) | |-private - каталог для размещения файлов скриптов (php) доступных для выполнения через директиву open_basedir | |- mysite2.ru |-web ....
Все файлы конфигурации Nginx будут создаваться в каталоге /etc/nginx/sites-available
Все активные сайты активируются путем создания симлинка в каталоге /etc/nginx/sites-enabled на соответствующий файл в /etc/nginx/sites-available
Все файлы настроек пулов php-fpm для Debian 9 будут создаваться в каталоге /etc/php/7.0/fpm/pool.d, для Debian 8 или Oracle Linux каталоги будут другие.
Все файлы правил ротации логов будут создаваться в каталоге /etc/logrotate.d
Ниже представлен типовой файл настроек Nginx (/etc/nginx/sites-available/mysite.ru.vhost)
Файлы называются по имени сайта с добавлением расширения vhost.
Вы можете изменить шаблон файла template/nginx_virtual_host.template на основе которого создается конфигурация vhost.
server { listen 194.XX.XX.XX:80; server_name mysite.ru www.mysite.ru; root /var/www/mysite.ru/web; index index.php index.html index.htm; error_log /var/www/mysite.ru/log/error.log; access_log /var/www/mysite.ru/log/access.log main; set $fastcgipass unix:/run/php/web1.sock; if ( $args ~ "_SERVER|_GLOBALS|DOCUMENT_ROOT|INCLUDE_FOLDER|ROOT_FOLDER|FILES_FOLDER|MODULE_FOLDER|ADMIN_FOLDER|TMP_FOLDER" ) { return 500; } location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mov)$ { charset utf-8; expires 14d; access_log off; log_not_found off; } location = /favicon.ico { log_not_found off; access_log off; } location = /robots.txt { allow all; log_not_found off; access_log off; } location /ng1nx_statuz { stub_status on; access_log off; allow all; } location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { try_files $uri = 404; fastcgi_pass $fastcgipass; fastcgi_param HTTPS $fastcgi_https; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include /etc/nginx/fastcgi_params; } }
Это минимально необходимый файл конфигурации Nginx, для того, чтобы заработали php-скрипты на сайте.
Вы можете его изменять и добавлять нужные Вам директивы.
Например если у Вас сайт на WordPress, то файл может принять такой вид (привожу только часть блоков location):
.... location ~* /(images|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ { deny all; access_log off; log_not_found off; } location ~* /wp-content/.*\.php$ { deny all; access_log off; log_not_found off; } location ~* /(?:uploads|files)/.*\.php$ { deny all; access_log off; log_not_found off; } location = /wp-config.php { deny all; access_log off; log_not_found off; } location = /xmlrpc.php { deny all; access_log off; log_not_found off; } location / { try_files $uri $uri/ /index.php; } location ~ \.php$ { try_files $uri @cms; include /etc/nginx/fastcgi_params; fastcgi_param HTTPS $fastcgi_https; fastcgi_pass $fastcgipass; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location @cms { fastcgi_pass $fastcgipass; fastcgi_param HTTPS $fastcgi_https; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include /etc/nginx/fastcgi_params; } ....
После изменения файла конфигурации Nginx не забудьте проверить конфигурацию и перезагрузить ее:
nginx -t && nginx -s reload
Ниже представлен типовой файл настроек пула php-fpm (/etc/php/7.0/fpm/pool.d/web1.conf)
Файлы пула называются по логину создаваемого пользователя от имени которого данный пул будет работать.
Вы можете изменить файл шаблона template/php_fpm.conf.template на основе которого создаются настройки пула php-fpm.
[web1] listen = /run/php/web1.sock listen.owner = web1 listen.group = client1 listen.mode = 0660 user = web1 group = client1 pm = dynamic pm.max_children = 10 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 5 pm.max_requests = 500 request_terminate_timeout = 15m request_slowlog_timeout = 5s slowlog = /var/www/mysite.ru/log/php-slow.log chdir = / php_admin_value[open_basedir] = /var/www/mysite.ru/web:/var/www/mysite.ru/private:/var/www/mysite.ru/tmp:/usr/share/php5:/usr/share/php:/tmp:/usr/share/phpmyadmin:/etc/phpmyadmin:/var/lib/phpmyadmin php_admin_value[session.save_path] = /var/www/mysite.ru/tmp php_admin_value[upload_tmp_dir] = /var/www/mysite.ru/tmp php_admin_flag[cgi.fix_pathinfo] = off php_admin_value[error_log] = /var/www/mysite.ru/log/php-error.log
Вы можете добавлять в этот файл уникальные для каждого сайта настройки php, например увеличим лимит памяти (memory_limit) для сайта, для этого добавим в файл /etc/php/7.0/fpm/pool.d/web1.conf настройку
php_admin_value[memory_limit] = 256M
Проверим корректность настроек и перезапустим php-fpm (для Debian 9):
php-fpm7.0 -t systemctl restart php7.0-fpm
Так же в комплекте со скриптом создания типовой хостинговой площадки (nginx-create-vhost.sh) идет скрипт ее удаления — nginx-remove-vhost.sh
Скрипту удаления площадки (nginx-remove-vhost.sh) нужно указать чуть больше настроек (нужно указать имя сайта, логин пользователя и имя группы), например:
Посмотрим какому пользователю и группе принадлежит сайт:
ls -l /var/www/mysite.ru total 16 drwxr-xr-x 2 root root 4096 Aug 6 15:45 log drwx--x--- 2 web1 client1 4096 Aug 6 15:45 private drwxrwx--- 2 web1 client1 4096 Aug 6 15:45 tmp drwxr-xr-x 2 web1 client1 4096 Aug 6 15:45 web
Удалим каталог сайта, все настройки php-fpm, nginx, logrotate, а так же пользователя и группу с правами которой работал php-fpm:
./nginx-remove-vhost.sh -d mysite.ru -u web1 -g client1
Результат:
Detecting your OS Linux (x86_64) Detecting Linux distrib Debian (SYSTEMD) Detecting your php-fpm Found php-fpm7.0 Delete php-fpm config file web1.conf... Done Configtest php-fpm... Done Restart php-fpm... Done Deactivate nginx config file... Done Delete nginx config file... Done Nginx configtest... Done Reload nginx... Done Delete logrotate rule... Done Unset protected attribute to directory... Done Delete site directory... Done Delete group client1... Done Delete user web1... Done
ВНИМАНИЕ! Скрипт nginx-remove-vhost.sh удаляет все настройки созданные скриптом nginx-create-vhost.sh включая каталог с сайтом, логами и т.п., он не спросит подтверждения, он удалит тот каталог в /var/www что Вы укажите в опции -d и удалит пользователя и группу указанные в опциях -u и -g
6. Расширенная настройка Nginx
Почему я выделил эти настройки в отдельный пункт и что сюда входит ?
При настройке работы Nginx многие администраторы не уделяют должного внимания таким вещам как порядок обработки запросов web-сервером Nginx и правильная настройка default_server. В результате когда у Вас на сервере размещается несколько сайтов и Вы случайно заходите на сайт не по доменному имени, а например по IP адресу Вашего web-сервера и получает страницу «Welcome to Nginx» или еще хуже того — страницу случайного сайта, расположенного на Вашем сервере.
Чтобы этого избежать нужно настроить default_server на Nginx — это тот виртуальный сервер, который Nginx будет использовать для обработки HTTP-запросов в поле Host которых указан сервер не подходящий под Ваши существующие настройки или отсутствующий у Вас в настройках в принципе.
Например, у вашего сервера IP адрес 194.10.12.13 (для примера), для сайтов mysite1.ru, mysite2.ru и mysite3.ru в качестве A-записи указан Ваш IP адрес 194.10.12.13. Для сайтов mysite1.ru и mysite2.ru у Вас создан виртуальный сервер Nginx (есть конфиг), а вот для mysite3.ru не создан виртуальный сервер. Тогда если Вы откроете в браузере mysite3.ru, то получите либо страницу «Welcome to Nginx», либо откроется первый из сайтов расположенных на Вашем сервере (первый, это тот чей виртуальный сервер будет первым в списке на обработку запросов у Nginx).
Чтобы этого избежать нужно создать виртуальный сервер по умолчанию, который будет обрабатывать все неизвестные запросы, как правило обрабатывать эти запросы не нужно, т.к. это создаст дополнительную нагрузку на Ваш web-сервер, правильнее всего все эти соединения закрывать. Для этого разработчики Nginx придумали специальный код 444 (его нет в стандарте HTTP), который закрывает соединение.
Итак правильный файл конфигурации виртуального сервера по умолчанию будет таким:
server { listen 194.XX.XX.XX:80 default_server; listen 194.XX.XX.XX:443 http2 ssl default_server; server_name _; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_certificate /etc/nginx/ssl/default_server.crt; ssl_certificate_key /etc/nginx/ssl/default_server.key; return 444; }
Сохраняем это в файл /etc/nginx/conf.d/fallback.conf, правим под себя IP адрес вашего сервера.
Чтобы Nginx подключил конфигурацию из файла /etc/nginx/conf.d/fallback.conf нужно чтобы каталог /etc/nginx/conf.d был определен в директиве include в файле /etc/nginx/nginx.conf, примерно так:
.... http { ... include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
Данный fallback.conf определяет default_server как для соединений по 80 порту (HTTP), так и для соединений по порту 443 (HTTPS). Для обработки HTTPS соединений нам нужно создать минимальный самоподписной сертификат, он будет нужен лишь для того, чтобы браузер на этапе установки TLS-соединения (Handshake) попытался все таки его установить, хоть и с выводом ошибки, что сертификат самоподписной, ну а далее уже на этапе HTTP соединение будет закрыто самим Nginx. Если кому-то интересно почитать как работает TLS, то я рекомендую статью Александра Венедюхина, там много интересного.
Создаем простой самоподписной сертификат (194.XX.XX.XX замените на свой IP):
mkdir /etc/nginx/ssl openssl genrsa -out /etc/nginx/ssl/default_server.key 2048 openssl req -new -key /etc/nginx/ssl/default_server.key -sha256 -out /etc/nginx/ssl/default_server.csr -subj "/C=CA/ST=None/L=NB/O=None/CN=194.XX.XX.XX" openssl x509 -req -sha256 -days 3650 -in /etc/nginx/ssl/default_server.csr -signkey /etc/nginx/ssl/default_server.key -out /etc/nginx/ssl/default_server.crt
После этого проверяем конфигурацию Nginx и перезагружаем ее:
nginx -t && nginx -s reload
Теперь пробуем открыть сервер по IP адресу:
http://194.XX.XX.XX
https://194.XX.XX.XX
http://mysite3.ru
https://mysite3.ru
* Сайты mysite3.ru я взял для примера, у Вас конечно же будут свои сайты.
В браузере соединение по HTTP будет закрыто сразу, а по HTTPS к примеру Google Chrome скажет вначале, что у нас самоподписной сертификат (NET::ERR_CERT_AUTHORITY_INVALID), далее если принять сертификат и перейти на сайт, то соединение по HTTPS так же будет закрыто.
Можно попробовать с другого сервера установить соединение с помощью curl, например так:
Для HTTP:
$ curl -D -k -s http://194.XX.XX.XX -v * Rebuilt URL to: http://194.XX.XX.XX/ * Trying 194.XX.XX.XX... * Connected to 194.67.207.125 (194.XX.XX.XX) port 80 (#0) > GET / HTTP/1.1 > Host: 194.XX.XX.XX > User-Agent: curl/7.47.0 > Accept: */* > * Recv failure: Connection reset by peer * Closing connection 0
Для HTTPS:
$ curl -D -k -s https://194.XX.XX.XX -v * Rebuilt URL to: https://194.XX.XX.XX/ * Trying 194.XX.XX.XX... * Connected to 194.XX.XX.XX (194.XX.XX.XX) port 443 (#0) * found 148 certificates in /etc/ssl/certs/ca-certificates.crt * found 592 certificates in /etc/ssl/certs * ALPN, offering http/1.1 * SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256 * server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none * Closing connection 0
Мы видим, что соединение сразу же закрывается — этого мы и хотели добиться.
Вместо кода 444 Вы можете написать в fallback.conf код 403 и тогда соединение будет открываться и возвращаться HTTP код 403, но лучше не доводить соединение до стадии открытия.
7. Установка и настройка phpMyAdmin
Для Web-разработчиков phpMyAdmin необходим как собственно и сам PHP, поэтому давайте установим и настроим его.
Во-первых давайте определимся по какому URL мы и web-разработчики будут заходить в phpMyAdmin.
Обычно для phpMyAdmin выделают отдельный поддомен, например phpmyadmin.mysite.ru, но у нас же на сервере будет куча сайтов и делать для каждого такого вида поддомен просто неудобно.
Давайте сделаем URL такого вида http://mysite.ru/phpmyadmin и при входе на него наш web-сервер будет делать 301 редирект на какой-то постоянный сервисный домен http://phpmyadmin.myorg.ru
Пусть сайт phpmyadmin.myorg.ru так же будет на этом сервер, для простоты настройки.
Воспользуемся моим скриптом nginx-create-vhost.sh для создания этой сервисной площадки:
./nginx-create-vhost.sh -d phpmyadmin.myorg.ru
Я опущу вывод процесса создания площадки, она успешно создастся, наш рабочий каталог для php-скриптов phpMyAdmin будет /var/www/phpmyadmin.myorg.ru/web
Теперь скачаем последнюю версию phpMyAdmin и развернем ее в каталоге /var/www/phpmyadmin.myorg.ru/web:
cd /var/www/phpmyadmin.myorg.ru/web wget https://files.phpmyadmin.net/phpMyAdmin/4.8.3/phpMyAdmin-4.8.3-all-languages.zip -O phpMyAdmin-4.8.3-all-languages.zip unzip phpMyAdmin-4.8.3-all-languages.zip rm -f phpMyAdmin-4.8.3-all-languages.zip mv phpMyAdmin-4.8.3-all-languages/* . rm -rf ./phpMyAdmin-4.8.3-all-languages/ chown -R web2:client2 *
Здесь в команде chown мы назначаем владельца и группу для файлов phpMyAdmin, у Вас это будут другие пользователь и группа.
Далее настроим конфигурацию phpMyAdmin, для этого перейдите в браузер по адресу http://phpmyadmin.myorg.ru/setup/ и создайте файл конфигурации config.inc.php для вашей БД, в самом простом виде он выглядит так:
<?php $cfg['blowfish_secret'] = 'XXXXXXXXXXXX'; $cfg['DefaultLang'] = 'ru'; $cfg['ServerDefault'] = 1; $cfg['UploadDir'] = ''; $cfg['SaveDir'] = ''; /* Servers configuration */ $i = 0; /* Server: localhost [1] */ $i++; $cfg['Servers'][$i]['verbose'] = 'localhost'; $cfg['Servers'][$i]['host'] = 'localhost'; $cfg['Servers'][$i]['port'] = 3306; $cfg['Servers'][$i]['socket'] = ''; $cfg['Servers'][$i]['auth_type'] = 'cookie'; /* End of servers configuration */ ?>
Параметр $cfg[‘blowfish_secret’] генерируется автоматически и очень важен для защиты.
После создания файла конфигурации Вы можете зайти на http://phpmyadmin.myorg.ru/ и авторизоваться введя данные пользователя MySQL.
Так же я настоятельно рекомендую настроить HTTPS для нашего поддомена phpmyadmin.myorg.ru, но эту тему я оставляю на Вашей совести. Про правильную настройку HTTPS на Nginx я расскажу в отдельной статье.
8. Установка и настройка Pure-FTPd
Теперь установим и настроим ftp-сервер Pure-FTPd.
apt-get -y install pure-ftpd
В качестве базы хранения пользователей мы будем использовать локальную базу Pure-FTPd.
Для начала отключим авторизацию по системный учетным записям через подсистему PAM, для этого остановим Pure-FTPd и выполним ряд команд:
/etc/init.d/pure-ftpd stop unlink /etc/pure-ftpd/auth/70pam rm -f /etc/pure-ftpd/conf/PAMAuthentication ln -s /etc/pure-ftpd/conf/PureDB /etc/pure-ftpd/auth/45puredb
Настроим некоторые полезные опции Pure-FTPd:
1. Запретим анонимный вход;
2. Включим поддержку chroot, это значит, что пользователь будет ограничен своим домашним каталогом и не сможет перейти выше уровнем;
3. Включим расширенное ведение логов;
4. Оставим поддержку только IPv4;
5. Увеличим максимальное число клиентов до 100;
6. Разрешим отображение в директориях файлов начинающихся с точки;
7. Определим список пассивных портов;
8. Зададим кодировку по умолчанию;
9. Увеличим лимиты на количество отображаемых в директориях файлов и глубину вложенности;
echo "yes" > /etc/pure-ftpd/conf/NoAnonymous echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone echo "yes" > /etc/pure-ftpd/conf/VerboseLog echo "yes" > /etc/pure-ftpd/conf/IPV4Only echo "100" > /etc/pure-ftpd/conf/MaxClientsNumber echo "yes" > /etc/pure-ftpd/conf/DisplayDotFiles echo "yes" > /etc/pure-ftpd/conf/DontResolve echo "40110 40210" > /etc/pure-ftpd/conf/PassivePortRange echo "UTF-8" > /etc/pure-ftpd/conf/FSCharset echo "5000 500" > /etc/pure-ftpd/conf/LimitRecursion
Запустим Pure-FTPd:
/etc/init.d/pure-ftpd start
Проверим, что демон pure-ftpd запустился:
# ps -auxw | grep [p]ure-ftpd root 6220 0.0 0.1 28316 3456 ? Ss Aug19 0:18 pure-ftpd (SERVER)
Посмотрим список открытых портов:
# netstat -ltupn | grep pure-ftpd tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 6220/pure-ftpd (SER
Отлично, Pure-FTPd работает.
Теперь можно добавить виртуального пользователя (логин mysite):
pure-pw useradd mysite -u web1 -g client1 -d /var/www/mysite.ru
В опции -u мы указали UID нашего виртуального пользователя, он должен соответствовать UID реального пользователя имеющего право на чтение и запись в домашний каталог.
В опции -g мы указывается GID нашего виртуального пользователя, он должен так же должен соответствовать GID реальной группы.
В опции -d мы указали домашний каталог нашего виртуального пользователя, он должен соответствовать корневому каталогу нашей площадки для сайта mysite.ru в которой располагаются каталог web, log, private и tmp.
При первом запуске данная команда создает базу пользователей, а после любых операций с пользователями — обновляет (не забывайте ее запускать каждый раз):
pure-pw mkdb
Чтобы избежать использования команды ‘pure-pw mkdb’ после каждого изменения данных я рекомендую использовать опцию ‘-m’ в командах модификации. Ниже Вы увидите ее в примерах.
Просмотрим список пользователей:
pure-pw list
Для просмотра подробной информации о пользователе mysite выполним:
pure-pw show mysite
Результат:
Login : mysite Password : $6$MRCbtVpkmo94lpS0$mFPvkoHD/RZ5kl7xrKZtS/aG8OIbaoue.DHoapX9wt54K1/u8KqehHoSAOrWs/Lq8HAilZnbc58U3FLuq3TqK1 UID : 1001 (web1) GID : 1002 (client1) Directory : /var/www/mysite.ru/./ Full name : Download bandwidth : 0 Kb (unlimited) Upload bandwidth : 0 Kb (unlimited) Max files : 0 (unlimited) Max size : 0 Mb (unlimited) Ratio : 0:0 (unlimited:unlimited) Allowed local IPs : Denied local IPs : Allowed client IPs : Denied client IPs : Time restrictions : 0000-0000 (unlimited) Max sim sessions : 0 (unlimited)
Мы видим, что у пользователя есть много различных настроек, например мы можем задать лимиты на загрузку файлов, ограничения на подключение по времени или по количеству одновременных сессий и т.д.
Для смены пароля пользователя mysite выполните:
pure-pw passwd mysite -m
Для смены домашней директории пользователя mysite выполните:
pure-pw usermod mysite -d /var/www/mysite.ru/web -m
Для удаления пользователя mysite выполните:
pure-pw userdel mysite -m
Pure-FTPd пишет логи в файл /var/log/messages, поэтому для просмотра логов нужно отфильтровать их по слову pure-ftpd, например так:
tail -f /var/log/messages | grep pure-ftpd
Расширенный лог пишется в файл /var/log/pure-ftpd/transfer.log, в нем можно посмотреть кто, когда и какие операции выполнял после прохождения аутентификации. Сами попытки аутентификации (удачные и не удачные) нужно смотреть в файле /var/log/messages
Вопрос включения TLS и некоторых других интересных опций я рассмотрю в отдельной небольшой статье.
На этом все, до скорых встреч. Если у Вас возникли вопросы или Вы хотите чтобы я помог Вам, то Вы всегда можете связаться со мной разными доступными способами.
Профессионально занимаюсь системным администрированием Linux -серверов и баз данных (MySQL, PostgreSQL) на протяжении последних 24 лет.
Доброго времени суток.
Спасибо за ваши статьи )
P.s.
sed -i «s/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/» /etc/php/7.0/fpm/php.ini и другие можно сократить:
sed -i -e ‘s/;(\cgi.fix_pathinfo\)/\1=0/’ /etc/php/7.0/fpm/php.ini
Проверяю тут https://www.shellcheck.net/
Добрый.
echo «vnoremap :w !xsel -b» >> ~/.vimrc не работает.
echo ‘vnoremap :w !xsel -b’ >> ~/.vimrc работает
Да, все верно. Спасибо, исправил в статье. У меня там вообще была неправильная строка.
Ссылка «размещены у меня на github.com» не работает.
Спасибо, что написали. Ссылку исправил.
Выдает ошибку,всю голову сломал.
root@c4:/home/linux-scripts-master/nginx# ./nginx-create-vhost.sh -d test.de
Detecting your OS Linux (x86_64)
Detecting Linux distrib Debian (SYSTEMD)
Detecting your php-fpm Found php-fpm7.0
Detecting nginx owner Found www-data
Error: In file /etc/nginx/settings.conf not found parameter NEXTWEBUSER.
Usage: ./nginx-create-vhost.sh [ -d domain_name -s site_directory -u user_name -g group_name]
-d sitename : Domain name, domain.com
-s sitedir : Site directory, /var/www/domain.com
-u username : User name, www-data
-g group : Group name, www-data
-h : Print this screen
root@c4:/home/linux-scripts-master/nginx#
Проверьте наличие файла /etc/nginx/settings.conf, его содержимое при создании первого хостингового домена должно быть примерно такое
SERVERIP=XX.XX.XX.XX
SERVERPORT=80
NEXTWEBUSER=web1
NEXTWEBGROUP=client1
Вообще этот файл создается автоматически при первом запуске скрипта, возможно вы изменили файл руками, что не следует делать. (особенно менять NEXTWEBUSER и NEXTWEBGROUP)
Михаил, огромное спасибо за ваши статьи!
Человеку, только ставшему на пусть изучения данного направления они крайне полезны и экономят уйму нервов.
Михаил добрый день!
Очень хорошо расписываете все шаги, интересно читать!
Ждем пока доберетесь до — Про правильную настройку HTTPS на Nginx я расскажу в отдельной статье.
Спасибо!
Помогли в решении моей задачи
Извините за дилетантский вопрос, но почему на папку web не поставить права 750, вместо 755, чтобы вообще никто кроме нужного пользователя и сервера (который в соотв. группе) не мог там ничего просматривать? Чему помешают права 750?
Можно поставить 750, так будет безопаснее. Сломаться ничего не должно.
Спасибо.