• Авторизация


LINUX: настройка нового web-сервера с нуля 19-02-2017 17:46 к комментариям - к полной версии - понравилось!


Довольно часто появляются задаче по полной настройке и оптимизации web-серверов. Как правило, это физические сервера с хорошими характеристиками. В данном посте я скомпоновал весь свой опыт по начальной настройке. На правильность эти действия ни коем образом не претендуют. Быть может надо делать как-то иначе и будет лучше... Я просто напишу как делаю я.

Далее всё будет относится к операционной системе Ubuntu 18.04. На других Убунтах и Дебианах инструкции будут аналогичные.

При установке Убунту можно нажать F4 и выбрать там Install minimal system. Нам ведь не нужен мусор из стандартного дистрибутива вроде lxc или python3?
Устанавливаем операционную систему.

После установки прежде всего обновим информацию о репозиториях и далее обновим все пакеты.
apt-get update
apt-get upgrade
apt-get autoremove

Отредактируем файл /etc/default/grub так чтобы в нём присутствовала такая строчка:
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
Это нужно для ускорения работы docker, а быть может и других программ. Далее нужно обновить GRUB:
update-grub
Подробности того зачем это надо можно найти тут: https://askubuntu.com/questions/417215/how-does-kernel-support-swap-limit

Убунта могла обновить ядро, поэтому на всякий случай перезагружаемся:
shutdown -r now

В будущем обновлять ядро я категорически не рекомендую. А пока сервер пустой, мы ничем не рискуем.

После перезагрузки установим кое-какие пакеты, чтобы можно было по человечески работать с системой:
apt-get install nano mc htop iftop
nano - консольный текстовый редактор
mc - файловый менеджер "для людей"
htop - красивое отображение текущей ситуации на сервере (процессоры, память, запущеные приложения)
iftop - мониторинг трафика

Далее я всё делаю через mc. Гуляю по папкам, вношу изменения. Если надо набрать консольные команды, то жму Ctrl + O и всё делаю. Обратно в mc - тоже Ctrl + O. Если нужно отредактировать файл - жму F4. Чтение - F3. Сохранение - F2. Выход из файла - два раза ESCAPE. Всё там просто и классно! Для того чтобы мне было удобно я ещё настраиваю это. Далее лучше перезайти на сервер по своему SSH. Я считаю, что новичкам тоже лучше всё делать через mc. Иначе ты не видишь систему с которой работаешь.

Также рекомендую повесить SSH на какой-нибудь другой порт, потому что по 22 обычно ломятся китайцы. Инструкции описаны, например, тут. После смены порта желательно проделать и это:

"Данное правило ограничивает больше 20-ти подключение к 80 порту(web) за 15 секунд с 1 ip адреса.
(кстати, подобное правило есть на уровне nginx, но сжирает огромное количество ресурсов)":
iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 15 --hitcount 20 -j DROP

"Правило ограничивает количество подключений к SSH, не более 4-х подключений за 1 минуту":
iptables -A INPUT -p tcp --dport 354 -i eth0 -m state --state NEW -m recent --set
iptables -A INPUT -p tcp --dport 354 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 -j DROP
"Где 354 порт вашего ssh сервера. На деле у меня не получалось авторизовать более 1 раза за минуту. Далее это правило вы дальше можете адаптировать под себя и другие сервисы."

Добавляем правила для запрета Simple Service Discovery Protocol (SSDP) чтобы датацентр не просил нас это сделать в будущем. Также блокируем все порты кроме тех что нам нужны (в этом примере открываем только порт 22):
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -j DROP
-A INPUT -i eth0 -p tcp -m tcp --dport 1900 -j DROP
-A INPUT -i eth0 -p udp -m udp --dport 1900 -j DROP
-A FORWARD -i eth0 -p tcp --dport 22 -j ACCEPT
-A FORWARD -i eth0 -j DROP
-A FORWARD -i eth0 -p tcp -m tcp --dport 1900 -j DROP
-A FORWARD -i eth0 -p udp -m udp --dport 1900 -j DROP
-A OUTPUT -s 234.165.140.130/32 -p tcp -m tcp --sport 1900 -j DROP
-A OUTPUT -s 234.165.140.130/32 -p udp -m udp --sport 1900 -j DROP
Где 234.165.140.130 - это IP адрес вашего сервера в интернете.

Или так:
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i eth0 -p tcp -m tcp -m multiport --dports 22 -j ACCEPT
-A INPUT -i eth0 -m conntrack -j ACCEPT --ctstate RELATED,ESTABLISHED
-A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i eth0 -j DROP
-A OUTPUT -s 234.165.140.130/32 -p tcp -m tcp --sport 1900 -j DROP
-A OUTPUT -s 234.165.140.130/32 -p udp -m udp --sport 1900 -j DROP
-A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
-A FORWARD -i eth0 -j DROP

После рестарта системы все правила обнулятся, по этому делаем следующее:
apt-get install ifupdown

Далее создаем и редактируем файл /etc/network/if-up.d/00-iptables
nano -w /etc/network/if-up.d/00-iptables

Пишем в него:
#!/bin/sh
iptables-restore < /etc/firewall.conf

сохраняем и делаем файл исполняемым:
chmod +x /etc/network/if-up.d/00-iptables

Сохраняем правила в файл:
iptables-save | sudo tee /etc/firewall.conf

Всё, правила настроены и сохранятся после перезагрузки системы."

Вместо ручной правки iptables можно использовать fail2ban.

Синхронизируем время:
apt-get install ntpdate
crontab -e
И прописываем в crontab:
* */4 * * * ntpdate 2.de.pool.ntp.org
Можно было бы выбрать более удачный сервер времени, но мне влом их искать. Всё работает надёжно.

"Ускоряем общую работу системы. Prelink и Preload. Prelink - для создание статичных адресов библиотек, Preload - это небольшое приложение, которое следит за файлами наиболее часто используемых приложений, и загружает их в память, когда система простаивает.
Установка Prelink:
apt-get -y install prelink

Редактируем файл /etc/default/prelink:
nano /etc/default/prelink

Измените строку с PRELINKING=unknown на PRELINKING=yes
Запускаем:
/etc/cron.daily/prelink

Установка Preload:
apt-get -y install preload"
Информация взята из этой статьи.

Предлагаю перенести /tmp в оперативную память. В статье по ссылки изложены предпосылки и результаты такого переноса. Делается так:
echo "tmpfs /tmp tmpfs size=8G,rw,nosuid,nodev 0 0" | tee -a /etc/fstab
reboot
UPD: теперь я думаю, что переносить /tmp в оперативку не надо. Можно разок положить туда большой файл и положить сервер. Смысла в этом нет особо, потому что папка в памяти уже есть и она называется /dev/shm - это обычная папка не смотря на то, что лежит в /dev.

Далее я отключаю различные лимиты. При отключении лимитов сервер может "жестко упасть", в случае бага в программах. Например, программа съест всю память. Но, при таких настройках сервер сможет держать наверняка более высокую нагрузку. Вот что я прописываю в файл /etc/security/limits.conf:

# Disable all limits for root
root - core 0
root - nofile 1048576
root - memlock unlimited
root - fsize unlimited
root - data unlimited
root - rss unlimited
root - stack unlimited
root - cpu unlimited
root - nproc unlimited
root - as unlimited
root - locks unlimited
root - sigpending unlimited
root - msgqueue unlimited

# Disable all limits for other users
* - core 0
* - nofile 1048576
* - memlock unlimited
* - fsize unlimited
* - data unlimited
* - rss unlimited
* - stack unlimited
* - cpu unlimited
* - nproc unlimited
* - as unlimited
* - locks unlimited
* - sigpending unlimited
* - msgqueue unlimited

Как видите, у меня параметр core равен нулю, чтобы система не какала core-dump'ами при сбоях какого-нибудь php. Всё остальное фактически без ограничений.

Теперь необходимо оптимизировать ядро через /etc/sysctl.conf. Есть масса альтернативных конфигов этого файла и споры на эту тему. Вот некоторые примеры.

Cтатья про оптимизацию ядра: https://gist.github.com/kgriffs/4027835
И вот это для VDS: https://habrahabr.ru/post/186362/
А ещё вот (проверено Яндекс.Танком): https://www.prolinux.org/post/nastroyki-nagruzhennogo-servera/
Вот здесь лимиты отключают вообще: https://tobert.github.io/post/2014-06-24-linux-defaults.html

Описание параметров sysctl.conf на русском языке есть тут:
http://adminunix.ru/nastrojka-sysctl/
и тут
https://nikitushkin.wordpress.com/2011/02/12/%D0%B...D0%BF%D1%80%D0%B0%D0%B2%D0%BB/

Активнее выгружаем неиспользуемые страницы из кеша.
vm.vfs_cache_pressure = 1000
Иначе кеш сожрёт всю память и этого не будет видно ни одной тулзой! Подробности тут. Чтобы освободить память нужно сделать это:
sync
echo 3 > /proc/sys/vm/drop_caches

Также на свой страх и риск можно добавить это:
"После этого стоит настроить отложенную запись — ядро будет копить данные, ожидающие записи на диск, и записывать их либо при острой необходимости, либо по истечении таймаута. Я ставлю таймаут на 60 секунд, кто-то — на 150.
Для этого открываем /etc/sysctl.conf и добавляем параметры
vm.laptop_mode = 5 // Включение режима
vm.dirty_writeback_centisecs = 6000 время в сСк. Т.е. 100ед = 1 секунда"
Источник: статья на хабре.

Я использовал конфиг по первой ссылке. Его надо прописать целиком в /etc/sysctl.conf. Позже можно протестировать свою систему в других конфигурациях. Можно всё изучить и так будет лучше, но тема большая. В целом мой конфиг /etc/sysctl.conf выглядит так:

#
# Из статьи: https://www.prolinux.org/post/nastroyki-nagruzhennogo-servera/
#
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
kernel.sysrq = 0
net.ipv4.tcp_syncookies = 0
kernel.msgmnb = 65536
kernel.msgmax = 65536
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
vm.swappiness = 0
net.ipv4.tcp_fack = 1
net.ipv4.tcp_sack = 1
net.ipv4.tcp_mem = 8388608 12582912 16777216
net.ipv4.udp_mem = 8388608 12582912 16777216
net.ipv4.udp_rmem_min = 16384
net.ipv4.udp_wmem_min = 16384
net.core.wmem_max = 8388608
net.core.rmem_max = 8388608
net.ipv4.tcp_rmem = 8192 87380 8388608
net.ipv4.tcp_wmem = 8192 87380 8388608
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_window_scaling = 1
net.core.somaxconn = 300000
net.core.netdev_max_backlog = 8192
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_keepalive_time = 180
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_max_tw_buckets = 1000000
net.ipv4.ip_local_port_range = 1024 65535
net.nf_conntrack_max = 1000000

#
# Отложенная запись — ядро будет копить данные, ожидающие записи на диск, и записывать их либо при острой необходимости, либо по истечении таймаута.
# Я ставлю таймаут на 60 секунд, кто-то — на 150.
#
vm.laptop_mode = 5 # включение режима
vm.dirty_writeback_centisecs = 6000 # время: 100 ед. = 1 секунда

#
# Lines, as recommended by the LXD project
#
fs.inotify.max_queued_events = 1048576
fs.inotify.max_user_instances = 1048576
fs.inotify.max_user_watches = 1048576

#
# Активнее выгружаем неиспользуемые страницы из кеша: https://blog.poiuty.com/dopolnitelnye-nastrojki-sysctl-conf.html
#
vm.vfs_cache_pressure = 10000

#
# Настройка для Redis
#
vm.overcommit_memory = 1

#
# Перезагрузка при обнаружении kernel panic
#
kernel.core_pattern = /var/crash/core.%t.%p
kernel.panic = 20
kernel.unknown_nmi_panic = 1

Примерняем настройки из конфгиа без перезагрузки:
sysctl --system

Включить rc.local в Ubuntu 18.04 можно так:
https://askubuntu.com/questions/886620/how-can-i-execute-command-on-startup-rc-local-alternative-on-ubuntu-16-10
Для нормальной работы Percona и Redis надо добавить эту строчку в rc.local:
echo never > /sys/kernel/mm/transparent_hugepage/enabled

Установим nginx:
apt-get install nginx

Теперь можно настроить nginx. Инфы об этом дофига. Можно воспользоваться этой информацией к примеру. Мой конфиг /etc/nginx/nginx.conf выглядит так.

Установим всё необходимое для php 7:
apt-get install php-fpm php-common php-cli
Тут надо убедиться, что никаких сраных Апачей нам не установится.
Если нужна более старая версия PHP, то придётся использовать неоффициальные пакеты для этого. Способ установки php 5.6 описан тут.

Конфигурировать php-fpm можно так. Но я использовал рекомендации из статьи выше.

Для php7 также необходимо установить кучу расширений:
apt-get install php-geoip php-curl php-gd php-intl php-mysql php-tidy php-opcache php-json php-mcrypt php-bz2 php-readline php-xsl php-memcache php-bcmath php-mbstring php-xml php-zip php-memcached

Если бы это нужно было сделать версии 5.6, то было бы так:
apt-get install php-geoip php5.6-curl php5.6-gd php5.6-intl php5.6-mysql php5.6-tidy php5.6-opcache php5.6-json php5.6-mcrypt php5.6-bz2 php5.6-readline php5.6-xsl php-memcache php5.6-bcmath php5.6-mbstring php5.6-xml php5.6-zip php-memcached

Внимание! PHP в целом является весьма хреновым средством с точки зрения безопасности. Настраивать конфиги php.ini нужно вдумчиво, всё тщательно взвесив. Например, желательно отключить загрузку файлов, если она не используется в вашем проекте. Описание многих лазеек для хакеров и мер предосторожности можно начать читать тут: https://www.cyberciti.biz/tips/php-security-best-practices-tutorial.html Когда я был наивным и не "битым", то думал что эти страхи преувеличены - я сильно ошибался.

Установим geoip:
apt-get install php-geoip geoip-database-contrib

Настраивать тут ничего не нужно. Разве что в php.ini в нужном месте прописать настройку для browscap:
[browscap]
; http://php.net/browscap
browscap = /etc/php/7.0/modules-available/php_browscap.ini

Тут путь должен быть другим - туда где у вас на самом деле лежит php_browscap.ini. Сам этот файл можно взять например тут.

Установим memached:
apt-get install memcached
Настроить его можно в файле /etc/memcached.conf. Посмотрите этот файл и сами всё поймёте. Он элементарный.

Теперь ставим БД. Для всех любителей mysql я настоятельно рекомендую не использовать стандартную реализацию этой СУБД. Вместо неё используем Percona. Будет ровно тоже самое, но с выигрышем по скорости.

UPD: Percona 8.0 ставится так: https://www.percona.com/doc/percona-server/8.0/installation/apt_repo.html
(то что написано дальше про установку Percona не актуально)

Следующие команды установят Percona:

cd /tmp
wget https://repo.percona.com/apt/percona-release_0.1-4.$(lsb_release -sc)_all.deb
dpkg -i percona-release_0.1-4.$(lsb_release -sc)_all.deb
apt-get update
apt-get install percona-server-server-5.7

mysql -u root -e "CREATE FUNCTION fnv_64 RETURNS INTEGER SONAME 'libfnv_udf.so'"
mysql -u root -p -e "CREATE FUNCTION fnv_64 RETURNS INTEGER SONAME 'libfnv_udf.so'"
mysql -u root -p -e "CREATE FUNCTION murmur_hash RETURNS INTEGER SONAME 'libmurmur_udf.so'"

Расшифровка установки Percona тут.

Далее можно настроить её:
При настройке mysql / percona мы должны помнить об этом:
http://rimzy.net/category/mysql-5-7/
http://stackoverflow.com/questions/10905226/mysql-...ormance-tuning-recommendations
http://stackoverflow.com/questions/30901041/can-no...l-max-connections-in-ubuntu-15

Мой файл /etc/mysql/percona-server.conf.d/mysqld.cnf выглядит так:

#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html

[mysqld]
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
explicit_defaults_for_timestamp

local-infile = 0

# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1

# Recommended in standard MySQL setup
#sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_ALL_TABLES

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links = 1

# GENERAL #
default-storage-engine = InnoDB

# MyISAM #
key-buffer-size = 96M
#myisam-recover = FORCE,BACKUP

# SAFETY #
max-allowed-packet = 16M
max-connect-errors = 1000000
sysdate-is-now = 1
innodb = FORCE

# CACHES AND LIMITS #
tmp-table-size = 32M
max-heap-table-size = 32M
query-cache-type = 0
query-cache-size = 0
max-connections = 500
thread-cache-size = 50
open-files-limit = 65535
table-definition-cache = 1024
table-open-cache = 2048

# INNODB #
innodb-flush-method = O_DSYNC
innodb-log-files-in-group = 2
innodb-log-file-size = 512M
innodb-flush-log-at-trx-commit = 2
innodb-file-per-table = 1
innodb-buffer-pool-size = 32G

# LOGGING #
log-error = /var/log/mysql/error.log
log-queries-not-using-indexes = 0
slow-query-log = 0
#slow-query-log-file = /var/log/mysql/slow.log

Создал я его с помощью визарда на сайте Percona, где можно подобрать параметры под разные сервера из задачи. Бинлоги в этой конфигурации отключены!

Теперь надо устранить один косяк СУБД. Вот так:

cp /lib/systemd/system/mysql.service /etc/systemd/system/

Add the following lines to the bottom of the file /etc/systemd/system/mysql.service:
LimitNOFILE=infinity
LimitMEMLOCK=infinity

Now reload the Systemd configuration with:
systemctl daemon-reload

Подробности того зачем это надо были в одной из ссылок выше.

С оптимизацией на этом всё. Теперь нужно тестировать всё это хозяйство и мониторить. Например, с помощью Яндекс.Танка.
вверх^ к полной версии понравилось! в evernote


Вы сейчас не можете прокомментировать это сообщение.

Дневник LINUX: настройка нового web-сервера с нуля | eugene20237 - Дневник eugene20237 | Лента друзей eugene20237 / Полная версия Добавить в друзья Страницы: раньше»