ServerAdmin.ru
31.6K subscribers
853 photos
57 videos
23 files
3K links
Авторская информация о системном администрировании.

Информация о рекламе: @srv_admin_reklama_bot
Автор: @zeroxzed

Второй канал: @srv_admin_live
Сайт: serveradmin.ru

Ресурс включён в перечень Роскомнадзора
Download Telegram
Решал на днях простую задачку. Нужно было сделать так, чтобы разработчики могли сами включать на сайте режим обслуживания, чтобы весь трафик пользователей шёл на страницу заглушку, а они могли с сайтом работать, как обычно. Такой режим есть в движке Битрикс. Довольно удобно, разработчики пользуются.

Хотелось сделать примерно то же самое на базе Nginx/Angie, но с помощью файла-флага, который можно положить в корень сайта и это будет включать режим обслуживания. Если файл есть – весь трафик пользователей идёт на заглушку, а IP адреса разработчиков или какие-то подсети видят сайт как обычно и работают с ним.

Задача в целом популярная, в сети легко находятся готовые примеры. Но там везде используется if. Хотелось сделать без него, но у меня не получилось. Долго мучал chatgpt. Он бодро предлагал неработающие решения, потом так же бодро сообщал, что действительно тут ошибка и так не работает. Надо делать вот так и тогда получится. В итоге простого красивого и удобного решения именно с файлом-флагом, без правки конфигурации и reload веб сервера сделать не получилось. Реализовал наиболее простой вариант с помощью пары if.

Создаём файл /etc/angie/allowed_ips.conf следующего содержания:

map $remote_addr $bypass_maintenance {
  default 0;
187.192.238.175 1;
  192.168.0.0/24 1;
}


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

  location = /maintenance.html {
    try_files $uri =503;
  }

  location / {
    set $in_maintenance 0;
    if (-f $document_root/maintenance.flag) {
    set $in_maintenance 1;
    }
    set $maintenance_check "${in_maintenance}_${bypass_maintenance}";
    if ($maintenance_check = "1_0") {
      return 302 /maintenance.html;
    }
    try_files $uri $uri/ /index.php?$args;
  }


Теперь если в корне сайта создать файл maintenance.flag, то всем пользователям, кого нет в списке allowed_ips.conf будет отображаться содержимое файла maintenance.html, который надо добавить.

Это максимально простой и быстрый вариант. Но столкнулся с небольшим нюансом. Когда обслуживание закончено, желательно пользователей, кто остался на странице maintenance.html обратно вернуть на главную, когда они в очередной раз обновят страницу. Добавляем проверку в location /maintenance.html

  location = /maintenance.html {
    if (!-f $document_root/maintenance.flag) {
    return 302 /;
  }
    try_files $uri =503;
  }


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

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

#nginx #angie
2👍178👎3
Часто возникают ситуации, когда хочется силами веб сервера закрыть доступ к какому-то непубличному ресурсу. Причём не обязательно у этого ресурса нет своей аутентификации. Если нет явной необходимости то и её стоит закрыть от посторонних глаз. Расскажу, какими способами это можно сделать в веб сервере Angie/Nginx.

1️⃣ Basic Authentication. Самый простой и быстрый способ, известный очень давно. Для аутентификации используется текстовый файл с сохранёнными там парами логин-пароль. Очевидное неудобство – этот файл нужно вести отдельно от любых других хранилищ учётных записей.

2️⃣ Модуль ngx_http_auth_request_module. Это модуль от команды Nginx, который работает относительно просто. Он создаёт подзапрос к какому-то внешнему сервису и если получает от него код ответа 2xx, доступ разрешается, если 401 и 403, то запрещается. В качестве внешнего сервиса могут использоваться разные системы с разными бэкендами для хранения учётных данных. Например, для аутентификации через LDAP обычно используют nginx-ldap-auth. Полная схема работы с ним есть в статье на сайте Nginx.

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

3️⃣ Модуль ngx_http_auth_ldap_module. Это внешний модуль стороннего разработчика для аутентификации через внешний LDAP сервис. Его отличие от предыдущего варианта в намного более простой настройке. Вся логика подключения к LDAP каталогу настраивается в конфигурации веб сервера. Он делает все запросы к каталогу и выполняет аутентификацию.

4️⃣ Модуль ngx_http_auth_spnego_module. Этот модуль позволяет настроить аутентификацию через Active Directory с помощью Kerberos. Его удобство относительно описанных выше способов в том, что если у вас браузер поддерживает сквозную аутентификацию Kerberos, то доменные пользователи будут автоматически попадать на закрытые ресурсы без необходимости отдельно вводить учётные данные.

5️⃣ Сервис SSO, например, Authentik. Решил вынести этот способ в отдельный пункт, хотя это и не совсем корректно. Это может быть комбинация различных методов аутентификации, так как тот же Authentik, к примеру, может выступать в качестве LDAP каталога, либо реализовывать тот же метод Basic Authentication, только с хранением учётных данных у себя.

Если будете использовать внешние модули, то удобнее взять Angie, так как там в базовом репозитории они все уже есть. Для Nginx скорее всего что-то придётся собирать самому в зависимости от дистрибутива. Где-то в репозиториях есть модули, где-то нет.

Современным и удобным способом является использование сервиса SSO. Наиболее известные - Keycloak, Authentik, Authelia, ZITADEL. Список составлен от сложного и тяжёлого к более простому и лёгкому. Они реализуют в том числе современные технологии типа OAuth2, OTP (one-time password), OpenID Connect и т.д. Но и, соответственно, требуют больше внимания и времени на настройку. Если какой-то модуль Nginx можно быстро установить и настроить, то с SSO придётся повозиться. Для простых ситуаций это может быть неоправданно.

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

#nginx #angie
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍106👎2
Расскажу про одну простую настройку в Nginx/Angie, которую использую постоянно, но с некоторыми нюансами, про которые возможно кто-то не знает. По крайней мере я не сразу об этом узнал. Речь пойдёт про basic_auth.

Я уже много раз упоминал про эту настройку, которая позволяет очень просто и быстро скрыть от посторонних глаз какой-то сервис с помощью простой аутентификации с использованием имени пользователя и пароля. Делается это примерно так:

# sh -c "echo -n 'user01:' >> /etc/nginx/.htpasswd"
# sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"

Создали файл .htpasswd, куда добавили пользователя user01 и задали ему интерактивно пароль. Теперь настраиваем Nginx/Angie, добавляя в секцию server или отдельной location настройку:

location / {
auth_basic "Access Denied";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ =404;
}

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

Таким способом очень удобно скрывать различные непубличные сервисы или технические панели. Например, я всегда так закрываю публикацию баз 1C, доступ в Phpmyadmin, Zabbix, Grafana, Apache Guacamole, какую-нибудь веб панель для управления, если используется и т.д. В общем, всё, что не для широкой публики лучше скрыть от посторонних глаз.

Иногда хочется, чтобы кого-то пускало напрямую без аутентификации. Первое, что приходит в голову, добавить директивы allow и deny, потому что они тоже часто используются. По крайней мере я постоянно использую. Но они напрямую не работают с basic_auth, либо одно, либо другое. Нужен ещё один параметр - satisfy.

location / {
satisfy any;
allow 192.168.137.0/24;
deny all;
auth_basic "Access Denied";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ =404;
}

В этом примере пользователи из подсети 192.168.137.0/24 зайдут на ресурс напрямую без аутентификации, а всем остальным нужно будет ввести пароль. Это удобно для той же публикации 1С, когда люди из офиса ходят напрямую в локальную базу, а снаружи с аутентификацией. В случае публикации на внешнем сервере удобно разрешить доступ с внешнего IP адреса офиса прямой доступ, а всем остальным с паролем.

Точно так же удобно открыть прямой доступ к техническим панелям администраторам или только себе лично напрямую, а всем остальным закрыть паролем. Точнее даже не всем остальным, а тоже себе, если вдруг придётся подключаться с каких-то недоверенных адресов.

Если нужно указать несколько подсетей и отдельных IP адресов, то их можно добавлять новыми строками, примерно так:

allow 192.168.0.0/24;
allow 10.20.5.0/24;
allow 185.25.48.189;

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

Basic_auth простая и надёжная технология. Не припоминаю, чтобы хоть раз была какая-то уязвимость в обход неё. Пароль можно только перехватить, если не используется HTTPS, либо сбрутить, но это трудно, так как во-первых, стоит настраивать ограничение в веб-сервере на количество одновременных запросов. Я всегда это делаю по умолчанию. Плюс, производительности веб сервера будет недостаточно, чтобы подбирать сложный пароль с хорошей скоростью. Это не локально брутить. По интернету несловарный сложный пароль не подобрать.

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

———
ServerAdmin: 📱 Telegram | 🌐 Сайт | 📲 MAX

#nginx #angie
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍221👎5
Думаю, все уже слышали или знают такой продукт, как Angie. Это веб сервер, форк Nginx, который развивается, насколько я понимаю, независимо от него. Я уже давно нигде не устанавливаю Nginx. Если только по привычке на тестах каких-нибудь, потому что он есть в базовых репах дистрибутивов, а Angie - нет. В работу везде ставлю Angie, потому что он функциональнее и удобнее Nginx.

Мне сейчас сходу трудно перечислить ключевые отличия от Nginx, потому что за последним банально перестал следить. Мне лично Angie сразу понравился в первую очередь тем, что там:

🔹Удобнее устанавливать дополнительные модули. Они все упакованы в пакеты в едином репозитории. Просто берёшь, ставишь и настраиваешь. В то время, как Nginx приходилось собирать самому с нужными модулями.

🔹У Angie реализован экспорт метрик для мониторинга, плюс панель веб управления, где своя визуализация некоторых метрик и настроек. Я сделал себе шаблон для Zabbix, но после того, как разработчики опубликовали свой дашборд для Grafana, перешёл на него, так как стало лень поддерживать свой шаблон самому. А тут всё уже есть в готовом виде.

🔹Над Angie активно работают и улучшают, в том числе полностью бесплатную open source версию. Бесплатный Nginx после продажи компании F5 как-будто развивать вообще перестали и просто поддерживают на плаву.

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

Про настройку Angie написал отличный содержательный цикл статей Лавлинский Николай. Его материалы, как и анонсы вебинаров Отуса с его участием, можно периодически наблюдать на моём канале.

Каждая статья содержит как текстовое описание, так и подробное видео с примерами. Очень содержательный материал. Рекомендую. Я смотрел все видео. Там и по базовой, и не только, настройки есть всё, что нужно. Цикл опубликован на Хабре:

◽️Почему стоит переходить на Angie.
◽️Установка Angie из пакетов и в докере.
◽️Переезд с Nginx на Angie. Пошаговая инструкция.
◽️Настройка location в Angie. Разделение динамических и статических запросов.
◽️Перенаправления в Angie: return, rewrite и примеры их применения.
◽️Сжатие текста в Angie: статика, динамика, производительность.
◽️Серверное кэширование в Angie: тонкости настройки.
◽️Настройка TLS в Angie: безопасность и скорость.
◽️Настройка Angie в роли обратного HTTP-прокси.
◽️Балансировка нагрузки для HTTP(S) в Angie.
◽️Мониторинг Angie с помощью Console Light и API.
◽️Балансировка и проксирование L4-трафика в Angie.
◽️Клиентское кэширование в Angie.
◽️Динамические группы проксируемых серверов в Angie.
◽️Мониторинг Angie с Prometheus и Grafana.

Немного не в тему, но добавлю ещё одну интересную ссылку с полезным материалом:

Ещё одно тестирование Angie, HAProxy, Envoy, Caddy и Traefik от Devhands
HAProxy показывает наиболее сбалансированные и стабильные результаты на стандартных настройках. Старый, проверенный универсальный балансировщик.

Если всё ещё используете Nginx, рекомендую попробовать Angie. Переезд на него не требует практически никаких изменений конфигурации. Возможно где-то только пути придётся поправить с /etc/nginx на /etc/angie, а может и этого не придётся в зависимости от структуры вашей конфигурации.

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

———
ServerAdmin: 📱 Telegram | 🌐 Сайт | 📲 MAX

#webserver #angie #отечественное
Please open Telegram to view this post
VIEW IN TELEGRAM
👍181👎3
Вчера была заметка про Angie. Хочу подробнее остановиться на одной из его настроек, о которой кто-то возможно не знает. Привычное применение веб сервера - непосредственно обработка HTTP запросов или их проксирование с балансировкой куда-то ещё. Последнее обычно называют работой в качестве обратного прокси. Но помимо HTTP трафика Angie может обрабатывать и другие соединения.

У Nginx, следовательно и у Angie, есть модуль Stream для обработки TCP и UDP соединений. По умолчанию он не включён в стандартный состав веб-сервера, да и появился он в Nginx не сразу. С его помощью можно проксировать соединения, к примеру RDP протокола, DNS запросов или подключений к VPN серверу. Применений можно найти массу. Очень удобно управлять всеми соединениями в единой точке входа.

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

У Angie модуль stream включён в сборку в стандартных пакетах, так что ничего не нужно дополнительно делать. Можно сразу настраивать нужную функциональность. Выглядит она примерно так:

stream {
  limit_conn_zone $binary_remote_addr zone=addr:10m;
  log_format basic '$remote_addr [$time_local] '
    '$protocol $status $bytes_sent $bytes_received '
    '$session_time ' "$upstream_addr";
include /etc/angie/stream.d/*.conf;
}

upstream rdp {
  server 192.168.100.2:3389;
  server 192.168.100.3:3389;
}

server {
  listen 3390;
  allow 192.168.100.0/24;
  deny all;
  limit_conn addr 1;
  proxy_pass rdp;
  access_log /var/log/angie/rdp-access.log basic;
}


Что мы тут сделали:

- Запустили Angie на TCP порту 3390 слушать входящие соединения.
- Настроили перенаправление соединений на 2 терминальных сервера:
  server 192.168.100.2:3389;
  server 192.168.100.3:3389;
- Настроили ограничение на 1 соединение с одного IP адреса.
- Настроили ограничение на доступ только из подсети 192.168.100.0/24.
- Настроили логирование соединений в rdp-access.log с заданным форматом.

Это немного синтетический пример просто для демонстрации возможностей. Конкретно RDP протокол может не только транслироваться куда-то дальше, но и разбираться прямо на сервере с помощью ещё одного модуля stream_rdp_preread_module. Можно идентифицировать сессию и направить её на конкретный сервер. Отдельно отмечу, что подобная настройка будет актуальна и для одного RDP сервера. Мы просто скрываем его за Angie.

В чём вообще смысл подобных настроек? Балансировщиков много разных, плюс сам сервис может иметь свой балансировщик, как тот же RD Gateway (Remote Desktop Gateway).

Основное удобство в том, что вы получаете все инструменты по управлению, ограничению, логированию запросов, которые уже есть в Angie. Я тут как раз их и продемонстрировал. Мы, во-первых, логируем все запросы, в том числе и неудачные, мы, во-вторых, ограничили число запросов и доступ с определённых подсетей. И это далеко не всё, что умеет Angie.

В дополнение к этому можно настроить TLS соединения с клиентами для тех сервисов, которые сами это не умеют делать. То есть клиенты подключатся к Angie по TLS, а дальше соединения проксируются на сервис без шифрования. Какой-нибудь старый почтовый сервер так можно закрыть, который стоит локально и не умеет в шифрование. Или соединения к СУБД временно направить извне, не меняя конфигурацию, которая настроена на локальные подключения без шифрования.

Плюс, можно на основе имени домена в SNI направить трафик в нужном направлении. Например, при обращении к домену example.com направлять запросы на веб сервер с сайтом, а при запросе домена rdp.example.com направить соединения на бэкенды с RDP. То есть мы не по портам раскидываем трафик, а по доменным именам в TLS соединениях.

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

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

———
ServerAdmin: 📱 Telegram | 🌐 Сайт | 📲 MAX

#angie
Please open Telegram to view this post
VIEW IN TELEGRAM
👍128👎6
В одном из обновлений Angie ещё в начале этого года был добавлен модуль с ACME клиентом. Я уже как-то писал о нём мельком сразу после выхода. Он обеспечивает автоматическое получение бесплатных сертификатов Let's Encrypt. Я по старинке использую certbot и иногда acme.sh. Старые сервера перенастраивать не стал, особого смысла нет. А вот для новых имеет смысл попробовать.

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

Все параметры описаны в документации. Я смотрел только туда. Получилось всё с первого раза, но пара вопросов остались. В конце отмечу их. Покажу итоговый пример для двух доменов: mail.zeroxzed.ru и webmail.zeroxzed.ru. Сделал их для статьи по почтовому серверу, которую пока пишу.

Добавляем в раздел http конфигурации Angie:

http {
....
resolver 62.76.76.62 62.76.62.76;
acme_client webmail https://acme-v02.api.letsencrypt.org/directory;
acme_client mail https://acme-v02.api.letsencrypt.org/directory;
....
}


62.76.76.62 и 62.76.62.76 - публичные DNS сервера компании MSK-IX. Можете использовать любые другие.

Создаём 2 файла конфигурации виртуальных хостов в директории /etc/angie/http.d - mail.conf и webmail.conf. Содержание одинаковое, отличается только поддомен и параметр acme:

server {
  listen 443 ssl;
  server_name webmail.zeroxzed.ru;

  root /var/www/webmail;
  index index.php index.html;

  acme webmail;
  ssl_certificate $acme_cert_webmail;
  ssl_certificate_key $acme_cert_key_webmail;

  access_log /var/log/angie/webmail-access.log;
  error_log /var/log/angie/webmail-error.log;

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  location ~ \.php$ {
    fastcgi_pass  unix:/run/php/php8.4-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }
}

server {
  listen 80;
  server_name webmail.zeroxzed.ru;
  return 301 https://$host$request_uri;
}


Перезапускаем веб сервер и наблюдаем в логах:

2025/11/27 17:24:28 [notice] 154580#154580: creating implicit client block for "@acme"
2025/11/27 17:24:28 [notice] 154580#154580: no certificate, renewal scheduled now, ACME client: webmail
.......................
2025/11/27 17:24:31 [notice] 154582#154582: ACME account ID: "https://acme-v02.api.letsencrypt.org/acme/acct/2832575756", ACME client: webmail
2025/11/27 17:24:47 [notice] 154582#154582: certificate renewed, next renewal date: Mon Jan 26 16:26:15 2026, ACME client: webmail


И так для обоих доменов. В директории /var/lib/angie/acme появились две папки mail и webmail, где расположены соответствующие сертификаты.

Не видел нигде примеров конфигурации с несколькими доменами, поэтому не понял, можно ли как-то всё красиво оформить через переменные в ssl_certificate, но с одним acme_client? Или для каждого отдельного домена надо прописывать своего клиента?

Второй момент, который остался непонятен. Он актуален, если эти же сертификаты использует кто-то ещё. Не увидел никакой возможности настроить хуки после обновления сертификатов, чтобы уведомить зависящие от них службы. Придётся какие-то костыли городить, типа incron, что нивелирует простоту изначальной настройки.

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

❗️Если заметка вам полезна, не забудьте 👍 и забрать в закладки.

———
ServerAdmin: 📱 Telegram | 🌐 Сайт | 📲 MAX

#angie
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍97👎5