Обновить
32K+

Nginx *

Веб-сервер и почтовый прокси-сервер

27,31
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Деплой-платформа для MCP-серверов и сайтов, встроенная в каталог

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели7.6K

Недавно я писал на Хабре, как собрал каталог MCP-серверов: 80 тысяч записей из девяти источников в одном индексе. В комментариях и в личке быстро всплыл вопрос, который я сам не до конца продумал, когда делал каталог: «нашёл сервер, а запускать его где?»

С MCP-серверами беда в том, что добрая половина живёт не как готовый npm-пакет, а как репозиторий на GitHub. Его надо склонировать, поставить зависимости, собрать, запустить и держать живым. Если сервер stdio (а таких большинство), сверху ещё задача обернуть его в HTTP, иначе к нему не подключится ни claude.ai, ни ChatGPT. Итог: под сервер на 40 строк человек поднимает VPS, пишет Dockerfile, настраивает nginx, выпускает сертификат и вешает вебхук на автодеплой. Дизбаланс усилий чудовищный.

Поэтому я сделал внутри Unyly полноценный раздел деплоя. Подключаешь GitHub-репозиторий, на выходе получаешь работающий проект на slug.unyly.org, пуш в ветку пересобирает его сам. Работает и для сайтов (статика, фронтенд-сборки, Next.js), и для MCP-серверов на Node и Python. Ниже разберу архитектуру по слоям и честно перечислю грабли, на которых потерял время.

Читать далее

Новости

Use-As-Dictionary: как мы перестали отдавать один и тот же бандл по пять раз в день

Уровень сложностиПростой
Время на прочтение14 мин
Охват и читатели4.9K

У нас в среднем два релиза в день, бандл весит 7,76 МиБ после brotli, и половина клиентов качает его заново по несколько раз в сутки: хеш в имени файла поменялся - значит, кеш мимо. Compression Dictionary Transport (RFC 9842) позволяет объявить вчерашнюю сборку словарём для сегодняшней, и вместо 7,76 МиБ уезжает 15 КБ.

Рассказываю, что из этого работает на практике при непрерывной поставке: почему дельты только к предыдущей сборке хватает лишь на 43% визитов, как считать окно словарей по своим логам, как отдавать дельты из nginx без reload на каждый релиз, и что ломается на откатах, канарейках и бампах зависимостей. Все цифры - с нашего портала, методика в конце.

Читать далее

Приложение течёт, а утечки нет: как оптимизатор картинок Next.js съел 4-гигабайтный VPS

Уровень сложностиСредний
Время на прочтение7 мин
Охват и читатели8.6K

История про то, как я три дня искал утечку памяти в Node-приложении, не нашёл — и был прав, что не нашёл. А ещё про то, что у каждого починенного пункта тут оказывался свой счёт: фикс памяти через месяц вернулся жалобой на скорость, а разбор скорости вскрыл третью проблему, о которой я не думал вовсе.

Читать далее

У nginx сжатие заголовков одностороннее

Уровень сложностиСложный
Время на прочтение24 мин
Охват и читатели9.4K

Стенд: один nginx, одно HTTP/3-соединение, четыре одинаковых запроса подряд. Меряем размер сжатого блока заголовков в обе стороны.

Ответ (nginx → клиент): 131, 131, 131, 131 байт. Запрос (клиент → nginx): 246, 8, 8, 8.

Ответ — константа: сколько запросов ни повтори, столько же байт. Запрос со второго раза схлопывается в тридцать раз. В HTTP/2 к тому же серверу — та же константа.

Между тем динамическая таблица HPACK и QPACK и есть половина смысла обоих протоколов: повторяющийся заголовок отправляется один раз, дальше идут ссылки на номер. Клиент ей пользуется. Сервер не пользуется ни в одном из двух — в HTTP/2 выставляет её размер в ноль, в HTTP/3 не открывает encoder-поток вовсе.

Разбор по фиксированным тегам: nginx 1.31.3, quic-go, Cloudflare quiche, ls-qpack, Google QUICHE. Две реализации из пяти таблицу всё-таки ведут. И приёмная половина — та, которой сервер сам не пользуется, но обязан обслуживать, — в мае принесла nginx use-after-free с оценкой 9.2.

Читать далее

nginx -s reload может не применить конфиг

Уровень сложностиСложный
Время на прочтение21 мин
Охват и читатели8.8K

Пока идёт бинарный апгрейд nginx, systemctl reload nginx не применяет конфиг так, как вы думаете: в лучшем случае к половине процессов сервера, в худшем — вообще никуда. Код возврата ноль в обоих случаях, в error.log пусто. Что именно у вас — решает одна строчка в юните: -s reload бьёт по pid-файлу, а он после USR2 принадлежит новому мастеру; kill -s HUP $MAINPID бьёт по старому, а тот конфиг вообще не перечитывает, и это описано в документации nginx — в разделе про обновление исполняемого файла, куда по другому поводу не заходят.

Это первая из пяти проверок. Я взял пять ходовых утверждений про reload в nginx, померил каждое на стенде — и получил результаты по обе стороны: три подтвердились, два развалились. Развалившиеся оказались интереснее.

Не работают ровно те страшилки, что про слушающий сокет: listen ... reuseport бесшовность не ломает (inode’ы сокетов до и после reload одни и те же — их держит мастер, а не воркер), паузы в accept при reload не существует вовсе (msleep(100) стоит ПЕРЕД QUIT), а значит и арифметика про переполнение backlog на reload — про нагрузку, а не про reload.

Зато подтвердилось то, о чём почти не пишут. keepalive_min_timeout оставляет уходящего воркера в живых, и тот обслуживает запросы, которых в момент reload ещё не существовало — по старому конфигу. А ngx_close_idle_connections не различает направление соединения, поэтому каждый reload сбрасывает пул keepalive к бэкендам — и с 1.29.7 это касается всех, у кого есть блок upstream: пул там включён по умолчанию, 32 соединения на воркер.

Правило из первой части — «соединение, открытое до reload, нового конфига не увидит» — приходится переформулировать: держится старого конфига не соединение, а процесс.

В конце — Traefik, у которого reload’а нет вовсе, и который умеет не применить конфиг своим способом: кольцевой буфер на одно сообщение и двухсекундный дроссель.

nginx release-1.31.3, traefik v3.7.10, все опыты в репозитории, запуск одной командой.

Читать далее

nginx не умеет reload. Он умеет fork

Уровень сложностиСложный
Время на прочтение17 мин
Охват и читатели13K

Деплой делает nginx -s reload. Команда возвращает ноль, nginx -T показывает новый конфиг, в error.log ровно одна строка — reconfiguring. А keep-alive соединение, открытое секундой раньше, в этот момент закрывается.

Само по себе это не ошибка: сервер вправе закрыть простаивающий keep-alive когда угодно. Ошибку даёт гонка — FIN уходит в тот момент, когда клиент уже записал в сокет следующий запрос. Идемпотентный он повторит, POST — нет.

Разбор по исходникам на фиксированных тегах: nginx release-1.31.3, httpd 2.4.68, traefik v3.7.10, плюс замер всех четырёх (с HAProxy) на одном стенде в одном прогоне. Выясняется, что мастер nginx конфиг не перечитывает вообще: он строит новый цикл целиком и форкает новых воркеров, а старым остаётся ровно то, что у них было. Apache приходит к тому же контракту через счётчик поколений, HAProxy — через замену процесса. А у одного из четырёх второй запрос в том же самом сокете возвращает уже новый конфиг — и причина не та, о которой вы подумали.

Внутри: почему документация nginx сама создаёт половину недоразумения; почему WebSocket и SSE не попадают под ngx_close_idle_connections и держат старого воркера сколько угодно долго, а HTTP/2 попадает всегда и получает GOAWAY; как сигнал родителя у Apache доезжает до конкретного соединения через пять звеньев; и таблица из двенадцати клеток, в которой четыре реализации расходятся ровно в одной.

Со стендом (один docker build, один docker run), полными выводами ps и тремя claims-*.tsv, где каждое утверждение о коде проверяется скриптом.

Читать далее

proxy_pass и fastcgi_pass — одна машина

Уровень сложностиСложный
Время на прочтение11 мин
Охват и читатели9.5K

У директив proxy_* и fastcgi_* совпадает 46 опций из 53 — буферизация, таймауты, кеш, next_upstream, с точностью до префикса и вплоть до значений по умолчанию. Два независимо написанных модуля так не сходятся.

Они и не независимы. Всё, чем proxy_pass отличается от fastcgi_pass, — девять указателей на функции в ngx_http_upstream_t. Соединение, таймауты, повторы, буферизация и отдача клиенту лежат в общих 7352 строках ngx_http_upstream.c, и восемь модулей — от proxy до свежего tunnel — дёргают один и тот же код.

Только контракт из этих девяти указателей врёт в обе стороны. Один из них, abort_request, ставят все восемь модулей — а машинерия не вызывает его ни разу: ноль вызовов во всём дереве и ни одного коммита с вызовом за всю публичную историю, с импорта 0.1.14 в январе 2005-го. Другой, pipe->input_filter, в контракте не объявлен вовсе — но обязателен, как только включена буферизация, и вызывается без проверки на NULL.

Разбираем по тегу release-1.31.3 со ссылками файл:строка: все места вызова каждого колбэка, включая тот, который разбирает заголовок не из сокета, а из файла кеша; матрица «кто какие указатели ставит» по всем восьми модулям; два сценария падения с разными стек-трейсами. Плюс свой рабочий upstream-модуль на 335 строк, собранный и проверенный curl'ом, и tunnel — самый маленький из восьми, приехавший в open source в апреле.

Читать далее

В nginx один алгоритм балансировки

Уровень сложностиСложный
Время на прочтение17 мин
Охват и читатели17K

server a.internal weight=10 max_fails=2; — десять к одному. Ночью бэкенд на пару секунд отвалился, к утру давно жив и из ротации не выведен. А первые полсотни запросов рабочего дня распределяются не 10:1, и среди них есть места, где два запроса подряд уходят на сосед с весом единица.

Ни один лог об этом не скажет, в документации по upstream такого объяснения нет. Есть — в двух строках ngx_http_upstream_round_robin.c.

Разбираем по тегу release-1.31.3, со ссылками файл:строка: smooth weighted round-robin и его восемь копий в исходниках; effective_weight, которого нет в документации, и то, как max_fails втихую им управляет; почему least_conn сравнивает не число соединений; почему ip_hash не работает на unix-сокетах. Плюс sticky и least_time, приехавшие в open source несколько месяцев назад.

Читать далее

Логирование в Angie

Уровень сложностиПростой
Время на прочтение12 мин
Охват и читатели8.6K

Надёжная работа любого сервиса опирается на возможности системы журналирования. С помощью логов можно решить широкий спектр задач: решение проблем, аналитика поведения пользователей, расследование инцидентов безопасности, мониторинг состояния системы и другие. В этой статье посмотрим на возможности и практические приёмы для работы с логами сервера Angie.

Читать далее

Приложение открывается только с VPN. Разбирался почему

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели14K

Пользователи из регионов начали писать в поддержку одно и то же: приложение не открывается. Симптомы у всех разные. У кого-то вечная загрузка, у кого-то белый экран, у кого-то заходит, только если включить VPN.

На своём компьютере всё летает. С зарубежного сервера проверяю, тоже без проблем. Сижу, чешу затылок.

Сначала списал на случайные глюки у провайдеров. Мало ли, бывает. Но обращений становилось больше, а не меньше, и в какой-то момент стало ясно: это не совпадение, это системная штука. Пришлось лезть в сетевой дебаг с головой.

В этой статье расскажу, как искал причину таймаутов, где я сам сначала неправильно объяснил себе проблему, и что в итоге поменял в инфраструктуре, чтобы всё заработало стабильно.

Читать далее

Оптимизация Angie для высоких нагрузок

Уровень сложностиСредний
Время на прочтение16 мин
Охват и читатели8.6K

Вопрос производительности работы сервера Angie и различных оптимизаций не раз поднимался в других статьях цикла. Поэтому здесь мы соберём основные приёмы и подходы к настройке Angie для высоких нагрузок, а за подробностями по отдельным вопросам будем направлять читателя в специализированные статьи.

Читать далее

Я поставил сайт-визитку и посчитал посетителей. Живых оказалось 8 %

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели9.7K

273 «уникальных посетителя» за трое суток и ни одного пользовательского скачивания. Разбираю сырые логи nginx руками: почему фильтр по User-Agent ловит только честных роботов, какой поведенческий признак отделяет живой браузер от сканера и как из 273 адресов остаётся 21.

Читать далее

Habitica self-hosted: полный гайд по развёртыванию, настройке Nginx и docker-compose

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели11K

Если кратко, я создаю свою домашнюю лабораторию, которой планирую пользоваться в повседневной жизни. В неё я решил внедрить и трекер задач, так как это был единственный инструмент, который выбивался из моего привычного workflow и существовал полностью отдельно. Из-за этого список ежедневных дел мне приходилось копировать в Obsidian, чтобы в случае удаления старого трекера не бояться, что мои планы пропадут.

После недолгих поисков я пришел к Habitica. Геймификация в ней меня действительно зацепила, и, пользуясь этим подходом последние несколько дней, я не жалею. Поэтому я хочу поделиться тем, как я настраивал все для себя, чтобы добиться лучшего результата.

Читать далее

Ближайшие события

ЧАСТЬ 2. Своя self-hosted двухсерверная VPN-архитектура: Gitea, сборка Amnezia, проблемы 7.1.3-arch1-2 и многое другое

Уровень сложностиСложный
Время на прочтение10 мин
Охват и читатели11K

Эта статья является прямым продолжением вот этой статьи про мой проект ServeHub-2, которое охватывает релиз 1.4.0 и отчасти 2.0.0, 2.1.0 (а также определенные подробности, которые не упоминались в прошлой статье). Здесь будут подробно объясняться моменты в том порядке, в котором они появлялись в проекте.

Также изначально планировалось в этой же статье рассказать про Go Wails установщик, но тогда она получается слишком большой, поэтому про это будет в следующей части.

Читать далее

Сборка Angie из исходных кодов

Уровень сложностиСредний
Время на прочтение13 мин
Охват и читатели9.7K

Стандартным методом установки софта в Linux сегодня является использование бинарных пакетов. В некоторых средах используются готовые образы контейнеров. Однако, умение собирать Angie из исходных кодов открывает широкие дополнительные возможности. Погрузимся в этот непростой процесс и обсудим, зачем может пригодиться сборка из исходников.

Читать далее

Влияние TLS-библиотек и настроек на производительность

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели8.5K

Тонкая настройка TLS необходима для современного веб‑сервера, обратного прокси или балансировщика с терминацией TLS. При этом тема достаточно запутанная для изучения, в сети можно найти множество устаревших материалов и откровенных мифов. В этой статье будем тестировать влияние важных настроек и вариантов TLS‑библиотек на примере веб‑сервера Angie.

Читать далее

Как перенести Docker Compose на новую VPS без даунтайма

Уровень сложностиСредний
Время на прочтение4 мин
Охват и читатели13K

Совсем недавно я переносил работающий прод с одной впс на другую. Причина простая - новый провайдер давал в несколько раз больше ресурсов за те же деньги и с тем же SLA, но были две проблемы: Первая - сервисом пользовались круглосуточно, и даже несколько минут простоя были нежелательны. Вторая проблема - инфраструктура очень скромная, и подозреваю, знакомая многим: один сервер, docker compose, nginx как реверс прокси. Все легкие способы переезда отпадают сразу.

Читать далее

Я устал деплоить проекты вручную и автоматизировал этот процесс

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели8.9K

Проблема
Мне как бэкэнд-разработчику приходится работать с деплоем своих проектов, каждый раз одна и та же рутина: настройка сервера, nginx, ssl, безопасность сервера(fail2ban, user), CD и многое другое. Это отнимает очень много времени.

Что сделал
После десятков задеплоенных проектов я понял, что все эти действия можно автоматизировать, и решил написать скрипт.

Читать далее

Стриминг ZIP‑архивов на лету с nginx + mod_zip — просто, как 2 байта переслать

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели7K

В проекте пользователям регулярно нужно скачивать наборы документов в виде архива. Изначально архивы формировались только из файлов внутри системы, но задача усложнилась, когда потребовалось добавлять внешние источники. В статье я разбираю решение на базе nginx mod_zip и потоковой генерации архива, позволяющее собирать ZIP «на лету» с минимальной нагрузкой на сервер. Также я подготовил простое демо, где можно всё попробовать самостоятельно.

Читать далее

Как мы поднимали файловое облако для команды: Seafile, HTTPS, мобильные клиенты и белый экран на Android

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели6.1K

Практическая история о том, как для небольшой команды мы подняли частное файловое облако на Seafile, прикрутили HTTPS через Nginx, столкнулись с белым экраном на Android и в очередной раз убедились, что все бывает гораздо проще, чем кажется на первый взгляд.

Читать далее
1
23 ...