Рабочие заметки

Немного тише: настройка логов nginx

На маленьком сервере access.log однажды занял больше, чем всё остальное вместе. Виноват был не трафик, а боты: сканеры перебирают /wp-login.php и три тысячи его вариаций круглые сутки.

Не логировать статику

Самое дешёвое действие. Картинки и css не несут никакой информации в логе:

location ~* \.(css|js|png|jpg|jpeg|gif|svg|woff2?|ico)$ {
    access_log off;
    expires 30d;
    add_header Cache-Control "public, immutable";
}

Условное логирование

Директива map позволяет выкинуть заведомо неинтересное, не трогая всё остальное:

map $status $loggable {
    ~^[23]  0;   # 2xx и 3xx не пишем
    default 1;
}

map $http_user_agent $is_probe {
    default                  0;
    "~*(nmap|masscan|zgrab)" 1;
}

access_log /var/log/nginx/access.log combined if=$loggable;

Оговорка: выкидывать все 2xx стоит только там, где логи не нужны для аналитики. На сайте с посещаемостью так делать не надо — лучше уменьшить формат.

Свой формат вместо combined

combined тащит referer и полный user-agent — вместе это половина строки. Если они не нужны, короткий формат экономит заметно:

log_format slim '$remote_addr $status $request_method '
                '$uri $body_bytes_sent $request_time';

access_log /var/log/nginx/access.log slim buffer=32k flush=5s;

buffer и flush — отдельная приятность: nginx перестаёт дёргать диск на каждый запрос.

Ротация

logrotate есть по умолчанию, но настройки стоит пересмотреть — недельного хранения обычно мало, а сжатия нет:

# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        [ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
    endscript
}

kill -USR1 обязателен: без него nginx продолжит писать в уже переименованный файл, и место не освободится до перезапуска.

Итог

После всего этого access.log уменьшился примерно в семь раз, и в нём наконец стало видно реальные ошибки — раньше они тонули между попытками найти админку WordPress, которого на сервере никогда не было.


← ко всем записям