Skip to content
Retour au blog
Sécurité

Créer un fichier .htpasswd : guide de l'authentification Basic HTTP

Créez un fichier .htpasswd avec bcrypt ou apr1, configurez l'authentification Basic HTTP sur Apache, nginx, Docker et Kubernetes, puis sécurisez-la. Guide pratique 2026.

11 min de lecture

Créer un fichier .htpasswd : guide de l’authentification Basic HTTP

Un fichier .htpasswd est le magasin d’identifiants côté serveur pour l’authentification Basic HTTP : un fichier texte brut où chaque ligne est une paire username:hash. Pour créer un fichier .htpasswd, vous générez cette ligne hachée et l’enregistrez à un endroit que votre serveur web peut lire. Il existe trois façons de procéder :

  • La commande htpasswd (du paquet apache2-utils / httpd-tools) — l’outil canonique.
  • openssl passwd — déjà installé presque partout, sans paquet supplémentaire.
  • Dans votre navigateur — utilisez le générateur htpasswd pour produire une entrée localement, sans aucune installation et sans rien envoyer sur le réseau.

Ce guide va plus loin que la simple ligne de commande. Nous verrons comment le protocole d’échange Basic Auth fonctionne réellement, comment créer le fichier de trois façons, lequel des cinq formats de hachage choisir, comment le brancher dans Apache, nginx, Docker, Kubernetes, Caddy et Traefik, et comment tout verrouiller pour ne pas livrer un fichier d’identifiants que n’importe qui peut télécharger.

Qu’est-ce qu’un fichier .htpasswd ?

Chaque ligne d’un fichier .htpasswd contient les identifiants d’un utilisateur sous forme de paire séparée par deux-points. Le nom d’utilisateur est stocké tel quel ; le mot de passe ne l’est que sous forme de hachage à sens unique, et le texte en clair n’est donc jamais écrit sur le disque. Une ligne bcrypt ressemble à ceci :

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

Le nom d’utilisateur vient en premier, puis un seul :, puis le hachage. Un nom d’utilisateur peut aller jusqu’à 255 octets et ne doit jamais contenir de deux-points, car le deux-points est le séparateur de champs. Le hachage porte son propre marqueur d’algorithme en préfixe ($2y$ pour bcrypt, $apr1$ pour le MD5 d’Apache, {SHA} pour SHA-1) ; le serveur sait donc comment le vérifier sans configuration supplémentaire.

Pour plusieurs utilisateurs, vous ajoutez une ligne par utilisateur :

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

Les algorithmes peuvent être mélangés dans un même fichier. Le serveur lit chaque ligne, détecte le format d’après son préfixe, et vérifie l’identifiant avec l’algorithme effectivement utilisé. Ici, deux utilisateurs bcrypt et un utilisateur apr1 coexistent sans problème.

.htpasswd vs .htaccess

On confond constamment ces deux fichiers parce qu’ils vont de pair sur Apache, mais ils ont des rôles distincts. .htaccess est le fichier de configuration par répertoire d’Apache. Il contient des directives — dont celles qui activent l’authentification Basic et pointent vers votre magasin d’identifiants. .htpasswd est la base de données d’identifiants — uniquement les lignes username:hash, aucune configuration.

En bref : .htaccess décide qu’un répertoire exige une connexion et où trouver la liste des utilisateurs ; .htpasswd est cette liste d’utilisateurs. nginx n’utilise pas du tout .htaccess — sa configuration Basic Auth se trouve dans le bloc server ou location de la configuration principale, mais il lit le même format d’identifiants .htpasswd.

Comment fonctionne l’authentification Basic HTTP

L’authentification Basic HTTP est un protocole d’échange défi-réponse intégré à la spécification HTTP. Ses trois étapes valent la peine d’être connues, car elles éclairent ensuite presque tout le dépannage :

  1. Le client demande une ressource protégée sans identifiants.
  2. Le serveur répond 401 Unauthorized et inclut un en-tête WWW-Authenticate: Basic realm="..." — c’est le défi.
  3. Le client réessaie la requête avec un en-tête Authorization: Basic <base64(user:password)>. Si les identifiants correspondent à une ligne du fichier .htpasswd, le serveur renvoie la ressource.

Voilà tout le protocole. Pas de formulaire de connexion, pas de cookie de session, pas de jeton. Chaque requête suivante transporte le même en-tête.

Le défi 401 / WWW-Authenticate

L’en-tête WWW-Authenticate fait deux choses. Son jeton Basic indique au client quel schéma utiliser, et sa chaîne realm étiquette l’espace de protection. Les navigateurs affichent le texte du realm dans la boîte de dialogue de connexion (« Le site indique : … ») et l’utilisent comme clé de cache : les identifiants saisis pour un realm sont réutilisés pour d’autres URL du même realm, ce qui évite de re-solliciter l’utilisateur à chaque page.

Voici l’échange brut, capturé avec 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

L’en-tête Authorization: Basic

L’identifiant que le client envoie est base64(username:password). C’est le fait de sécurité le plus important à propos de Basic Auth : le base64 est un encodage, pas un chiffrement. Il est entièrement réversible par n’importe qui, donc l’identifiant circule sous une forme pratiquement en clair. Vous pouvez observer l’aller-retour vous-même :

# 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

Cette réversibilité est la raison pour laquelle Basic Auth doit fonctionner sur HTTPS — sans TLS, le mot de passe est lisible par quiconque se trouve sur le chemin réseau. Si vous voulez construire ou inspecter cet en-tête à la main, l’encodeur/décodeur Base64 effectue la même transformation user:password dans le navigateur.

Comment créer un fichier .htpasswd

Il existe trois façons pratiques de créer le fichier. Choisissez selon ce qui est installé et l’endroit où vous voulez que le mot de passe réside.

Avec la commande htpasswd

Le binaire htpasswd est fourni dans le paquet d’utilitaires d’Apache. Installez-le d’abord :

# Debian / Ubuntu
sudo apt install apache2-utils

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

Créez le fichier et son premier utilisateur. L’option -c signifie create, et elle écrase un fichier existant — ne l’utilisez que la toute première fois :

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

Pour ajouter d’autres utilisateurs, omettez -c afin d’ajouter à la fin au lieu d’écraser :

htpasswd /etc/nginx/.htpasswd alice

Pour forcer bcrypt au lieu du format par défaut de la plateforme, ajoutez -B. Pour afficher l’entrée sur la sortie standard sans toucher à aucun fichier — pratique pour la rediriger vers une configuration ou un Dockerfile — combinez -b (mot de passe sur la ligne de commande) et -n (pas de fichier) :

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

Les options que vous utiliserez vraiment :

OptionSignification
-cCréer un nouveau fichier (écrase s’il existe) — premier utilisateur uniquement
-BUtiliser bcrypt
-bPrendre le mot de passe comme argument de ligne de commande (sans invite)
-nAfficher sur la sortie standard au lieu d’écrire un fichier
-DSupprimer du fichier l’utilisateur nommé

Une mise en garde avec -b : le mot de passe finit dans l’historique de votre shell. Pour des identifiants de production ponctuels, préférez la forme avec invite ou l’option du navigateur ci-dessous.

Sans apache2-utils — avec OpenSSL

Pas de binaire htpasswd ? OpenSSL est présent sur quasiment tous les systèmes et peut produire directement un hachage apr1. Enveloppez-le dans printf pour construire une ligne complète :

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

Le format apr1 est portable à la fois sur Apache et nginx, ce qui en fait la voie la moins dépendante sur une machine minimale.

Dans le navigateur — aucune installation, aucune fuite

Si vous ne voulez pas installer de paquet, ou si vous préférez ne pas taper un mot de passe de production dans un shell où il atterrit dans ~/.bash_history, générez l’entrée côté client. Le générateur htpasswd calcule les hachages bcrypt, apr1 et SHA-1 entièrement dans votre navigateur, vous remet une ligne user:hash prête à coller ainsi qu’un bloc de configuration serveur correspondant, et ne transmet jamais rien. Tant que vous y êtes, créez un mot de passe fort et unique avec le générateur de mot de passe aléatoire plutôt que d’en réutiliser un.

Comparatif des formats de mot de passe htpasswd

La commande htpasswd peut émettre cinq formats, et ils ne se valent pas. Ce tableau est la référence rapide pour en choisir un :

FormatPréfixeSaléRobustesseÀ utiliser pour
bcrypt$2y$OuiLe plus robusteApache, Docker Registry, Caddy, Traefik
apr1 (MD5 d’Apache)$apr1$OuiModéréenginx (portable, valeur par défaut sûre)
SHA-1{SHA}NonFaibleCompatibilité héritée uniquement
crypt (DES)(aucun)Oui (2 caractères)Très faibleÀ éviter
plain(aucun)NonAucuneTests locaux uniquement

Quelques remarques qui n’entrent pas dans une case de tableau. bcrypt utilise un sel aléatoire de 16 octets et un facteur de coût adaptatif (par défaut 10, recommandation moderne 12) : deux mots de passe identiques produisent donc des hachages différents, et le facteur de travail suit l’évolution du matériel. Sa seule particularité : bcrypt tronque le mot de passe à 72 octets — tout ce qui dépasse est ignoré silencieusement. apr1 exécute 1 000 tours de MD5 salé ; bien plus faible que bcrypt, mais implémenté nativement par Apache et nginx, d’où son statut de choix portable. SHA-1 n’est pas salé, donc des mots de passe identiques produisent des empreintes identiques et les tables arc-en-ciel s’appliquent — réservez-le aux systèmes hérités. crypt et plain existent pour des raisons historiques et de test ; ni l’un ni l’autre n’a sa place en production.

Les préfixes $2a$ / $2b$ / $2y$

Vous verrez des hachages bcrypt commencer par $2a$, $2b$ ou $2y$. C’est le même algorithme et ils produisent des hachages équivalents et interchangeables ; les lettres de version sont des reliquats de corrections de bugs historiques dans la manière dont certaines bibliothèques géraient les caractères à bit de poids fort et la longueur des chaînes. Le htpasswd d’Apache émet $2y$, et Caddy, Traefik et Docker Registry le vérifient tous correctement.

Si vous voulez la comparaison approfondie de bcrypt face aux alternatives modernes, le guide bcrypt vs Argon2 vs scrypt explique en quoi ces algorithmes de hachage de mot de passe diffèrent en coût, en dureté mémoire et en modèle de menace.

Configurer Basic Auth sur votre serveur

Un fichier d’identifiants ne fait rien tout seul — il faut indiquer à votre serveur de l’exiger. Voici six plateformes.

Apache (.htaccess)

Placez ceci dans un fichier .htaccess du répertoire que vous voulez protéger (ou dans un bloc <Directory> de votre vhost) :

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

AuthName est la chaîne de realm que le navigateur affiche ; AuthUserFile est le chemin absolu vers votre fichier d’identifiants ; Require valid-user accepte tout utilisateur qui y figure.

nginx (auth_basic)

nginx place la configuration dans un bloc location ou server — il n’y a pas de .htaccess :

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

Rechargez avec nginx -s reload. Utilisez ici le format apr1. nginx délègue la vérification de bcrypt au crypt() du système, qui échoue sur de nombreuses compilations (plus de détails dans la section dépannage), tandis qu’apr1 est vérifié en interne sur toutes les plateformes.

Docker Registry & ingress-nginx de Kubernetes

Le backend htpasswd d’un Docker Registry privé n’accepte que bcrypt. Générez l’entrée, montez-la, et faites pointer le registre dessus :

# 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

Pour l’ingress-nginx de Kubernetes, stockez le fichier sous forme de Secret et référencez-le via des annotations :

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"

Notez que la clé du Secret doit être nommée auth — ingress-nginx recherche exactement cette clé.

Caddy & Traefik

Tous deux attendent des hachages bcrypt. Caddy utilise la directive basic_auth (collez le hachage bcrypt, pas le texte en clair) :

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

Traefik utilise un middleware basicauth, avec des paires user:bcrypt-hash (échappez tout $ selon le format de votre configuration) :

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

Une fois un point d’accès protégé, vérifiez qu’il fonctionne en ligne de commande. Le constructeur de commande cURL assemble pour vous la requête -u user:pass afin de confirmer aussi bien le 401 que le 200 authentifié.

Bonnes pratiques de sécurité

Basic Auth est simple, ce qui rend faciles à repérer les quelques façons d’en faire mauvais usage.

  • Servez toujours via HTTPS. L’identifiant est du base64 réversible, donc le HTTP en clair expose le mot de passe sur le réseau. Terminez TLS devant tout point d’accès protégé, sans exception.
  • Stockez le fichier hors de la racine web. Si .htpasswd se trouve dans un répertoire servi, une mauvaise configuration peut permettre à quelqu’un de le télécharger. Conservez-le quelque part comme /etc/nginx/.htpasswd, appliquez chmod 640, et faites-en le propriétaire l’utilisateur du serveur web (www-data, nginx) pour que le serveur puisse le lire et que les autres comptes ne le puissent pas.
  • Utilisez des mots de passe forts et uniques. Chaque compte devrait recevoir son propre mot de passe à haute entropie issu du générateur de mot de passe aléatoire, jamais réutilisé. Si vous voulez comprendre ce que « assez fort » signifie en bits, l’explication de l’entropie des mots de passe détaille le calcul.
  • Connaissez ses limites. Basic Auth n’a ni déconnexion ni session : le navigateur met l’identifiant en cache par realm jusqu’à sa fermeture, et il est renvoyé à chaque requête. Pour une liste de contrôle plus large sur le hachage, les en-têtes et la validation, consultez nos bonnes pratiques de sécurité web.

Résolution des erreurs courantes

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

C’est l’échec d’authentification Basic le plus courant de nginx, et il signifie toujours la même chose : nginx a tenté de vérifier un hachage bcrypt ($2y$) sur une libc qui n’inclut pas le schéma Blowfish — typiquement la musl d’Alpine ou une glibc plus ancienne. La solution consiste à régénérer l’entrée en apr1, que nginx vérifie en interne sur n’importe quelle plateforme :

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

Passer à une image de base dont la libc prend en charge bcrypt fonctionne aussi, mais apr1 est la solution la plus simple et la plus portable.

Un 401 même avec le bon mot de passe

Lorsque vous êtes certain que le mot de passe est correct mais que vous obtenez quand même un 401, parcourez cette liste de contrôle dans l’ordre :

  1. Chemin du fichier. Vérifiez que AuthUserFile / auth_basic_user_file pointe vers le fichier réel (chemin absolu, sans faute de frappe).
  2. Permissions. L’utilisateur du serveur web doit pouvoir lire le fichier. Vérifiez avec sudo -u www-data cat /etc/nginx/.htpasswd.
  3. Fins de ligne / encodage. Un fichier édité sous Windows peut porter des caractères \r qui corrompent le hachage. Lancez file .htpasswd et appliquez dos2unix si nécessaire.
  4. Cache de navigateur obsolète. Le navigateur met les identifiants en cache par realm. Testez dans une fenêtre privée/incognito pour écarter un ancien mot de passe mémorisé.
  5. Hachage non concordant. Vérifiez que le hachage stocké correspond bien au mot de passe — collez les deux dans le mode de vérification du générateur htpasswd pour confirmer avant d’incriminer la configuration.

Quand NE PAS utiliser Basic Auth

Basic Auth est le bon outil pour un ensemble restreint de tâches : un site de préproduction, un chemin d’administration interne, un point d’accès aux artefacts d’intégration continue, un tableau de bord de métriques, un registre privé. Il est sans dépendance et se met en place en deux minutes.

C’est le mauvais outil pour une connexion produit. Pas de déconnexion, pas de réinitialisation de mot de passe, pas de limitation de débit, pas de verrouillage de compte, et pas de MFA. Les identifiants sont renvoyés à chaque requête et mis en cache par le navigateur jusqu’à sa fermeture. Pour tout ce où des utilisateurs se connectent, tournez-vous plutôt vers les sessions, OAuth ou OIDC. Gardez Basic Auth pour les cas où ces fonctions ne manquent à personne.

FAQ

Que contient réellement une seule ligne d’un fichier .htpasswd ?

Une paire username:hash séparée par un deux-points. Le hachage commence par un préfixe d’algorithme ($2y$ pour bcrypt, $apr1$ pour le MD5 d’Apache, {SHA} pour SHA-1), suivi du sel et de l’empreinte. Le mot de passe en clair n’apparaît jamais dans le fichier.

Quelle est la différence entre .htpasswd et .htaccess ?

.htaccess est le fichier de configuration par répertoire d’Apache — il active Basic Auth et pointe vers le magasin d’identifiants. .htpasswd est ce magasin d’identifiants, qui contient les lignes username:hash. nginx utilise le format .htpasswd mais configure l’authentification dans ses blocs server/location, et non dans .htaccess.

Comment ajouter, modifier ou supprimer un utilisateur dans un fichier .htpasswd ?

Pour ajouter ou modifier un utilisateur, lancez htpasswd /path/.htpasswd username sans -c — si l’utilisateur existe, son hachage est mis à jour. Pour en supprimer un, lancez htpasswd -D /path/.htpasswd username. N’utilisez -c que pour le tout premier utilisateur, car il écrase l’intégralité du fichier.

Comment le navigateur mémorise-t-il les identifiants Basic Auth, et comment les utilisateurs se déconnectent-ils ?

Le navigateur met les identifiants en cache par clé de realm et les renvoie automatiquement à chaque requête correspondante. Il n’y a pas de déconnexion standard : les seuls moyens de les effacer sont de fermer le navigateur ou de vider son cache. Cette absence de déconnexion est l’une des raisons pour lesquelles Basic Auth ne convient pas à l’authentification produit.

Puis-je utiliser le même fichier .htpasswd pour Apache et nginx à la fois ?

Oui, tant que le format de hachage est pris en charge par les deux. apr1 (MD5 d’Apache) est vérifié nativement par Apache et nginx partout, c’est donc le choix partagé le plus sûr. bcrypt fonctionne sur Apache mais, sur nginx, dépend du crypt() du système, qui échoue sur les compilations Alpine/musl.

L’authentification Basic HTTP est-elle encore pertinente en 2026 ?

Oui. En tant que barrière légère par-dessus HTTPS — outils internes, environnements de préproduction, registres privés, points d’accès de supervision — elle reste pratique et sans dépendance. Ne la confondez simplement pas avec l’authentification produit destinée aux utilisateurs, qui exige des sessions, des réinitialisations, une limitation de débit et une MFA que Basic Auth ne peut pas fournir.

Vérifié par l’équipe Go Tools : chaque commande, bloc de configuration et format de hachage de ce guide a été contrôlé par rapport à la sortie de référence d’Apache htpasswd (apache2-utils) et d’OpenSSL.

Tags: htpasswd basic-auth http-authentication nginx apache bcrypt security

Articles connexes

Voir tous les articles