DEV Community

Cover image for Lock It Down: Securing Your NGINX Site with `.htpasswd` and Ansible
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on Edited on

Lock It Down: Securing Your NGINX Site with `.htpasswd` and Ansible

Hello, I'm Maneshwar. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

Hi there! Right now, I’m building , a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. makes it easier to discover, understand, and interact with APIs in large infrastructures.

Your website is cool. But is it private?
Whether you're protecting a staging server, a Nomad dashboard, or a developer tool—Basic Auth via .htpasswd is your first line of defense.

Here's how to do it the Ansible way, with reusable roles, templated config, and one command deploys.

Quick Setup: What You'll Build

  • NGINX config auto-synced with Ansible
  • .htpasswd file created with secure credentials
  • Basic Auth enforced on protected domains
  • All configs dropped into /etc/nginx/ via rsync
  • Symlinks created in /etc/nginx/sites-enabled/
  • SSL ready for Certbot if needed

Project Structure

Start by generating the role:

ansible-galaxy init roles/nginx-conf-sync --offline
Enter fullscreen mode Exit fullscreen mode

Your structure should look like:

ansible/
├─ nginx-conf-sync-playbook.yml
├─ roles/
│  ├─ nginx-conf-sync/
│  │  ├─ files/
│  │  │  ├─ answer.dev.to
│  │  │  ├─ budi.dev.to
│  │  ├─ templates/
│  │  │  ├─ nginx.conf.j2
│  │  │  └─ options-ssl-nginx.conf.j2
│  │  ├─ tasks/
│  │  │  ├─ main.yml
│  │  │  ├─ create-nginx-confs.yml
│  │  │  ├─ certbot-setup-playbook.yml
│  │  │  └─ restart-nginx.yml
...
Enter fullscreen mode Exit fullscreen mode

Creating the .htpasswd File with Ansible

Inside roles/nginx-conf-sync/tasks/main.yml, ensure this task exists:

- name: Create .htpasswd file for basic auth
  command: htpasswd -bc /etc/nginx/.htpasswd hexmos v@6U6NYFVJ9CSk
  args:
    creates: /etc/nginx/.htpasswd
Enter fullscreen mode Exit fullscreen mode

This ensures the file is created once unless manually deleted. Want to regenerate it each time? Remove args.creates.

To clean up stale passwords before that:

- name: Remove .htpasswd file if it exists
  file:
    path: /etc/nginx/.htpasswd
    state: absent
Enter fullscreen mode Exit fullscreen mode

Add Auth to Your NGINX Config

In your nginx.conf.j2 or domain-specific confs (files/answer.dev.to, etc.), add:

server {
    server_name nomad.apps.hexmos.com;

    location / {
        auth_basic           "Administrator’s Area";
        auth_basic_user_file /etc/nginx/.htpasswd;

        proxy_pass http://localhost:4646;  # or whatever your app is
    }
}
Enter fullscreen mode Exit fullscreen mode

Ansible will rsync this into /etc/nginx/sites-available/ and symlink it.

Full Task Flow (Summary)

Your main.yml calls:

- import_tasks: create-nginx-confs.yml
- import_tasks: install-cron.yml
- import_tasks: certbot-setup-playbook.yml
- import_tasks: restart-nginx.yml
Enter fullscreen mode Exit fullscreen mode

Inside create-nginx-confs.yml, make sure you have:

- name: Ensure NGINX config directory exists
  file:
    path: "/etc/nginx/sites-available"
    state: directory

- name: Deploy main nginx.conf from template
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"

- name: Sync all nginx domain configs using rsync
  synchronize:
    src: "{{ role_path }}/files/"
    dest: "/etc/nginx/sites-available/"
    recursive: yes
    delete: yes

- name: Create symlinks in bulk
  ansible.builtin.shell: |
    for site in {{ nginx_conf_domains | join(' ') }}; do
      ln -sf "/etc/nginx/sites-available/$site" "/etc/nginx/sites-enabled/$site"
    done
Enter fullscreen mode Exit fullscreen mode

Test It

  1. Run your playbook:
ansible-playbook -i hosts.ini nginx-conf-sync-playbook.yml
Enter fullscreen mode Exit fullscreen mode
  1. Access the site in your browser.
    You’ll be prompted for a username (hexmos) and password (v@6U6NYFVJ9CSk).

  2. To reset the password:

ansible-playbook -i hosts.ini nginx-conf-sync-playbook.yml
Enter fullscreen mode Exit fullscreen mode

Just let the .htpasswd file get regenerated.

Pro Tips

  • Use htpasswd -B instead of -m to use bcrypt instead of MD5 for stronger hashing.
  • Store the username/password as Ansible Vault secrets if you're pushing this to CI.
  • Protect specific locations (like /admin) if you don’t want to auth the whole site.

That’s a Wrap

A single .htpasswd file + NGINX + Ansible = locked down and audit-friendly.
Whether you’re shipping staging sites, internal dashboards, or legacy admin panels — drop in a password wall without writing a line of shell.

Fast. Reproducible. Scriptable. Done.

helps you get all your backend APIs documented in a few minutes.

With , you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

If you're tired of updating manually or syncing collections, give it a shot.

git-lrc
*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

⭐ Star it on GitHub:

GitHub logo HexmosTech / git-lrc

Free, Micro AI Code Reviews That Run on Git Commit




GenAI today is a race car without brakes. It accelerates fast -- you describe something, and large blocks of code appear instantly. But AI agents silently break things: they remove logic, relax constraints, introduce expensive cloud calls, leak credentials, and change behavior -- without telling you. You often find out in production.

git-lrc is your braking system. It hooks into git commit and runs an AI review on every diff before it lands. 60-second setup. Completely free.

In short, git-lrc helps Prevent Outages, Breaches, and Technical Debt Before They Happen

At a glance: 10 risk categories · 100+ failure patterns tracked · every commit…

Top comments (2)

Collapse
 
nevodavid profile image
Nevo David •

pretty cool seeing someone lay it all out step by step like this - makes me think though, you ever run into a moment where quick fixes in security ended up biting back later down the line?

Collapse
 
dotallio profile image
Dotallio •

This is genuinely useful, love how you’ve automated everything with Ansible so it’s not an afterthought.

Have you ever run into edge cases with .htpasswd across different Linux distros?