# 🧰 A Beginner's Guide to NGINX and NGINX Proxy Manager

Whether you’re self-hosting applications or deploying websites in production, **reverse proxies** are one of the most powerful tools in your DevOps toolbox. At the heart of it all is **NGINX**—a versatile, open-source server that can function as a web server, reverse proxy, load balancer, and even a mail proxy.

However, writing manual NGINX configurations—especially for multiple services, subdomains, and SSL certificates—can quickly become tedious, redundant and error-prone.

That’s where **NGINX Proxy Manager (NPM)** steps in to simplify everything with a clean and user-friendly interface.

In this blog, we’ll begin with the basics of NGINX, and then walk you through how to deploy NGINX Proxy Manager in just a few steps.

---

## 🧠 What is NGINX?

**NGINX** (pronounced *engine-x*) is a high-performance, open-source web server that’s designed for scalability and efficiency. It can be used for:

* Serving static files (HTML, CSS, JavaScript)
    
* Acting as a **reverse proxy** (routing external traffic to internal services)
    
* Load balancing between servers
    
* Caching for faster delivery
    
* SSL termination (handling HTTPS connections)
    

Originally built to solve the **C10K problem**—handling 10,000+ concurrent connections—NGINX has become one of the most popular servers in the world.

## 🔄 What is a Reverse Proxy?

A **reverse proxy** acts as a gateway: it receives client requests, forwards them to the appropriate backend service, and returns the response to the client. This allows you to:

* Host multiple apps on a single server (e.g., [`app1.example.com`](http://app1.example.com), [`app2.example.com`](http://app2.example.com))
    
* Serve all apps over HTTPS using **Let’s Encrypt**
    
* Hide internal infrastructure from the public
    
* Apply rate limiting, access control, or logging policies
    

## ⚙️ Installing NGINX the Traditional Way

On most Linux distributions, you can install NGINX with:

```bash
sudo apt update -y
sudo apt install nginx -y
```

To verify NGINX is running:

```bash
systemctl status nginx
```

You should be able to visit `http://<your-server-ip>` and see the NGINX welcome page.

To configure new sites manually, you’ll edit files under `/etc/nginx/sites-available/` and link them to `/etc/nginx/sites-enabled/`

## 😵‍💫 The Problem: Manual NGINX Config is a Pain

For each new service or domain, you have to:

* Add a new subdomain
    
* Set up SSL with Let’s Encrypt
    
* Configure proxying rules
    
* Handle authentication and security settings
    
* Test your NGINX config and reload the service
    

This process is powerful but **not beginner-friendly** and quickly becomes a burden when managing many services.

## 🎉 The Solution: NGINX Proxy Manager (NPM)

**NGINX Proxy Manager** is a Docker-based application that wraps the power of NGINX in an easy-to-use **web interface**.

### 🔑 Key Features

* Intuitive web UI to manage proxy hosts
    
* Automatic SSL certificates via Let’s Encrypt
    
* Redirection and 404 host handling
    
* Access control via IP or basic auth
    
* Custom NGINX config snippets
    
* Lightweight and easy to deploy via Docker
    

## 🧱 How to Install NGINX Proxy Manager on Ubuntu/Debian

### Prerequisites

* A Linux server or cloud VPS
    
* Docker and Docker Compose installed
    
* A registered domain (optional but recommended)
    

### Step 1: Install Docker & Docker Compose

```bash
sudo apt update
sudo apt install docker.io docker-compose -y
```

Verify Docker is running:

```bash
sudo systemctl status docker
```

If inactive, enable and start it:

```bash
sudo systemctl enable docker
sudo systemctl start docker
```

### Step 2: Create the Docker Compose File

* Create a working directory:
    
    ```bash
    mkdir npm && cd npm
    ```
    
* Now create the `docker-compose.yml` file:
    
    ```yaml
    version: '3.8'
    services:
      app:
        image: 'jc21/nginx-proxy-manager:latest'
        restart: unless-stopped
        ports:
          # These ports are in format <host-port>:<container-port>
          - '80:80' # Public HTTP Port
          - '443:443' # Public HTTPS Port
          - '81:81' # Admin Web Port
    
        environment:
          # Mysql/Maria connection parameters:
          DB_MYSQL_HOST: "db"
          DB_MYSQL_PORT: 3306
          DB_MYSQL_USER: "npm"
          DB_MYSQL_PASSWORD: "npm"
          DB_MYSQL_NAME: "npm"
        volumes:
          - ./data:/data
          - ./letsencrypt:/etc/letsencrypt
        depends_on:
          - db
    
      db:
        image: 'jc21/mariadb-aria:latest'
        restart: unless-stopped
        environment:
          MYSQL_ROOT_PASSWORD: 'npm'
          MYSQL_DATABASE: 'npm'
          MYSQL_USER: 'npm'
          MYSQL_PASSWORD: 'npm'
          MARIADB_AUTO_UPGRADE: '1'
        volumes:
          - ./mysql:/var/lib/mysql
    ```
    

> 💡 **Why a database?**  
> The database stores all your proxy host settings, SSL metadata, users, and configuration changes persistently

### Step 3: Launch the Container

Run the containers:

```bash
docker-compose up -d
```

### Step 4: Access the Web Interface

Open your browser and visit:  
`http://your-server-ip:81`

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1750081729562/2645f332-454b-4411-8532-bf3d2956e1eb.png align="center")

Login with default credentials:

* **Email:** `admin@example.com`
    
* **Password:** `changeme`
    

> You’ll be prompted to change your login details after the first login.

Once you login, you’ll be redirected to your dashboard

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1750081786945/6cdda54f-96fb-405a-9bcc-7b49c0d48959.png align="center")

## 🔧 Setting Up Your First Proxy Host

1. Go to **"Proxy Hosts" &gt; "Add Proxy Host"**
    
2. Enter your **domain name** (e.g., [`npm.domain.com`](http://myapp.example.com))
    
3. Enter the **internal IP address and port** of your service (e.g., `192.168.1.100:8080`)
    
4. Enable **"Block Common Exploits"**
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1750081961598/7c209051-2b7a-47fe-b208-48cbd57e601d.png align="center")
    
5. Switch to the **SSL** tab:
    
    * Enable **SSL**
        
    * Request a **Let’s Encrypt certificate**
        
    * Enable **Force SSL**
        
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1750082023393/617953e9-3786-4b8e-9dd4-08f3014a0733.png align="center")
    
6. Click **Save**
    

> 🎉 Done! Your service is now live, secure, and reachable via your custom domain. (npm.domain.com in this case)

## 🔐 Advanced Features

* **Access Lists** – Restrict access using IP whitelisting or basic auth
    
* **Custom NGINX Directives** – Add your own caching rules, headers, or security policies
    
* **Rate Limiting** – Throttle excessive traffic and protect against DoS attacks
    
* **Redirection Hosts** – Easily forward old URLs to new destinations
    
* **404 Hosts** – Define catch-all behavior for unknown or misrouted domains
    

## 💡 Common Use Cases

* Host self-hosted apps like **Nextcloud**, **Jellyfin**, **Bitwarden**, or **Portainer**
    
* Expose internal microservices on custom subdomains
    
* Make local development tools publicly accessible with HTTPS
    
* Replace complex manual NGINX or Traefik setups with a user-friendly dashboard
    

## 🧠 Final Thoughts

NGINX is incredibly powerful, but configuring it manually can be time-consuming and error-prone.  
**NGINX Proxy Manager** simplifies this process without sacrificing flexibility.

It’s perfect for:

✅ Self-hosters  
✅ Developers managing multiple projects  
✅ Small teams hosting internal tools  
✅ Anyone who wants **easy SSL** and **quick proxy setup**
