ติดตั้งและใช้งาน Nginx Proxy Manager บน VPS: Web UI จัดการ Reverse Proxy และ SSL

ถ้าคุณรันหลาย Service บน VPS เดียวกัน ไม่ว่าจะเป็น WordPress, Node.js, Grafana หรือ Portainer คุณคงรู้ดีว่าปัญหาหลักคือการจัดการ Port และ SSL นั้นยุ่งยากและต้องเขียน Nginx config เองทุกครั้ง Nginx Proxy Manager (NPM) คือเครื่องมือที่แก้ปัญหานี้ได้อย่างตรงจุด ด้วย Web UI ที่สวยงามและใช้งานง่าย ทำให้คุณตั้ง Reverse Proxy และออก SSL Certificate ผ่าน Let's Encrypt ได้ในไม่กี่คลิก โดยไม่ต้องแตะ Nginx config แม้แต่บรรทัดเดียว

Nginx Proxy Manager คืออะไร

Nginx Proxy Manager คือ Web Application ที่ทำหน้าที่เป็น Frontend สำหรับจัดการ Nginx Reverse Proxy ผ่าน UI แทนที่จะต้องเขียน /etc/nginx/sites-available/mysite.conf ด้วยมือ คุณเพียงแค่กรอกข้อมูล Domain Name, Forward Hostname และ Port ใน UI แล้วกด Save ระบบจะสร้าง Nginx config และออก SSL ให้อัตโนมัติ

NPM รันผ่าน Docker

NPM ถูก Distribute เป็น Docker Image ทำให้ติดตั้งและ Upgrade ง่ายมาก ไม่กระทบกับ Package อื่นบน Server และสามารถลบออกได้สะอาดโดยไม่มีไฟล์ค้างในระบบ

Feature หลักของ Nginx Proxy Manager

เปรียบเทียบ NPM vs ตัวเลือกอื่น

เหมาะสำหรับ: VPS ที่รันหลาย Service โดยไม่อยากเขียน Nginx config ด้วยมือ, มือใหม่ที่ต้องการ UI ช่วย, หรือทีมที่ต้องการ Delegate การจัดการ Proxy ให้คนอื่นโดยไม่ต้อง SSH เข้า Server

Prerequisites ก่อนติดตั้ง

ก่อนเริ่มติดตั้ง Nginx Proxy Manager ตรวจสอบให้แน่ใจว่าคุณมีสิ่งต่อไปนี้ครบถ้วน

เปิด Port ใน UFW Firewall

NPM ต้องการ Port 3 ตัว ได้แก่ Port 80 (HTTP), 443 (HTTPS) และ 81 (NPM Web UI) ตรวจสอบและเปิด Port เหล่านี้ด้วยคำสั่ง

# เปิด Port 80 (HTTP) และ 443 (HTTPS) — จำเป็นสำหรับ Reverse Proxy และ SSL
ufw allow 80/tcp
ufw allow 443/tcp

# เปิด Port 81 สำหรับ NPM Web UI (ชั่วคราว — แนะนำให้ปิดทีหลัง)
ufw allow 81/tcp

# ตรวจสอบสถานะ
ufw status numbered

Security Note: Port 81 ควรเปิดเฉพาะช่วง Setup และ Maintenance เท่านั้น หลัง Setup เสร็จควร Block Port 81 จาก Public Internet แล้วใช้ SSH Tunnel แทน (อธิบายในหัวข้อ Security Hardening)

ติดตั้ง Nginx Proxy Manager ด้วย Docker Compose

วิธีที่แนะนำในการติดตั้ง NPM คือผ่าน Docker Compose ซึ่งทำให้ Manage ง่ายและ Reproducible

ขั้นตอนการติดตั้ง

  1. สร้าง Directory สำหรับ NPM
    mkdir -p ~/npm && cd ~/npm
  2. สร้างไฟล์ docker-compose.yml

    สร้างไฟล์ docker-compose.yml ใน directory ที่เพิ่งสร้าง

    nano ~/npm/docker-compose.yml

    แล้วใส่เนื้อหาต่อไปนี้ลงในไฟล์ (เปลี่ยน Password ให้แข็งแกร่ง)

    version: '3.8'
    services:
      app:
        image: 'jc21/nginx-proxy-manager:latest'
        restart: unless-stopped
        ports:
          - '80:80'
          - '443:443'
          - '81:81'
        volumes:
          - ./data:/data
          - ./letsencrypt:/etc/letsencrypt
    
      db:
        image: 'jc21/mariadb-aria:latest'
        restart: unless-stopped
        environment:
          MYSQL_ROOT_PASSWORD: 'npm_root_pw_changeme'
          MYSQL_DATABASE: 'npm'
          MYSQL_USER: 'npm'
          MYSQL_PASSWORD: 'npm_pw_changeme'
        volumes:
          - ./mysql:/var/lib/mysql
  3. รัน Docker Compose
    cd ~/npm && docker compose up -d

    Docker จะดึง Image ลงมาและเริ่ม Container ทั้งสองตัว (app และ db) ครั้งแรกอาจใช้เวลา 1–2 นาที

  4. ตรวจสอบว่า Container รันอยู่
    cd ~/npm && docker compose ps

    ควรเห็น Container ทั้งสองตัวมีสถานะ Up

  5. เข้า Web UI ครั้งแรก

    เปิด Browser แล้วไปที่ http://YOUR_VPS_IP:81 (แทนที่ YOUR_VPS_IP ด้วย IP จริงของ VPS คุณ)

หมายเหตุ: ถ้ามี Nginx หรือ Apache รันอยู่บน Port 80/443 อยู่แล้ว ต้องหยุด Service เหล่านั้นก่อน ไม่เช่นนั้น Docker จะ Bind Port ไม่ได้ ใช้คำสั่ง systemctl stop nginx หรือ systemctl stop apache2 แล้ว Disable ด้วย systemctl disable nginx

First Login และเปลี่ยน Password

เมื่อเข้า Web UI ที่ Port 81 ครั้งแรก ระบบจะแสดงหน้า Login ให้ใช้ข้อมูลเริ่มต้นดังนี้

หลัง Login สำเร็จ NPM จะบังคับให้เปลี่ยน Email และ Password ทันทีผ่าน Dialog ที่ปรากฏขึ้นมา ห้ามข้ามขั้นตอนนี้

แนะนำสำหรับ First Login

เพิ่ม Proxy Host ตัวแรก

Proxy Host คือการ Map Domain ให้ชี้ไปยัง Service ที่รันอยู่บน Port ใด Port หนึ่งบน Server (หรือ Container ใน Network เดียวกัน) พร้อมกับออก SSL Certificate ให้อัตโนมัติ

วิธีเพิ่ม Proxy Host

  1. ไปที่ Hosts → Proxy Hosts → Add Proxy Host

    คลิกที่เมนู Hosts ด้านบน แล้วเลือก Proxy Hosts จากนั้นคลิกปุ่ม Add Proxy Host สีเขียวด้านขวา

  2. กรอกข้อมูล Details tab
    • Domain Names: ใส่โดเมนของคุณ เช่น app.example.com (กด Enter หลังพิมพ์)
    • Scheme: เลือก http (สำหรับ Service ที่รันด้วย HTTP ปกติ)
    • Forward Hostname / IP: ใส่ IP หรือ Container name ของ Service (เช่น localhost หรือ wordpress ถ้าอยู่ใน Docker network เดียวกัน)
    • Forward Port: Port ที่ Service ฟังอยู่ เช่น 8080
    • Block Common Exploits: เปิดไว้ (แนะนำ)
    • Websockets Support: เปิดถ้า Service ใช้ WebSocket (เช่น Socket.io, Grafana Live)
  3. ตั้งค่า SSL ใน tab SSL
    • คลิก Tab SSL
    • เลือก Request a new SSL Certificate จาก Dropdown
    • เปิด Force SSL — บังคับ Redirect HTTP → HTTPS
    • เปิด HTTP/2 Support — ช่วยความเร็ว
    • ใส่ Email Address สำหรับ Let's Encrypt notification
    • ติ๊ก I Agree to the Let's Encrypt Terms of Service
  4. กด Save

    NPM จะสร้าง Nginx config และขอ SSL Certificate จาก Let's Encrypt ทันที กระบวนการนี้ใช้เวลาประมาณ 15–30 วินาที หลังจากนั้น Proxy Host จะมีสถานะ Online สีเขียว

DNS ต้องพร้อมก่อน: ก่อน NPM จะขอ SSL Certificate ได้สำเร็จ DNS ของโดเมนต้องชี้มาที่ IP ของ VPS แล้ว และ Propagate แล้ว (ตรวจสอบที่ dnschecker.org) ถ้า DNS ยังไม่พร้อม SSL จะ Fail และ Proxy Host จะแสดงสถานะ Offline

ตัวอย่างใช้งานจริง: รัน 3 Service บน VPS เดียว

สถานการณ์นี้พบบ่อยมาก: คุณรัน WordPress, Grafana และ Portainer บน VPS เดียว และต้องการให้แต่ละ Service มี Domain ของตัวเองพร้อม SSL โดยไม่ต้องจำ Port

Domain Mapping ที่ต้องการ

ขั้นตอนสำหรับ WordPress (Port 8080)

# ใน NPM Web UI
Domain Names: blog.example.com
Scheme: http
Forward Hostname / IP: localhost
Forward Port: 8080
Block Common Exploits: ON
Websockets Support: OFF
SSL: Request new cert, Force SSL ON, HTTP/2 ON

ขั้นตอนสำหรับ Grafana (Port 3000)

# ใน NPM Web UI
Domain Names: monitor.example.com
Scheme: http
Forward Hostname / IP: localhost
Forward Port: 3000
Block Common Exploits: ON
Websockets Support: ON  ← Grafana ใช้ WebSocket สำหรับ Live Dashboard
SSL: Request new cert, Force SSL ON, HTTP/2 ON

ขั้นตอนสำหรับ Portainer (Port 9000)

# ใน NPM Web UI
Domain Names: docker.example.com
Scheme: http
Forward Hostname / IP: localhost
Forward Port: 9000
Block Common Exploits: ON
Websockets Support: ON  ← Portainer ใช้ WebSocket
SSL: Request new cert, Force SSL ON, HTTP/2 ON

สำคัญมาก: ถ้า NPM และ Service ต่าง ๆ รันอยู่ใน Docker Container ด้วยกัน การใช้ localhost อาจไม่ทำงานเสมอไป เพราะ Container แต่ละตัวมี Network Namespace แยกกัน วิธีที่ถูกต้องคือการใช้ Docker Network ร่วมกัน ดูหัวข้อถัดไป

Docker Network — วิธีที่ถูกต้องสำหรับ Container-to-Container

เมื่อทั้ง NPM และ Services รันใน Docker Container การเชื่อมต่อกันที่ถูกต้องและ Stable ที่สุดคือการใช้ Docker Network ร่วมกัน แล้วใช้ Container Name แทน IP Address หรือ localhost เพราะ Container Name จะไม่เปลี่ยนแม้ Container จะ Restart และ IP เปลี่ยน

สร้าง Custom Docker Network

# สร้าง Network ชื่อ npm_network
docker network create npm_network

docker-compose.yml แบบมี Network

แก้ไขไฟล์ ~/npm/docker-compose.yml ให้เพิ่ม Network config

version: '3.8'
services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '443:443'
      - '81:81'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - npm_network

  db:
    image: 'jc21/mariadb-aria:latest'
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'npm_root_pw_changeme'
      MYSQL_DATABASE: 'npm'
      MYSQL_USER: 'npm'
      MYSQL_PASSWORD: 'npm_pw_changeme'
    volumes:
      - ./mysql:/var/lib/mysql
    networks:
      - npm_network

networks:
  npm_network:
    external: true

docker-compose.yml สำหรับ Service ที่ต้องการ Proxy

Service อื่น (เช่น WordPress) ต้องอยู่ใน Network เดียวกัน

version: '3.8'
services:
  wordpress:
    image: wordpress:latest
    restart: unless-stopped
    container_name: wordpress  # ชื่อนี้จะใช้เป็น Forward Hostname ใน NPM
    environment:
      WORDPRESS_DB_HOST: wp_db
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: wp_pass_changeme
    volumes:
      - ./wp_data:/var/www/html
    networks:
      - npm_network  # อยู่ใน npm_network เดียวกัน

  wp_db:
    image: mysql:8.0
    restart: unless-stopped
    container_name: wp_db
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wp_user
      MYSQL_PASSWORD: wp_pass_changeme
      MYSQL_ROOT_PASSWORD: root_pass_changeme
    volumes:
      - ./wp_mysql:/var/lib/mysql
    networks:
      - npm_network

networks:
  npm_network:
    external: true

เมื่อทุก Container อยู่ใน npm_network เดียวกัน ในการตั้ง Proxy Host ให้ใช้ Container Name (wordpress) แทน localhost ใน Forward Hostname และ Port 80 (ไม่ใช่ 8080 เพราะ Map Port ใช้สำหรับ Host-to-Container เท่านั้น ภายใน Network Container ใช้ Port ตรง ๆ)

ตรวจสอบ Network

# ดูว่า Container ใดอยู่ใน npm_network บ้าง
docker network inspect npm_network

# ดู Container ทั้งหมดที่รันอยู่
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

SSL Certificate — Let's Encrypt และ Wildcard

NPM จัดการ SSL Certificate ได้ครบถ้วนทั้ง Single Domain และ Wildcard Cert โดยไม่ต้องใช้ Certbot แยกต่างหาก

SSL Certificates Tab

ไปที่เมนู SSL Certificates เพื่อดู Certificate ทั้งหมดที่มีอยู่ รวมถึงวันหมดอายุ NPM จะ Renew Certificate อัตโนมัติก่อนหมดอายุ ไม่ต้องทำอะไรเพิ่มเติม

Wildcard Certificate (*.example.com)

Wildcard Certificate ครอบคลุม Subdomain ทุกตัวของ Domain ด้วย Certificate เดียว เช่น *.example.com ครอบคลุม blog.example.com, monitor.example.com, docker.example.com ทั้งหมด ข้อดีคือไม่ต้องขอ cert แยกสำหรับแต่ละ Subdomain

Wildcard Cert ต้องใช้ DNS Challenge (ไม่ใช่ HTTP Challenge) เพราะต้องพิสูจน์ว่าคุณควบคุม DNS ของ Domain ได้ NPM รองรับ DNS Provider หลายตัว เช่น Cloudflare, Route 53, Namecheap

ขั้นตอน Wildcard Cert ด้วย Cloudflare DNS Challenge

  1. ได้รับ Cloudflare API Token

    เข้า Cloudflare Dashboard → Profile → API Tokens → Create Token → เลือก Template "Edit zone DNS" แล้วจำกัด Zone เฉพาะ Domain ของคุณ

  2. เพิ่ม SSL Certificate ใน NPM

    ไปที่ SSL Certificates → Add SSL Certificate → Let's Encrypt

    • Domain Names: *.example.com และ example.com (ใส่ทั้งสองเพื่อครอบคลุม root domain ด้วย)
    • Use a DNS Challenge: เปิด
    • DNS Provider: เลือก Cloudflare
    • Credentials File Content: ใส่ dns_cloudflare_api_token = YOUR_CF_API_TOKEN
    • Propagation Seconds: 120 (รอ DNS Propagate 2 นาที)
  3. กด Save

    NPM จะสร้าง TXT Record ใน Cloudflare ผ่าน API เพื่อ Verify Domain แล้วออก Wildcard Certificate

  4. นำ Wildcard Cert ไปใช้กับ Proxy Host

    เมื่อเพิ่ม Proxy Host ใหม่ ในแท็ป SSL เลือก Wildcard cert ที่สร้างไว้ แทนการขอ cert ใหม่

Auto-Renewal

NPM จัดการ Renew Certificate อัตโนมัติ ไม่ต้องตั้ง Cron Job เพิ่มเติม Let's Encrypt cert มีอายุ 90 วัน NPM จะ Renew ก่อนหมดอายุ 30 วัน

Access List — จำกัดการเข้าถึง

Access List ช่วยให้คุณจำกัดว่าใครสามารถเข้าถึง Proxy Host ได้บ้าง มีสองรูปแบบหลัก: IP Whitelist และ HTTP Basic Authentication

สร้าง Access List

ไปที่เมนู Access Lists → Add Access List

รูปแบบที่ 1: IP Whitelist

จำกัดการเข้าถึงเฉพาะ IP ที่กำหนด เหมาะสำหรับ Internal Tools เช่น Admin Panel

# ใน Access List Configuration
Name: "My Home IP"
Allow: 203.0.113.10  # IP บ้านของคุณ
Allow: 10.0.0.0/8   # IP Range ของ Internal Network
Deny: All (ติ๊กที่ "Satisfy any" = OFF เพื่อให้เป็น Whitelist)

รูปแบบที่ 2: HTTP Basic Authentication

เพิ่ม Username/Password ให้ Service ที่ไม่มี Login ในตัวเอง เช่น Netdata Dashboard หรือ Simple Web App

# ใน Access List — Tab "Authorization"
เพิ่ม Username และ Password ได้หลายคู่
NPM จะสร้าง htpasswd ให้อัตโนมัติ

นำ Access List ไปใช้กับ Proxy Host

เมื่อสร้าง Access List แล้ว ไปแก้ไข Proxy Host แล้วเลือก Access List ที่ต้องการในฟิลด์ Access List ใน Details tab

Custom Nginx Config (Advanced)

แต่ละ Proxy Host มี Advanced tab ที่ให้คุณใส่ Nginx directive เพิ่มเติมได้โดยตรง เหมาะสำหรับการปรับแต่งที่ UI ปกติไม่รองรับ

ตัวอย่าง Custom Config ที่ใช้บ่อย

เพิ่ม Upload Size สำหรับ WordPress

# ใส่ใน Advanced tab ของ Proxy Host
client_max_body_size 100m;

ตั้ง Timeout สำหรับ Long-running Request

proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;

ส่ง Header ต้นฉบับสำหรับ WordPress (Real IP)

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;

เพิ่ม Security Headers

add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

ปิด Buffering สำหรับ Streaming / Server-Sent Events

proxy_buffering off;
proxy_cache off;

ข้อควรระวัง: Custom config ใน Advanced tab ต้องเป็น Nginx directive ที่ถูกต้องเท่านั้น ถ้าใส่ directive ที่ผิด Syntax NPM จะแสดงข้อผิดพลาดและไม่ Save ตรวจสอบ Syntax ก่อนนำไปใช้เสมอ

Redirect Host

Redirection Host ใช้สำหรับ Redirect Domain หนึ่งไปยังอีก URL อย่างง่าย เช่น Redirect example.com ไปยัง www.example.com หรือ Redirect Domain เก่าไปยัง Domain ใหม่

วิธีตั้งค่า Redirect Host

  1. ไปที่ Hosts → Redirection Hosts → Add Redirection Host
  2. กรอกข้อมูล
    • Domain Names: Domain ต้นทาง เช่น example.com (ไม่มี www)
    • Scheme: https
    • Forward Domain Name: Domain ปลายทาง เช่น www.example.com
    • HTTP Code: เลือก 301 สำหรับ Permanent Redirect (ดีต่อ SEO)
    • Preserve Path: เปิดเพื่อให้ Path เดิมติดไปด้วย เช่น /about ยังคงเป็น /about
  3. ตั้งค่า SSL

    เพิ่ม SSL Certificate ให้ Redirect Host ด้วย เพื่อให้ HTTP Request ถูก Redirect ไปยัง HTTPS ได้ถูกต้อง

Streams — TCP/UDP Proxy

Streams ใช้สำหรับ Forward non-HTTP traffic ที่ไม่ใช่ HTTP/HTTPS เช่น Database Port, Mail Port หรือ Game Server ซึ่ง Nginx Reverse Proxy ปกติไม่รองรับ

ตัวอย่าง: Forward MySQL Port (3306)

สถานการณ์: คุณต้องการเข้าถึง MySQL ที่รันใน Docker Container จาก Client ภายนอก VPS (เช่น DBeaver บนเครื่องของคุณ) โดยไม่เปิด Port 3306 โดยตรง

# ใน Streams — Add Stream
Incoming Port: 33060  # Port ที่ Client จะ Connect มา (เลือก Port ที่ไม่ซ้ำ)
Forward Host: mysql_container  # Container name หรือ IP
Forward Port: 3306
TCP Forwarding: ON
UDP Forwarding: OFF

ข้อควรระวัง: การ Expose Database Port ออก Internet แม้ผ่าน Proxy เป็นความเสี่ยงด้าน Security ควรจำกัดด้วย Access List หรือ Firewall ให้เข้าได้เฉพาะ IP ที่เชื่อถือเท่านั้น

ดู Logs และ Debug

เมื่อ Proxy Host แสดงสถานะ Error หรือ Offline มีหลายวิธีในการ Debug

ดู Realtime Log ของ NPM Container

# ดู Log ของ NPM app container แบบ realtime
cd ~/npm && docker compose logs -f app

# ดู Log เฉพาะ 100 บรรทัดล่าสุด
docker compose logs --tail=100 app

# ดู Log ของ database container
docker compose logs -f db

ปัญหาที่พบบ่อยและวิธีแก้

502 Bad Gateway

เกิดขึ้นเมื่อ NPM เชื่อมต่อไปยัง Backend Service ไม่ได้ สาเหตุที่พบบ่อย:

# ตรวจสอบ Container ที่รันอยู่
docker ps

# ทดสอบ Connect ไปยัง Service จาก NPM Container
docker exec npm-app-1 curl -s http://CONTAINER_NAME:PORT

SSL Certificate ไม่ออก (Failed)

# ตรวจสอบว่า Port 80 เปิดอยู่จาก VPS
curl -I http://YOUR_DOMAIN

# ตรวจสอบ DNS
dig +short YOUR_DOMAIN A

Too Many Redirects

เกิดขึ้นเมื่อเปิด Force SSL ใน NPM และ Service ปลายทางก็ Redirect HTTP → HTTPS เองอยู่แล้ว ทำให้วนซ้ำ

# แก้: ปิด Redirect ใน Service ปลายทาง
# หรือตั้ง Scheme เป็น https ใน Proxy Host ถ้า Service ปลายทางรัน HTTPS

Connection Refused

เกิดขึ้นเมื่อ Port ที่ Forward ไปไม่มีใครฟังอยู่ หรือ Service ไม่ได้อยู่ใน Docker Network เดียวกัน

# ตรวจสอบว่า Container อยู่ใน npm_network
docker network inspect npm_network | grep -A2 '"Name"'

# เพิ่ม Container เข้า npm_network (runtime)
docker network connect npm_network CONTAINER_NAME

Security Hardening สำหรับ NPM

NPM Web UI ที่รันบน Port 81 ไม่ควร Expose บน Public Internet เพราะถ้ามีคนเข้าถึงได้ก็สามารถเปลี่ยน Proxy config ทั้งหมดได้ ต่อไปนี้คือวิธี Harden NPM

วิธีที่ 1: Block Port 81 จาก Public Internet

# Block Port 81 จาก UFW หลัง Setup เสร็จ
ufw deny 81

# ตรวจสอบ
ufw status numbered

วิธีที่ 2: เข้า NPM Web UI ผ่าน SSH Tunnel

เมื่อ Block Port 81 แล้ว คุณยังเข้า NPM UI ได้ผ่าน SSH Tunnel โดยรันคำสั่งนี้บนเครื่อง Local ของคุณ

# รันบนเครื่อง Local ของคุณ (ไม่ใช่บน Server)
ssh -L 81:localhost:81 user@YOUR_VPS_IP

# จากนั้นเปิด Browser แล้วไปที่
http://localhost:81

คำสั่งนี้สร้าง Encrypted Tunnel ส่ง Traffic จาก Port 81 บนเครื่อง Local ของคุณไปยัง Port 81 บน Server โดยผ่าน SSH ทำให้ Secure โดยไม่ต้องเปิด Port 81 ให้ Public

วิธีที่ 3: จำกัด Port 81 ด้วย Firewall ให้เข้าได้เฉพาะ IP ของคุณ

# อนุญาตเฉพาะ IP ของคุณ (เปลี่ยน 203.0.113.10 เป็น IP จริง)
ufw allow from 203.0.113.10 to any port 81

# Block จาก IP อื่นทั้งหมด
ufw deny 81

วิธีที่ 4: เปลี่ยน Default Admin Email และ Password

ตรวจสอบว่าคุณได้เปลี่ยน Admin Email และ Password จาก Default ค่า [email protected] / changeme แล้ว ถ้ายังไม่ได้เปลี่ยน ให้ไปที่ Admin → Profile ใน NPM UI

Backup และ Update

การ Backup NPM ที่สำคัญที่สุดคือ Directory data, letsencrypt และ mysql ใน ~/npm/ เพราะ Directory เหล่านี้เก็บ Config, SSL Cert และ Database ทั้งหมด

Backup

# Backup ด้วย cp (ทำขณะ Container หยุดเพื่อความปลอดภัย)
cd ~/npm && docker compose stop

# Backup ไปยัง /backup/ (สร้าง directory ตามวันที่)
mkdir -p /backup/npm-$(date +%Y%m%d)
cp -r ~/npm/data ~/npm/letsencrypt ~/npm/mysql /backup/npm-$(date +%Y%m%d)/

# Start อีกครั้ง
docker compose up -d

# ดู Backup ที่สร้าง
ls -la /backup/

Update NPM เป็นเวอร์ชันล่าสุด

# Pull Image เวอร์ชันล่าสุด
cd ~/npm && docker compose pull

# Recreate Container ด้วย Image ใหม่ (Downtime สั้นมาก)
docker compose up -d

# ตรวจสอบเวอร์ชัน
docker compose exec app nginx -v

ควร Backup ก่อน Update ทุกครั้ง: แม้ NPM จะ Update ได้ง่ายมาก แต่ควร Backup data directory ก่อนทุกครั้งเพื่อป้องกัน Migration Issue ที่อาจเกิดขึ้นกับ Database Schema ในกรณีที่ Major Version เปลี่ยน

Structure ของ Data Directory

สรุปและ Next Steps

Nginx Proxy Manager เป็นเครื่องมือที่ยอดเยี่ยมสำหรับ VPS ที่รันหลาย Service ทำให้การจัดการ Reverse Proxy และ SSL กลายเป็นเรื่องง่ายที่ใครก็ทำได้ผ่าน Web UI โดยไม่ต้องเขียน Nginx Config ด้วยมือ

เหมาะสำหรับ

ข้อจำกัดที่ควรรู้

Next Steps ที่แนะนำ

พร้อมเริ่มต้น VPS สำหรับ Nginx Proxy Manager?

VPS AsiaGB ให้ Full Root Access, RAM เริ่มต้น 1GB ขึ้นไป รองรับ Docker และ Docker Compose ได้ทันที ดาต้าเซ็นเตอร์ไทย และ สิงคโปร์ เริ่มต้น 500 บาท/เดือน

ดู VPS AsiaGB