Bash Days | Linux | DevOps
Авторский блог от действующего девопса Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу. Автор: Роман Шубин Реклама: @maxgrue MAX: https://max.ru/bashdays Курс: @tormozilla_bot Блог: https://bashdays.ru
显示更多📈 Telegram 频道 Bash Days | Linux | DevOps 的分析概览
频道 Bash Days | Linux | DevOps (@bashdays) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 23 797 名订阅者,在 技术与应用 类别中位列第 5 708,并在 俄罗斯 地区排名第 28 124 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 23 797 名订阅者。
根据 16 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -201,过去 24 小时变化为 -10,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 20.40%。内容发布后 24 小时内通常能获得 11.53% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 4 855 次浏览,首日通常累积 2 744 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 17。
- 主题关注点: 内容集中在 bashdays, linux, bash, docker, скрипт 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
凭借高频更新(最新数据采集于 17 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
/tmp.
В некоторых дистрибах эта папка монтируется в память. Но если оперативки мало, а чья-то софтина активно пишет в нее, есть смысл перенести папку /tmp куда-нибудь на диск.
Ну а если папка /tmp лежит на корневом разделе, а на разделе нет места, то это тоже проблема.
ㅤ
Самый распространенный и быстрый вариант:
1. Смонтировать новый диск в /mnt/tmp
2. Прокинуть симлинкой /mnt/tmp → /tmp
Но в некоторых случаях софт упоротый и скажет — я ебал писать в симлинку, давай мне нормальный локейшен в /tmp.
Упоротый софт в моем случае была некая многопоточная конвертилка pdf файлов, которая раздувала папку tmp до — я ебёшь! И пока она не сделает свои дела, за собой не уберет.По опыту скажу — софт никто править не будет, а попросят инженера вбить костыль. Так быстрее и не нужно тратить время разработчика. Да! Так и живем в больших интерпрайзах. Поэтому изобретают подобный велосипед. Монтируют новый диск в
/mnt/tmp
sudo mkdir /mnt/tmp
sudo chmod 1777 /mnt/tmp
Права 1777 важны для временных директорий, чтобы все пользователи могли создавать файлы, но не удаляли чужие. Единичка это — стинкибит.Создаем файл и пишем в него:
/etc/systemd/system/mnt-tmp.mount
[Unit]
Description=Mount tmpfs on /mnt/tmp
[Mount]
What=tmpfs
Where=/mnt/tmp
Type=tmpfs
Options=mode=1777,size=10G
[Install]
WantedBy=multi-user.target
Название файла не может быть любое, у нас есть путь /mnt/tmp в этом случае файл называем mnt-tmp.mount. Если было бы /mnt/tmp/bashdays, то файл нам нужно обозвать mnt-tmp-bashdays.mount.Ага, вот такие нюансы, иначе оно грязно выругается и нассыт тебе в глаз. По юниту все интуитивно понятно, расписывать не буду. А потом, как обычно:
sudo systemctl daemon-reload
sudo systemctl enable mnt-tmp.mount
sudo systemctl start mnt-tmp.mount
Да, чтобы процессы использовали новый каталог, в файле /etc/environment указываем переменную.
TMPDIR=/mnt/tmp
Не забываем применить:
source /etc/environment
Проверяем и зачищаем старье:
echo $TMPDIR
df -h /mnt/tmp
sudo rm -rf /tmp/*
Всё, дело в шляпе. Аналогично делается с папкой логов, но там есть свои нюансы, попозже расскажу.
tags: #linux
—
🔔 @bashdays➡️ @gitgatescreen
cd /usr/local/sbin
./db_import.sh
И потом закрывают терминал, а скрипт db_import.sh продолжает где-то там шуршать и делать свои делишки.
ㅤ
Потом возвращаются спустя время и делают:
screen -list
3393.pts-3.dev (Attached)
screen -x 3393.pts-3.dev
или
screen -r 3393.pts-3.dev
Убеждаются что скрипт завершил свою работу, ну и выходят, порой даже не закрывая screen сессию (3393.pts-3.dev).
Чем отличается -r и -x
-r (resume) = подключаемся к сессии которая в данный момент отсоединена, то есть к ней не подключены другие юзеры. -x (multi-user mode) = подключаемся к сессии к которой уже кто-то подключен, то есть несколько пользователей могут мешать друг другу в рамках одной сессии.Подход нормальный, никаких тебе ключей запоминать не нужно и т.п. Но есть такой вариант:
screen -dmS имя_сессии bash /путь/к/скрипту.sh
dmS это параметры для запуска screen в фоновом режиме (detached mode) с именем сессии. d = запускает сессию в отключенном (detached) режиме. m = создаёт новую сессию, даже если она существует. S = имя сессииКоманда выше создаст сессию screen и запустить скрипт в фоновом режиме. А самое главное отпустит терминал и ты сможешь дальше в нём работать. И самая киллер-фича — после отработки скрипта, screen сессия автоматически закроется и после выполнения команды:
screen -list список будет пуст.
Еще можно так:
screen -X -S "script0$scriptID" stuff "^C"
script0$scriptID = указывает на сессию с именем, здесь $scriptID это переменная, содержащая идентификатор или значение, которое будет подставлено в команду. stuff = передаёт текст или последовательность символов в сессию screen, как если бы их ввел пользователь.На закуску. Когда ты подключился к сессии и у тебя там еще работает скрипт, как не закрывая терминал вернуться в интерактивный режим? Я раньше просто закрывал окно с терминалом и сейчас вижу что много кто так делает. Все просто, прожимаем
CTRL+A и затем «d». Ты отключаешься от сессии, переходишь в интерактивный режим с терминалом, а скрипт продолжает шуршать в фоне.
А как посмотреть выхлоп скрипта если сессия закрыта?
Добавь в свой скрипт логирование и обработку экспешенов, пусть оно в файлик пишет результаты своей работы. Нахуй тебе через screen потом ебаться все это просматривать.
Буквально вчера увидел как инженер с утра запустил распаковку базы на сервере, через пару часов у него мигнул интернет, ssh сессия с сервером превратилась в тыкву! Начинайте сначала!
Если запускаешь на сервере что-то очень долгое и не хочешь быть к этому привязан, используй screen! Это мастхев для подобных процедур. По крайней мере сохранишь время и нервы.
Вот и вся наука. Изучай!
tags: #linux #utilites #bash
—
🔔 @bashdays➡️ @gitgateUnicode представляет текст как последовательность кодовых точек — чисел, которым присвоено определённое значение. Каждая кодовая точка записывается в формате U+XXXX, где XXXX — это шестнадцатеричное число в верхнем регистре. Для латинских символов каждой кодовой точке соответствует конкретный символ на экране. Например, кодовая точка U+0067 обозначает букву "g". Однако в некоторых системах письма один видимый символ может состоять из нескольких кодовых точек. Например, символ "की" в деванагари формируется из кодовых точек U+0915 и U+0940, соединённых вместе.Где можно применить? Ну конечно же поиграться, изобрести что-то своё, попентестить формочки на отказ в ослуживании, либо вставлять метки «жучки», чтобы в случае утечки данных отследить отправителя и получателя. Тут всё зависит от твоих потребностей и креативных идей. В телеге кстати нормально работает, но при условии если эмодзи отправлен без дополнительного текста и т.п. В других мессенджерах не проверял.
В комменты закину такой смайлик на потыкать. Перешли себе в Избранное и от туда уже правой мышкой - копировать текст.🅰️🅰️ ➡️ Технический подробности глянуть тут. ➡️ Исходники кодера/декодера на гитхабе. Надо на Bash такую пепяку сделать, ради прикола. tags: #security #crypt — 🔔 @bashdays➡️ @gitgate
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576sudo apt update
sudo apt install libpam-google-authenticator
Запускаем конфигуратор:
google-authenticator
Я запускаю под рутом, но если тебе нужно настроить 2FA для другого юзера, для начала переключись на этого пользователя и только потом запускай конфигуратор.
После запуска конфигуратора, получишь Do you want authentication tokens to be time-based (y/n)
Тут поди сам разберешься чо нажимать. В ответ тебе выплюнут QR код, ссылку и секретный ключ.
Можно еще всякие ключики использовать:
google-authenticator -t -f -d -w 3 -e 5 -r 3 -R 60
Если интересно: google-authenticator --help
Всю эту инфу куданить себе скопируй чтоб не проебаться.
Дальше сканируем этот QR код, либо берем секретный ключ который он тебе выплюнул и вставляем в vaultwarden в TOTP или на телефоне в апку добавляем.
Тот самый секретный ключ:
Your new secret key is: MAIY4KDCXKWHPDCI
В общем нужно получить шестизначный код, вернуться в терминал (где ты запускал конфигуратор) и вставить его. Логика аналогична подключению 2FA в любых сервисах.
После этого оно выплюнет тебе рекавери коды, ну и спросит:
Do you want me to update your "/root/.google_authenticator" file?
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks
и другие
На всё соглашаешься, но если хочешь, можешь прочитать и тонко затюнить под свои задачи.
В файл /root/.google_authenticator сохранится секретный ключ и коды восстановления. Этот файл не трогаем, без него тоже нихуя не заработает.
Теперь открываем файл /etc/pam.d/sshd
И добавляем в него строчку:
# @include common-auth
auth required pam_google_authenticator.so
По необходимости комментим common-auth если ничего не работает. Есть вариант не комментить, но тогда нужно правильно настроить common-auth, но у нас сегодня не про это.
Закомментировав этот модуль ты отключаешь стандартные механизмы аутентификации и даешь зеленый свет на использование pam_google_authenticator.
Тут аккуратнее, можешь себе в ногу выстрелить. Сначала все проверяем и только потом закрываем терминал с активной сессий.
Дальше добавляем в конфиг: /etc/ssh/sshd_config
UsePAM yes
PasswordAuthentication no
ChallengeResponseAuthentication yes
PubkeyAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
Вот и всё, настройка 2FA завершена.
Рестартим:
sudo systemctl restart ssh
И пробуем подключиться по ssh к этому серверу:
ssh root@bashdays.ru
(root@bashdays.ru) Verification code:
Ха! А что вводить? Это и есть 2FA, сюда вводим одноразовый код который выплюнул тебе vaultwarden либо аппка на телефоне.
Всё! Залетаем спокойно на сервер. Без кода и ключа хуй ты теперь чо сделаешь.
Как использовать резервные коды?
Да также при запросе в Verification code. НО из файла /root/.google_authenticator они будут отлетать. Тут тоже аккуратнее.
Также можешь включать 2FA для конкретных пользователей, в конфиге /etc/ssh/sshd_config
Match User <имя юзера>
AuthenticationMethods publickey,keyboard-interactive
Настроек там жопой кушай, я тебе лишь концепт показал как эту хуйню можно быстренько настроить.
А как работать с 2FA и QR кодами из консоли, можешь почитать тут.Главное не спеши и делай всё вдумчиво, чтобы не проебать доступ к серверу. Ну а если все проебал, да и хуй с ним, ебани кофейка и мультики посмотри. tags: #linux #devops #linuxfactory — 🔔 @bashdays➡️ @gitgate
ssh-keygen -t rsa -b 4096 -f ~/.ssh/ssh_ca -C "SSH Certificate Authority"
Описывать за что отвечают параметры не буду, всё это уже разжевали, читай посты по тегу #linuxfactoryПо итогу получаем 2 ключа,
ssh_ca (приватный) и ssh_ca.pub (публичный).
Дальше чтобы сервера могли доверять сертификатам, подписанным нашим CA, добавляем публичный ключ CA (ssh_ca.pub) на все 100500 серверов.
Тут уже сам автоматику организуй, либо баш скриптом, либо ансибл ролью либо еще как-то. Попробуй ради интереса изобрести своё решение.Покажу в рамках одного сервера:
scp ~/.ssh/ssh_ca.pub user@bashdays:/etc/ssh/
Теперь заходим на этот самый сервер куда ты скопировал публичную часть ключа.
Открываем конфиг /etc/ssh/sshd_config
И пишем в него:
TrustedUserCAKeys /etc/ssh/ssh_ca.pub
Не забываем хуйнуть:
sudo systemctl restart ssh
Теперь сервер будет доверять сертификатам подписанным CA.
Ну а чтобы пользователь мог подключаться по сертификату, подписываем его публичный ключ с помощью CA.
Для этого копируем на CA машину свой локальный публичный ключ. Тот что у тебя на машине лежит и который ты прописывал ранее в authorized_keys на удаленных серверах.
Подписываем публичный ключ и превращаем его в сертификат.
ssh-keygen -s ~/.ssh/ssh_ca -I "user_cert" -n user -V +1w /tmp/user_key.pub
В ответ получаем нечто такое:
Signed user key /tmp/user_key-cert.pub: id "user_cert" serial 0 for username valid from 2025-02-16T12:02:00 to 2025-02-23T12:02:59И в папке
/tmp появляется файл user_key-cert.pub
➡️ Важно. При подписании ключа, указывай валидного юзера под которым будешь подключаться, иначе нарвешься на ошибку:
error: Certificate invalid: name is not a listed principal
Забираем себе на локальную машину подписанный ключ и пробуем подключиться:
ssh -i ~/.ssh/id_rsa -o CertificateFile=~/.ssh/user_key-cert.pub root@bashdays.com
Вуаля, я залетаю на сервер с подписанным ssh ключом, а на удаленном сервере вижу в логах:
2025-02-16 sshd[958704]: Accepted publickey for root from 11.11.11.11 port 35528 ssh2: RSA-CERT SHA256:Q4SKZ5cRycm79w0SyvRhAQR8 ID user_cert (serial 0) CA RSA SHA256:PtNBUw/+4/gGz4rc/ybu/uNHngcI
Если что-то не получается или не даёт зайти, пиздуешь на сервер к которому подключается и смотришь логи var/logs/auth.log. В этом файле тебе очень информативно подскажут что погуглить.И да, на удаленном сервере можно снести файл
~/.ssh/authorized_keys от тебе больше не пригодится. Потому что сервак начинает доверять всем ключам, которые подписаны через CA.
Ну а теперь давай отзовем сертификат с ключа
На сервере к которому ты настраивал подключение:
touch /etc/ssh/revoked_certs
В файле /etc/ssh/sshd_config добавляем:
RevokedKeys /etc/ssh/revoked_certs
Добавляем серт в этот файл с отзывами:
ssh-keygen -k -f /etc/ssh/revoked_certs -z 1 user_key-cert.pub
Всё, теперь если попробуем подключиться к серверу, нас пошлют нахуй.
Выглядит все это конечно пиздец крипово, но при правильной автоматизации этого процесса у тебя получится достаточно гибкий инструмент.
Завтра про Vault Hashicorp расскажу, в нем все проще делается
tags: #linux #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgateALT+F1, F2, F3 (чтобы переключать tty).
Надеюсь ты понял о чем я тебе говорю. Ну дак вот!
Задача: Нужно запретить физический вход по логину/паролю, но оставить вход по ssh с ключами.
Как настраивать все эти ключи можешь почитать в серии постов по тэгу: #linuxfactory
Давай теперь отключим физический доступ к tty.
Заходим на сервер и смотрим юниты
systemctl list-units | grep getty
В ответ получаем список активных tty
getty@tty1.service
getty@tty2.service
getty@tty3.service
getty@tty4.service
getty (сокращение от get tty) — это программа в Linux и Unix-подобных системах, которая отвечает за управление терминалами и логин-процессом для пользователей, подключающихся к системе через консоль.Теперь запускаем команды:
systemctl disable getty@tty{1..10}.service
systemctl stop getty@tty{1..10}.service
Всё! Песда! Терминал становится черным, интерактивность потеряна.
Пробуем понажимать ALT+F1, F2, F3 — хуй там плавал!
Перезагружаем сервер и НИЧЕГО! Черная дыра! Пробуем подключиться к серверу по ssh — ХА! Работает сучка!
При отключении getty для терминалов tty1–tty10, это не повлияет на SSH-доступ, так как SSH-сервер работает независимо от getty.Теперь даже имея физический доступ к серверу, ты нихуя с ним сделать не сможешь. Максимум загрузиться в Recovery mode и починить:
sudo mount /dev/sdXn /mnt
sudo chroot /mnt
sudo systemctl enable getty@tty{1..10}.service
sudo systemctl start getty@tty{1..10}.service
Вот такие приколюхи! Как и где это применять решай сам. Развлекайся.
Про Magic SysRq в Linux писал тут.
Чем терминал отличается от консоли писал тутtags: #linux #devops — 🔔 @bashdays➡️ @gitgate
server_name _;
Что это блядь за «чёрточка» вместо сервер_нейма?
ㅤ
Если техническим языком — это подстановочное имя хоста.
Пусть на сервере прописано так:
server {
listen 80;
server_name _;
return 444;
}
server {
listen 80;
server_name bashdays.ru;
return 200;
}
server {
listen 80;
server_name linuxfactory.ru;
return 200;
}
Если в браузере откроем bashdays.ru или linuxfactory.ru, то получим статус 200.
А как получить 444, тот самый с «чёрточкой»?
Просто! Например, зайти на сервер по его IP адресу. Nginx не сможет сопоставить доменные имена, которые прописаны в конфиге и отдаст статус 444.
То есть «чёрточка» это что-то типа заглушки. Nginx не воспринимает его как специальный символ, это обычное имя хоста, которое можно использовать для обработки запросов, не соответствующих другим явно указанным доменам.
Обычно эту «чёрточку» прописывают в файле defaults, чтобы тем, кто попал на сервер по IP адресу увидел, то что ты захочешь, а не рандомный сайт который у тебя висит на сервере.
Короче если запрос приходит с именем хоста, которое не совпадает ни с одним из явно прописанных server_name, то он будет обрабатываться этим серверным блоком.
А в сочетании с return 444 (No Response) используется для закрытия нежелательных запросов или для обработки некорректных запросов.
Если «чёрточка» не используется, то вместо неё можно просто прописать default_server в директиве listen, и блок будет работать аналогично.
server {
listen 80 default_server;
return 444;
}
Символ _ не имеет специального значения в самом Nginx. Это просто удобное соглашение, принятое сообществом.Вот так вот и живём, изучай! tags: #nginx #devops #linuxfactory — 🔔 @bashdays➡️ @gitgate
Ответ простой — Бесплатная версия GitLab (Community Edition) с открытым кодом даёт возможность изучить платформу без затрат. Для бизнеса это ещё и свобода от привязки к вендору.Именно по этой причине всем кому не лень напихали себе
Как пример, в школе я писал на Паскале, в голове сложил как работает программирование, ну и потом без труда пересел на сиськи потому что имел представление как работают программы. Синтаксис везде разный, но общая составляющая по базе одинаковая. Грубо говоря — нарисовал в голове блок схему, напрограммировал. Благо сейчас полно книжек — Java для детей, Golang - для бабушек и т.п. Читаешь книжку за пару дней, знакомишься с синтаксисом и пошел кодить. Функции, циклы, условия они везде одинаковые.Так и с пайпами, познакомился с yaml разметкой, взял из интернетов болванку с пайплайном и переписал под свои нужды, хоть для бакета, гитхаба, гитлаба, неважно. Так что если ты изучаешь пайпы на гитхабе, да ради бога, база у тебя в голове будет и ты без труда сможешь адаптировать все для гитлаба. И если видишь в вакухе — знания гитлаба, а ты его не знаешь, да и хуй с ним. Скажи — знаю! А там уже за пару часов разберешься, ничего в этом сложного нет. Но конечно же при условии, что ты пайпы хоть раз в жизни писал для чего-нибудь другого. Такие дела! tags: #рабочиебудни #devops — 🔔 @bashdays➡️ @gitgate
server {
listen 80;
server_name _;
location /app {
proxy_pass http://localhost:5000;
}
}
И есть приложение:
from flask import
Flask app = Flask(__name__)
@app.route('/')
def hello():
return 'Привет, Linux Factory!'
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Плюс к нему Dockerfile:
FROM python:3.8-slim
WORKDIR /app COPY .
/app RUN pip install -r requirements.txt
EXPOSE 5000
CMD ["python", "app.py"]
Собираем и запускаем контейнер:
docker build -t bashdays .
docker run -d -p 5000:5000 bashdays
Идем в браузере на http://bashdays.ru/app и получаем хуй с маслом:
Not Found. The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.Важно! Уже по этой ошибке можно сделать какие-то выводы, эт не стандартная ошибка от nginx, а значит запрос отлично доходит до приложения. Но где-то внутри приложения теряется. Тренируй насмотренность, у nginx ошибки обычно по центру выводятся, а тут align вправо. Еще как вариант, можешь остановить контейнер и еще раз в браузере тыкнуться, если получишь 502 Плохой шлюх, то значит что nginx нормально всё у тебя передает запросы на Flask. Но где-то внутри Flask происходит какое-то гавнище. А что случилось? Всёж верно? Локейшен в nginx прописан, прокси-пасс тоже присутствует, где ответ от приложения? Все дело в слэшах!
location /app {
proxy_pass http://localhost:5000/;
}
В конце порта 5000 ставим слэш и проверяем. Хуяк и оно начинает работать!
Что вообще происходит?
Когда мы делаем локейшен без последнего слэша в прокси-пассе, nginx проксирует запросы на приложение без изменения пути.
То есть приложение app.py получает роут /app а его там естественно нет. А есть просто корень /.
А когда мы добавляем слэш, nginx добавляет путь после /app к целевому урлу.
Короче опять заумно расписал, давай снова на котиках!
➡️ Без слэша запрос /app проксируется на http://localhost:5000/app, что не совпадает с маршрутом, настроенным в Flask.
➡️ С слэшем запрос /app проксируется на http://localhost:5000, и приложение Flask обслуживает его как корневой путь /.
В общем с конечным слэшем nginx «удаляет» часть пути /app и отправляет запрос на корень приложения Flask.
Вот и вся наука. Грабли прям жизненные и порой доставляют проблемы с многочасовым дебагом.
Так что держи это в голове, если с виду вроде все правильно, но не работает, пиздани в конце слэш, типа метод тыка.
Вечерком еще чтива подвезу, случайно набрал интеграций, теперь отдуваюсь.
tags: #nginx #devops #linuxfactory
—
🔔 @bashdays➡️ @gitgatelimit_req_zone, он то нам и пригодится. Этот параметр ограничивает количество одновременных запросов с одного айпишника.
Поехали настраивать.
Создаем файл /etc/nginx/conf.d/assholes.conf
geo $limited {
default 1;
192.168.1.1 0; # Этот IP не лимитируется
10.0.0.0/24 0; # 10.0.0.0/24 тоже без ограничений
}
map $limited $limit {
1 $binary_remote_addr;
0 "";
}
limit_req_zone $limit zone=bashdays:20m rate=200r/s;
limit_req_zone - ключ для отслеживания запросов.
$binary_remote_addr - системная переменная nginx, внутри хранит ip адрес клиента.
zone=bashdays:20m - произвольное имя зоны, 20m это объём памяти в мегабайтах для хранения данных. В этой зоне хранятся данные о количестве запросов от каждого уникального клиента.
rate=200r/s - ограничение равное 200 запросов в секунды с одного ip клиента.
Для рейта есть такая табличка:
Сценарий rate burst ------------------------------------------- API с высокой нагрузкой 100r/s 200 Средний веб-сайт 50r/s 100 Анти-DDoS защита 10r/s 20 CDN или кеширующий прокси 500r/s 1000тестируем так:
ab -n 1000 -c 50 http://bashdays.ru/
wrk -t4 -c100 -d10s http://bashdays.ru/
И смотрим нет ли ошибок 503 Слишком дохуя запросов и корректно ли отрабатывает лимит.
🅰️🅰️
Сука! А как рассчитать эту 20m памяти? Щаа…
Максимальное количество клиентов = размер зоны в байтах / размерзаписинаклиентаПардон, хуйню сморозил, давай на котиках:
Пример расчёта для 20m (20 мегабайт = 20 × 1024 × 1024 = 20 971 520 байт): 20 971 520 / 128 = 163 840То есть, зона
20m может хранить лимиты примерно для 163 тысяч уникальных клиентов одновременно.
А откуда взялось 128?
Как я написал выше nginx хранит каждого уникального клиента (ключ $binary_remote_addr или другое значение) в зоне, используя примерно 128 байт на запись.
Есть такая табличка:
< 20 000 = 4m ~80 000 = 10m ~160 000 = 20m 500 000+ = 64mДа, еще можно настроить
burst для резких пиков. burst позволяет временно превышать rate, прежде чем включится жёсткий лимит.
Например:
limit_req zone=bashdays burst=400 nodelay;
Клиенту разрешается до 400 мгновенных запросов, а затем он попадает в ограничение 200r/s.
nodelay означает, что первые 400 запросов проходят сразу, а потом начинается строгий лимит.
Теперь по мапингам и гео хуйне.
В первом блоке про гео:
1. Все пользователи получат $limited = 1 (по умолчанию).
2. Те, кто с 192.168.1.1 или из 10.0.0.0/24, получат $limited = 0 и не будут ограничены.
Во втором блоке про мапинг:
1. Если $limited = 1, то $limit = $binary_remote_addr (IP-адрес клиента).
2. Если $limited = 0, то $limit = "", и клиент не попадает в limit_req_zone.
Короче делаем что-то вроде белого списка и кто в него не входит — идёт нахуй! Надеюсь понятно объяснил.
Теперь чтобы вся эта поебота заработала, нужно прописать в нужный локейшен:
location / {
limit_req zone=bashdays burst=10 nodelay;
try_files $uri $uri/ /index.php?$args;
}
Про burst и nodelay выше уже рассказывал.Ну а чтобы отдавать нужный статус при достижении лимита, делаем:
location / {
limit_req_status 429;
limit_req zone=bashdays burst=10 nodelay;
try_files $uri $uri/ /index.php?$args;
}
Возвращаем 429 Слишком дохуя запросов, вместо стандартного 503.
Бездумно это настраивать не советую, могут пострадать обычные пользователи, а вот если всё вдумчиво сделать — спасешь свой стартап от злых писек.
➡️ Ну и сыпь в комменты свои варианты!
tags: #nginx #devops #security
—
🔔 @bashdays➡️ @gitgate
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
