expires в nginx: как настроить кэш браузера
Директива expires добавляет к ответу заголовки Expires и Cache-Control: браузер сохраняет файл и до конца срока не запрашивает его заново. Ставят её для стилей, скриптов и картинок, а страницам HTML долгий срок не задают.
Содержание 10
Что сделать прямо сейчас
- Команды вводятся на сервере: подключитесь к нему по SSH ([как подключиться](/instrukcii/kak-podklyuchitsya-k-vps-po-ssh/)) и набирайте их в том же окне.
- Откройте файл сайта:
sudo nano /etc/nginx/sites-available/example.com. Вместо example.com — имя файла вашего сайта: список покажетls /etc/nginx/sites-enabled/. Если система спросит пароль, введите пароль своего пользователя на сервере. Символы при вводе не видны — наберите пароль и нажмите Enter. - Найдите в файле строку root: Ctrl+W, слово
root, Enter. Сразу после неё, внутри блока server, добавьте блок для стилей, скриптов и картинок. - Сохраните файл — Ctrl+O, Enter, затем Ctrl+X — и проверьте настройки:
sudo nginx -t. В ответе должны быть слова syntax is ok и test is successful. Тогда примените их:sudo systemctl reload nginx. Если команда ничего не ответила, настройки применены. - Проверьте заголовки — как это сделать.
Если проверка нашла ошибку, nginx назовёт файл и номер строки, а сайт продолжит работать на старых настройках. Что значит сообщение — Все ошибки nginx.
Блок для стилей, скриптов и картинок
location ~* \.(css|js|png|jpe?g|webp|gif|svg|ico|woff2)$ {
expires 30d;
}Знак ~* значит: регулярное выражение без учёта регистра букв, подойдут и .PNG, и .png. Блок срабатывает на адреса, которые кончаются этими расширениями. 30d — 30 дней. Как nginx выбирает между этим блоком и location / — location в nginx.
Файлы в этом блоке nginx берёт из папки, указанной в root. Если файла нет, nginx ответит 404 и не передаст запрос ни в index.php, ни приложению.
Если картинки и стили отдаёт приложение через proxy_pass, а в папке из root их нет, этот блок не подойдёт: на них начнётся 404. Тогда напишите строку expires 30d; в том блоке location, через который идут эти файлы, например location /static/. В location / её не пишите — срок получат и страницы.
Если в файле уже есть блок location с регулярным выражением для этих расширений, второй не добавляйте — допишите expires в существующий. Из двух подходящих регулярных выражений nginx берёт первое по порядку в файле.
Что значат значения expires
| Строка | Что получит браузер |
|---|---|
expires 30d; | Cache-Control: max-age=2592000 — 30 дней в секундах — и Expires с датой через 30 дней |
expires 12h; | Cache-Control: max-age=43200 — 12 часов |
expires max; | Cache-Control: max-age=315360000 — 10 лет — и Expires: Thu, 31 Dec 2037 23:55:55 GMT |
expires 0; | Cache-Control: max-age=0 — срок хранения ноль |
expires -1; | Cache-Control: no-cache и Expires в прошлом |
expires epoch; | Cache-Control: no-cache и Expires: Thu, 01 Jan 1970 00:00:01 GMT |
expires off; | nginx не трогает эти заголовки — так по умолчанию |
max-age — сколько секунд браузер может брать файл из своей копии, не спрашивая сервер. no-cache — копию хранить можно, но перед каждым показом браузер проверяет у сервера, не изменился ли файл.
Время пишут числом с буквой: s — секунды, m — минуты, h — часы, d — дни, w — недели, M — месяцы по 30 дней, y — годы по 365 дней. Регистр важен: m — минуты, M — месяцы.
Если приложение за proxy_pass само прислало Cache-Control, expires заменит его своим значением.
Какие ответы получают срок
nginx добавляет Expires и Cache-Control только к ответам с кодами 200, 201, 204, 206, 301, 302, 303, 304, 307 и 308. К страницам ошибок — 404, 403, 500 — срок не добавится.
Где писать expires
expires можно писать в блоках http, server, location и в if внутри location. Строка из блока server действует во всех его блоках location, где нет своей строки expires.
Поэтому в server её лучше не ставить: долгий срок получат и страницы HTML, и посетители не увидят изменений на сайте, пока срок не кончится. Пишите expires в отдельном location для файлов, как в примере выше.
Что делать после обновления файлов
Пока срок не кончился, браузер берёт файл из своей копии: посетитель может видеть старые стили. Поэтому при изменении файла меняют его адрес в ссылке на странице: добавляют номер версии — style.css?v=2 вместо style.css?v=1 — или переименовывают файл.
Для браузера это новый адрес, и он скачает файл заново. nginx отдаст тот же файл: часть адреса после знака ? при поиске файла не учитывается.
Как проверить
Вместо адреса — адрес картинки или файла стилей с вашего сайта:
curl -sI 'https://example.com/css/style.css' | grep -i 'cache-control\|expires'Для expires 30d в ответе будут строки Cache-Control: max-age=2592000 и Expires с датой. curl может показать имена заголовков маленькими буквами — это то же самое. Если строк нет, запрос не попал в блок с expires: проверьте расширение файла в списке и что после правки был reload.
Что ещё умеет curl — команды wget и curl.
Ошибки и как их исправить
| Что видите | Что делать |
|---|---|
| после правки картинки или стили отвечают 404 | их отдаёт приложение, а не nginx с диска — что делать |
| посетители видят старые стили | поменяйте адрес файла — как |
"expires" directive invalid value | ошибка в значении: число и буква пишутся вместе, без пробела, например 30d |
"expires" directive is duplicate | в одном блоке две строки expires: оставьте одну |
| страницы сайта не обновляются у посетителей | expires стоит в блоке server или location /: перенесите его в блок для файлов |
Источники
- Документация nginx: expires — поля Expires и Cache-Control, коды ответа, параметры epoch, max, off и modified, отрицательное время.
- Исходный код nginx 1.24.0: ngx_http_headers_filter_module.c — max даёт max-age=315360000, epoch и отрицательное время — no-cache, 0 — max-age=0; expires заменяет Cache-Control из ответа приложения и переходит во внутренние блоки без своей строки.
- Исходный код nginx 1.24.0: ngx_parse.c — единицы времени: s, m, h, d, w, M — 30 дней, y — 365 дней.
- Документация nginx: location — ~* — регулярное выражение без учёта регистра; регулярные выражения проверяются по порядку в файле, первое совпавшее выбирается.
- RFC 9111: HTTP Caching, раздел 5.2 — что значат max-age, no-cache и no-store в Cache-Control.
Сверено 14 октября 2026 года.
Что почитать дальше
- Настройки nginxкак устроены файлы и блоки, главные директивы.
- gzip в nginxкак включить сжатие стилей и скриптов.
- add_header в nginxкак добавить свой заголовок к ответу.
- location в nginxкак выбирается блок для адреса.
- Команды wget и curlкак смотреть заголовки ответа командой curl -I.