Skip to content
Назад к блогу
Безопасность

Как создать файл .htpasswd: руководство по HTTP Basic Auth

Создайте файл .htpasswd с bcrypt или apr1, настройте HTTP Basic Auth в Apache, nginx, Docker и Kubernetes и защитите доступ. Практическое руководство 2026.

11 мин чтения

Как создать файл .htpasswd: руководство по HTTP Basic Auth

Файл .htpasswd — это серверное хранилище учётных данных для HTTP Basic Authentication: обычный текстовый файл, где каждая строка представляет собой одну пару username:hash. Чтобы создать файл .htpasswd, нужно сформировать такую строку с хешем и сохранить её там, откуда её сможет прочитать веб-сервер. Сделать это можно тремя способами:

  • Команда htpasswd (из пакета apache2-utils / httpd-tools) — канонический инструмент.
  • openssl passwd — уже установлен почти везде, дополнительный пакет не нужен.
  • В браузере — используйте генератор htpasswd, чтобы создать запись локально без единой установки и без передачи чего-либо по сети.

Однострочником дело не ограничивается. Ниже — как на самом деле работает рукопожатие Basic Auth, как создать файл тремя способами, какой из пяти форматов хеша выбрать, как подключить его к Apache, nginx, Docker, Kubernetes, Caddy и Traefik и как всё это защитить, чтобы не выложить файл с учётными данными, который сможет скачать кто угодно.

Что такое файл .htpasswd?

Каждая строка в файле .htpasswd хранит учётные данные одного пользователя в виде пары, разделённой двоеточием. Имя пользователя сохраняется как есть; пароль хранится только в виде одностороннего хеша, поэтому открытый текст никогда не попадает на диск. Анатомия одной строки bcrypt выглядит так:

admin    :    $2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
│             │
└─ username   └─ hash (algorithm prefix $2y$ + cost + salt + digest)

Сначала идёт имя пользователя, затем одно двоеточие :, а затем хеш. Имя пользователя может занимать до 255 байт и никогда не должно содержать двоеточие, поскольку именно двоеточие служит разделителем полей. Хеш несёт собственный маркер алгоритма в виде префикса ($2y$ для bcrypt, $apr1$ для Apache MD5, {SHA} для SHA-1), так что сервер знает, как его проверить, без какой-либо дополнительной настройки.

Для нескольких пользователей добавляется по одной строке на каждого:

admin:$2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
alice:$2y$10$3bQ8xY7tLp2mZ0xW5cR4fO9vK1jH6sD2nG8aQ5wE3rT7uI4oP1cm
bob:$apr1$mZ0xW5cR$4fK1jH6sD2nG8aQ5wE3rT2

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

.htpasswd против .htaccess

Эти два файла постоянно путают, потому что в Apache они идут рука об руку, но выполняют разные задачи. .htaccess — это файл конфигурации Apache для отдельного каталога. В нём хранятся директивы — в том числе те, что включают Basic Auth и указывают на хранилище учётных данных. .htpasswd — это база учётных данных: только строки username:hash, без какой-либо конфигурации.

Если коротко: .htaccess решает, что каталог требует входа и где найти список пользователей; .htpasswd — это и есть тот список пользователей. nginx вообще не использует .htaccess — его настройка Basic Auth находится в блоке server или location основной конфигурации, но он читает тот же формат учётных данных .htpasswd.

Как работает HTTP Basic Authentication

HTTP Basic Authentication — это рукопожатие по схеме «запрос — ответ», встроенное в спецификацию HTTP. Разобравшись в трёх его шагах, потом проще понять и любой сбой при диагностике:

  1. Клиент запрашивает защищённый ресурс без учётных данных.
  2. Сервер отвечает 401 Unauthorized и включает заголовок WWW-Authenticate: Basic realm="..." — это и есть запрос на аутентификацию.
  3. Клиент повторяет запрос с заголовком Authorization: Basic <base64(user:password)>. Если учётные данные совпадают со строкой в файле .htpasswd, сервер возвращает ресурс.

Это весь протокол. Ни формы входа, ни сессионного cookie, ни token. Каждый последующий запрос несёт тот же заголовок.

Запрос 401 / WWW-Authenticate

Заголовок WWW-Authenticate делает две вещи. Его token Basic сообщает клиенту, какую схему использовать, а строка realm обозначает защищаемое пространство. Браузеры показывают текст realm в диалоге входа («Сайт сообщает: …») и используют его как ключ кеша: учётные данные, введённые для одного realm, повторно применяются к другим URL-адресам в том же realm, поэтому пользователя не спрашивают заново на каждой странице.

Вот сырой обмен, перехваченный с помощью curl -i:

$ curl -i https://example.com/admin/
HTTP/2 401
www-authenticate: Basic realm="Restricted Area"

$ curl -i -u admin:s3cret https://example.com/admin/
HTTP/2 200

Заголовок Authorization: Basic

Учётные данные, которые отправляет клиент, — это base64(username:password). Это самый важный факт о безопасности Basic Auth: base64 — это кодирование, а не шифрование. Оно полностью обратимо для кого угодно, поэтому учётные данные путешествуют фактически в открытом виде. Полный цикл можно увидеть самостоятельно:

# Encode the credential the way a browser does
printf 'admin:s3cret' | base64
# → YWRtaW46czNjcmV0

# Anyone who captures the header can decode it instantly
printf 'YWRtaW46czNjcmV0' | base64 -d
# → admin:s3cret

Именно из-за этой обратимости Basic Auth должен работать поверх HTTPS — без TLS пароль может прочитать любой, кто находится на сетевом пути. Если нужно собрать или разобрать этот заголовок вручную, кодировщик/декодер Base64 выполняет то же преобразование user:password прямо в браузере.

Как создать файл .htpasswd

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

С помощью команды htpasswd

Бинарный файл htpasswd поставляется в пакете утилит Apache. Сначала установите его:

# Debian / Ubuntu
sudo apt install apache2-utils

# RHEL / CentOS / Fedora
sudo yum install httpd-tools

Создайте файл и его первого пользователя. Флаг -c означает create, и он перезапишет существующий файл — используйте его только в самый первый раз:

htpasswd -c /etc/nginx/.htpasswd admin
# prompts twice for the password, then writes the file

Чтобы добавить других пользователей, уберите -c, и тогда запись будет добавляться в конец, а не затирать файл:

htpasswd /etc/nginx/.htpasswd alice

Чтобы принудительно использовать bcrypt вместо формата по умолчанию для платформы, добавьте -B. Чтобы вывести запись в stdout, не трогая никакой файл — удобно для передачи по конвейеру в конфигурацию или Dockerfile, — объедините -b (пароль в командной строке) и -n (без файла):

htpasswd -Bbn admin 's3cret'
# → admin:$2y$10$N9qo8uLOickgx2ZMRZoMye...

Флаги, которые действительно пригодятся:

ФлагЗначение
-cСоздать новый файл (перезаписывает, если он существует) — только для первого пользователя
-BИспользовать bcrypt
-bПринять пароль как аргумент командной строки (без запроса)
-nВывести в stdout вместо записи в файл
-DУдалить указанного пользователя из файла

Один нюанс с -b: пароль попадает в историю команд оболочки. Для разовых рабочих учётных данных предпочтительнее форма с запросом пароля или вариант с браузером ниже.

Без apache2-utils — с помощью OpenSSL

Нет бинарного файла htpasswd? OpenSSL есть практически в любой системе и может сразу выдать хеш apr1. Оберните его в printf, чтобы собрать готовую строку:

printf "admin:$(openssl passwd -apr1 's3cret')\n" >> /etc/nginx/.htpasswd
# admin:$apr1$k3l4Hj9.$qN8vY7tLp2mZ0xW5cR4f.

Формат apr1 переносим между Apache и nginx, что делает этот путь наименее зависимым от пакетов на минимальной системе.

В браузере — без установки, без утечки

Если не хочется устанавливать пакет или вводить рабочий пароль в оболочку, где он окажется в ~/.bash_history, сформируйте запись на стороне клиента. Генератор htpasswd вычисляет хеши bcrypt, apr1 и SHA-1 целиком в браузере, выдаёт готовую к вставке строку user:hash и подходящий блок серверной конфигурации и ничего никуда не передаёт. Заодно создайте надёжный, уникальный пароль с помощью генератора случайных паролей вместо повторного использования старого.

Сравнение форматов паролей htpasswd

Команда htpasswd может выдавать пять форматов, и они не равноценны. Эта таблица — краткий справочник для выбора:

ФорматПрефиксС сольюСтойкостьПрименять для
bcrypt$2y$ДаСамая высокаяApache, Docker Registry, Caddy, Traefik
apr1 (Apache MD5)$apr1$ДаУмереннаяnginx (переносимый, безопасный по умолчанию)
SHA-1{SHA}НетСлабаяТолько для совместимости с устаревшими системами
crypt (DES)(нет)Да (2 символа)Очень слабаяНе используйте
plain(нет)НетНикакаяТолько для локального тестирования

Несколько замечаний, которые не помещаются в ячейку таблицы. bcrypt использует случайную соль в 16 байт и адаптивный фактор стоимости (по умолчанию 10, современная рекомендация — 12), поэтому одинаковые пароли дают разные хеши, а трудоёмкость растёт вместе с возможностями оборудования. Его единственная особенность: bcrypt обрезает пароль на 72 байтах — всё, что длиннее, молча игнорируется. apr1 выполняет 1 000 раундов MD5 с солью; намного слабее bcrypt, но реализован нативно и в Apache, и в nginx, поэтому это переносимый выбор. SHA-1 не использует соль, поэтому одинаковые пароли дают одинаковые дайджесты и применимы радужные таблицы — оставьте его только для устаревших систем. crypt и plain существуют по историческим причинам и для тестирования; ни тому, ни другому не место в продакшене.

Префиксы $2a$ / $2b$ / $2y$

Хеши bcrypt начинаются с $2a$, $2b$ или $2y$. Алгоритм за ними один и тот же, а сами хеши эквивалентны и взаимозаменяемы; буквы версий остались от старых исправлений в том, как некоторые библиотеки обрабатывали символы со старшим битом и длину строк. htpasswd от Apache выдаёт $2y$, а Caddy, Traefik и Docker Registry корректно его проверяют.

Если нужно более глубокое сравнение bcrypt с современными альтернативами, руководство bcrypt vs Argon2 vs scrypt разбирает, чем эти алгоритмы вычисления хеша паролей различаются по стоимости, требовательности к памяти и модели угроз.

Настройка Basic Auth на вашем сервере

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

Apache (.htaccess)

Поместите это в файл .htaccess в каталоге, который нужно защитить (или в блок <Directory> вашего vhost):

AuthType Basic
AuthName "Restricted Area"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user

AuthName — это строка realm, которую показывает браузер; AuthUserFile — абсолютный путь к вашему файлу учётных данных; Require valid-user принимает любого пользователя из этого списка.

nginx (auth_basic)

nginx размещает конфигурацию в блоке location или server — никакого .htaccess:

location /admin/ {
    auth_basic           "Restricted Area";
    auth_basic_user_file /etc/nginx/.htpasswd;
}

Перезагрузите командой nginx -s reload. Здесь используйте формат apr1. nginx делегирует проверку bcrypt системному crypt(), который не работает во многих сборках (подробнее в разделе диагностики), тогда как apr1 проверяется внутренними средствами на любой платформе.

Docker Registry и Kubernetes ingress-nginx

htpasswd-бэкенд приватного Docker Registry принимает только bcrypt. Сформируйте запись, смонтируйте её и укажите на неё реестру:

# Generate a bcrypt entry into a file
htpasswd -Bbn admin 's3cret' > auth/htpasswd

# Run the registry with that file
docker run -d -p 5000:5000 \
  -v "$(pwd)/auth:/auth" \
  -e REGISTRY_AUTH=htpasswd \
  -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  registry:2

Для Kubernetes ingress-nginx сохраните файл как Secret и сошлитесь на него через аннотации:

kubectl create secret generic basic-auth --from-file=auth=./auth/htpasswd
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"

Обратите внимание: ключ Secret должен называться именно auth — ingress-nginx ищет ровно этот ключ.

Caddy и Traefik

Оба ожидают хеши bcrypt. Caddy использует директиву basic_auth (вставляйте хеш bcrypt, а не открытый текст):

example.com {
    basic_auth /admin/* {
        admin $2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
    }
}

Traefik использует middleware basicauth с парами user:bcrypt-hash (экранируйте все $ под формат вашей конфигурации):

http:
  middlewares:
    admin-auth:
      basicAuth:
        users:
          - "admin:$2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"

Когда endpoint защищён, проверьте, что всё работает, из командной строки. Конструктор команд cURL соберёт за вас запрос -u user:pass, чтобы можно было подтвердить и 401, и аутентифицированный 200.

Лучшие практики безопасности

Basic Auth прост, и поэтому те немногие способы им злоупотребить легко заметить.

  • Всегда отдавайте по HTTPS. Учётные данные — это обратимый base64, поэтому обычный HTTP раскрывает пароль в канале. Терминируйте TLS перед любым защищённым endpoint, без исключений.
  • Храните файл вне корня веб-сервера. Если .htpasswd лежит в отдаваемом каталоге, ошибка в настройке может позволить кому-то его скачать. Держите его где-нибудь вроде /etc/nginx/.htpasswd, выставьте chmod 640 и сделайте владельцем пользователя веб-сервера (www-data, nginx), чтобы сервер мог его читать, а другие учётные записи — нет.
  • Используйте надёжные, уникальные пароли. Каждая учётная запись должна получить собственный пароль высокой энтропии от генератора случайных паролей и никогда его не переиспользовать. Если хотите понять, что значит «достаточно надёжный» в битах, объяснение энтропии паролей раскладывает математику по полочкам.
  • Знайте его пределы. У Basic Auth нет выхода из системы и нет сессии: браузер кеширует учётные данные для каждого realm, пока его не закроют, и пересылает их в каждом запросе. Более широкий чек-лист по хешированию, заголовкам и валидации смотрите в наших лучших практиках веб-безопасности.

Диагностика типичных ошибок

nginx: crypt_r() failed (22: Invalid argument)

Это самый частый сбой Basic Auth в nginx, и он всегда означает одно и то же: nginx попытался проверить хеш bcrypt ($2y$) на libc, в которой нет схемы Blowfish — обычно это musl в Alpine или старая glibc. Решение — сгенерировать запись заново в формате apr1, который nginx проверяет внутренними средствами на любой платформе:

printf "admin:$(openssl passwd -apr1 's3cret')\n" > /etc/nginx/.htpasswd
nginx -s reload

Переход на базовый образ, в libc которого есть поддержка bcrypt, тоже сработает, но apr1 — более простое и переносимое решение.

401 даже с правильным паролем

Когда вы уверены, что пароль верный, но всё равно получаете 401, пройдите этот чек-лист по порядку:

  1. Путь к файлу. Убедитесь, что AuthUserFile / auth_basic_user_file указывает на реальный файл (абсолютный путь, без опечаток).
  2. Права доступа. Пользователь веб-сервера должен иметь возможность читать файл. Проверьте командой sudo -u www-data cat /etc/nginx/.htpasswd.
  3. Концы строк / кодировка. Файл, отредактированный в Windows, может нести символы \r, которые портят хеш. Запустите file .htpasswd и при необходимости примените dos2unix.
  4. Устаревший кеш браузера. Браузер кеширует учётные данные для каждого realm. Проверьте в приватном окне (режим инкогнито), чтобы исключить запомненный старый пароль.
  5. Несовпадение хеша. Убедитесь, что сохранённый хеш действительно соответствует паролю — вставьте оба в режим проверки генератора htpasswd, чтобы подтвердить это, прежде чем винить конфигурацию.

Когда НЕ стоит использовать Basic Auth

Basic Auth — правильный инструмент для узкого круга задач: тестовый сайт, внутренний путь администрирования, endpoint с артефактами CI, дашборд метрик, приватный реестр. Он не требует зависимостей и настраивается за две минуты.

Это неправильный инструмент для входа в продукт. Нет выхода из системы, нет сброса пароля, нет ограничения частоты запросов, нет блокировки учётной записи и нет MFA. Учётные данные пересылаются в каждом запросе и кешируются браузером до его закрытия. Для всего, куда пользователи входят, выбирайте сессии, OAuth или OIDC. Basic Auth остаётся полезен ровно до тех пор, пока эту границу не переходят.

FAQ

Что на самом деле содержит одна строка в файле .htpasswd?

Пару username:hash, разделённую двоеточием. Хеш начинается с префикса алгоритма ($2y$ для bcrypt, $apr1$ для Apache MD5, {SHA} для SHA-1), за которым следуют соль и дайджест. Открытый пароль в файле не появляется никогда.

В чём разница между .htpasswd и .htaccess?

.htaccess — это файл конфигурации Apache для отдельного каталога: он включает Basic Auth и указывает на хранилище учётных данных. .htpasswd — это и есть то хранилище учётных данных, содержащее строки username:hash. nginx использует формат .htpasswd, но настраивает аутентификацию в своих блоках server/location, а не в .htaccess.

Как добавить, изменить или удалить пользователя в файле .htpasswd?

Чтобы добавить или изменить пользователя, выполните htpasswd /path/.htpasswd username без -c — если пользователь существует, его хеш будет обновлён. Чтобы удалить, выполните htpasswd -D /path/.htpasswd username. Используйте -c только для самого первого пользователя, поскольку этот флаг перезаписывает весь файл.

Как браузер запоминает учётные данные Basic Auth и как пользователям выйти из системы?

Браузер кеширует учётные данные с ключом по realm и автоматически пересылает их в каждом подходящем запросе. Стандартного выхода из системы нет: единственные способы очистить их — закрыть браузер или стереть его кеш. Это отсутствие выхода — одна из причин, по которым Basic Auth не подходит для аутентификации в продукте.

Можно ли использовать один файл .htpasswd для Apache и nginx одновременно?

Да, если формат хеша поддерживается обоими. apr1 (Apache MD5) нативно проверяется и Apache, и nginx везде, поэтому это самый безопасный общий выбор. bcrypt работает в Apache, но в nginx зависит от системного crypt(), который не работает в сборках на Alpine/musl.

Актуальна ли HTTP Basic Authentication в 2026 году?

Да. В качестве лёгкого барьера поверх HTTPS — внутренние инструменты, тестовые окружения, приватные реестры, endpoint мониторинга — она по-прежнему практична и не требует зависимостей. Только не путайте её с пользовательской аутентификацией в продукте, которой нужны сессии, сбросы паролей, ограничение частоты запросов и MFA, чего Basic Auth обеспечить не может.

Проверено командой Go Tools: каждая команда, блок конфигурации и формат хеша в этом руководстве были сверены с эталонным выводом htpasswd из Apache (apache2-utils) и OpenSSL.

Теги: htpasswd basic-auth http-authentication nginx apache bcrypt security

Похожие статьи

Все статьи