Ollama_Nginx / scripts /generate_htpasswd.py
GitLab CI
Deploy commit 2b86043c via GitLab CI
497602c
Raw History Blame Contribute Delete
3.62 kB
#!/usr/bin/env python3
"""
Generate .htpasswd file for Nginx Basic Authentication.
Uses NGINX_USERNAME and NGINX_PASSWORD environment variables.
Supports bcrypt hashing with fallback mechanisms.
"""
import os
import sys
def generate_htpasswd():
"""
Generate an .htpasswd file for Nginx Basic Authentication.
Creates a password file with the specified username and password, hashed using
the most secure available method. The file is saved to the path specified by
HTPASSWD_PATH environment variable (default: /etc/nginx/.htpasswd).
The function attempts to hash the password in the following order of preference:
1. bcrypt (most secure, recommended for modern Nginx)
2. openssl passwd with SHA-512 (-6 option)
3. crypt module with SHA-512 method
The generated file is created with read permissions for owner and group (0640).
Environment Variables:
NGINX_USERNAME: Username for authentication. Defaults to "admin" if not set.
NGINX_PASSWORD: Password for authentication. Must be set and non-empty.
HTPASSWD_PATH: Path where the .htpasswd file will be created.
Defaults to "/etc/nginx/.htpasswd".
Raises:
SystemExit: If NGINX_PASSWORD is not set or empty (exit code 1).
If password hashing fails (exit code 1).
If file creation fails (exit code 1).
Returns:
None: Prints success/error messages to stdout/stderr.
Example:
Set environment variables and run:
>>> export NGINX_USERNAME=user
>>> export NGINX_PASSWORD=secret
>>> export HTPASSWD_PATH=/tmp/.htpasswd
>>> generate_htpasswd()
[SUCCESS] .htpasswd created successfully at /tmp/.htpasswd for user 'user'.
"""
username = os.getenv("NGINX_USERNAME", "admin").strip()
password = os.getenv("NGINX_PASSWORD", "").strip()
if not password:
print("[ERROR] NGINX_PASSWORD environment variable is not set or empty.", file=sys.stderr)
sys.exit(1)
target_path = os.getenv("HTPASSWD_PATH", "/etc/nginx/.htpasswd")
# Attempt bcrypt hashing first (most secure and standard for modern Nginx)
hashed_entry = None
try:
import bcrypt
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(rounds=12)).decode('utf-8')
hashed_entry = f"{username}:{hashed_password}\n"
except ImportError:
pass
# Fallback to crypt module or openssl if bcrypt is not available
if not hashed_entry:
try:
import subprocess
res = subprocess.run(["openssl", "passwd", "-6", password], capture_output=True, text=True, check=True)
hashed_entry = f"{username}:{res.stdout.strip()}\n"
except Exception:
try:
import crypt
hashed_password = crypt.crypt(password, crypt.mksalt(crypt.METHOD_SHA512))
hashed_entry = f"{username}:{hashed_password}\n"
except Exception as e:
print(f"[ERROR] Could not hash password: {e}", file=sys.stderr)
sys.exit(1)
try:
os.makedirs(os.path.dirname(target_path), exist_ok=True)
with open(target_path, "w", encoding="utf-8") as f:
f.write(hashed_entry)
os.chmod(target_path, 0o640)
print(f"[SUCCESS] .htpasswd created successfully at {target_path} for user '{username}'.")
except Exception as e:
print(f"[ERROR] Failed to write {target_path}: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
generate_htpasswd()