Nginx Proxy Manager telepítése Dockerrel

Linux 13 perc olvasás

Egy szerveren a 80-as és a 443-as portot egyszerre csak egy program használhatja. Ha több webes alkalmazást futtatsz Dockerben (például egy WordPress oldalt, egy n8n-t és egy saját alkalmazást), kell eléjük egy fordított proxy (reverse proxy): ez fogadja az összes kérést, a kért domain alapján továbbítja a megfelelő konténerhez, és ő kezeli az SSL tanúsítványokat is.

Az Nginx Proxy Manager (NPM) egy ilyen proxy, webes kezelőfelülettel. Az Nginx beállítófájljait nem kell kézzel írni: a domaint, a cél konténert és a tanúsítványt néhány mezőben add meg, a Let’s Encrypt tanúsítványokat pedig az NPM kéri és újítja meg. Ideális egy saját KVM VPS-en, ahol több kisebb alkalmazás osztozik egy IP-címen.

A lépéseket 2026 novemberében Ubuntu 24.04 rendszeren próbáltuk ki, Docker Engine 29.9.3, Docker Compose 5.7.0 és Nginx Proxy Manager 2.16.0 változattal. A tesztgépnek nem volt nyilvános domainje, ezért a Let’s Encrypt tanúsítványkérést nem tudtuk végigvinni: a felületét bemutatjuk, a működését a dokumentáció és a program forráskódja alapján írjuk le, és ezt a cikkben jelezzük. A proxyzást a szerveren a curl paranccsal, a Host fejléc megadásával ellenőriztük.

Infografika: az internetről érkező kérések az Nginx Proxy Manager 80-as és 443-as portjára futnak be, amely a domain alapján továbbítja őket a proxy nevű Docker hálózaton lévő app1, app2 és WordPress konténerhez; a MariaDB a projekt saját hálózatán van, a kezelőfelület 81-es portja csak a 127.0.0.1 címen hallgat

Mielőtt belekezdesz

  • Docker és Compose. Telepítésük a Docker telepítése Ubuntu, Debian és AlmaLinux rendszerre cikkben található, a Compose alapjai a Docker Compose használata cikkben.
  • Szabad 80-as és 443-as port. Ha a szerveren natív Apache vagy Nginx fut, állítsd le és tiltsd le, különben az NPM konténer nem indul el („address already in use”). Hogy mi hallgat a portokon, a sudo ss -ltnp megmutatja.
  • DNS. A tanúsítványkéréshez a domainek (például app1.pelda.hu) A rekordjának, IPv6 esetén AAAA rekordjának a szerver IP-címére kell mutatnia.
  • Tűzfal. A 80-as és a 443-as port legyen elérhető kívülről (lásd: Hogyan állítsak be tűzfalat a VPS-emen?). A Docker a közzétett portokat a saját szabályaival nyitja meg, ezek megelőzik az ufw és a firewalld szabályait; ezért kell a kezelőfelület portját a helyi címre kötni, ahogy lent látható.

1. Közös Docker hálózat

Az NPM és az alkalmazások egy közös Docker hálózaton találkoznak. Így az alkalmazásoknak egyetlen portot sem kell közzétenniük a szerveren: az NPM a hálózaton belül, a konténer nevével éri el őket. Hozd létre egyszer:

docker network create proxy

2. Az NPM compose.yaml fájlja

mkdir -p ~/npm && cd ~/npm
nano compose.yaml
services:
  npm:
    image: jc21/nginx-proxy-manager:2.16.0
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "127.0.0.1:81:81"
    environment:
      TZ: "Europe/Budapest"
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - proxy

networks:
  proxy:
    external: true
  • Portok: a 80-as (HTTP) és a 443-as (HTTPS) port mindenki számára nyitott, ez a proxy dolga. A 81-es a kezelőfelület: a 127.0.0.1:81:81 miatt csak a szerveren belülről érhető el. A hivatalos leírásban '81:81' szerepel, így viszont a bejelentkezőoldal az egész internet felé nyitva lenne, a tűzfaltól függetlenül.
  • Kép: a változatot rögzítsd (2.16.0), ne a latest címkét használd, így a frissítés a te döntésed marad.
  • Kötetek: a data mappában van az adatbázis (SQLite), a beállítások és a naplók, a letsencrypt mappában a tanúsítványok. Ez a kettő a mentés tárgya.
  • networks: az NPM a fent létrehozott proxy hálózatra csatlakozik; az external: true jelzi, hogy a hálózatot nem ez a projekt kezeli.
  • Ha a szerveren nincs IPv6, a dokumentáció szerint a DISABLE_IPV6: 'true' környezeti változót is fel kell venni.

Indítás és az indulási napló:

docker compose up -d
docker compose logs -f

Az első indításkor az NPM létrehozza az adatbázist és a kulcsait. Ha a naplóban megjelenik a „Backend PID … listening on port 3000” sor, kész; a naplóból a Ctrl+C-vel léphetsz ki.

3. A kezelőfelület elérése SSH-alagúton

Mivel a 81-es port csak a szerveren belül hallgat, a saját gépedről SSH-alagúton érheted el. A saját gépeden futtasd (a felhasználónevet és a címet cseréld a sajátodra):

ssh -L 8181:127.0.0.1:81 felhasznalo@szerver-ip

Amíg ez a kapcsolat nyitva van, a böngészőben a http://localhost:8181 cím az NPM kezelőfelületét nyitja meg. Ha gyakran használod, az alagutat az ~/.ssh/config fájlba is felveheted LocalForward sorral (lásd: Az SSH config fájl használata). Az SSH-kapcsolatról általában a Hogyan csatlakozzak a VPS-emhez SSH-n keresztül? cikk szól.

4. Első bejelentkezés

A régebbi változatok egy alapértelmezett fiókkal indultak (admin@example.com, jelszó changeme), és sok leírás ma is ezt említi. A 2.16.0-s változatban ilyen fiók nincs: az első megnyitáskor a Welcome! oldal jelenik meg, ahol az adminisztrátori fiókot kell létrehozni.

Az Nginx Proxy Manager első indításkor megjelenő Welcome! oldala a Full Name, Email address és New Password mezővel és a Save gombbal

Add meg a nevet (Full Name), egy valódi e-mail-címet (Email address) és egy erős jelszót (New Password), majd kattints a Save gombra. A teszten a mentés néhány másodpercig tartott, utána a bejelentkezőoldal jelent meg.

Az e-mail-cím nem csak a belépéshez kell: a program forráskódja szerint az NPM ezzel a címmel regisztrál a Let’s Encryptnél, amikor tanúsítványt kér, és a Let’s Encrypt felhasználási feltételeit is automatikusan elfogadja. Ha tanúsítványkéréskor hibaüzenet jelez érvénytelen címet, javítsd a fiókodban (jobb felső sarok, a nevedre kattintva: Edit Profile).

Bejelentkezés után a kezdőlap (Dashboard) a felvett bejegyzések számát mutatja:

Az Nginx Proxy Manager kezdőlapja (Dashboard): 2 Proxy Hosts, 0 Redirection Hosts, 0 Streams, 0 404 Hosts

A kezelőfelület angolul indul. A jobb felső sarokban lévő földgömb ikonnal magyarra (Magyar) is átállítható; a cikkben az angol feliratokat idézzük. Ugyanebben a menüben (a nevedre kattintva) található a Two-Factor Auth is: a kezelőfelület teljes hozzáférést ad a szerver webes forgalmához, ezért érdemes bekapcsolnod a kétlépcsős azonosítást.

5. Két tesztalkalmazás

Próbaképpen indíts el két kis alkalmazást a proxy hálózaton: egy Nginx-et egy egyszerű oldallal (app1) és a traefik/whoami képet (app2), amely kiírja, milyen kérést kapott.

mkdir -p ~/apps/app1 && cd ~/apps
echo "<h1>Ez az app1</h1>" > app1/index.html
nano compose.yaml
services:
  app1:
    image: nginx:alpine
    restart: unless-stopped
    volumes:
      - ./app1:/usr/share/nginx/html:ro
    networks:
      - proxy

  app2:
    image: traefik/whoami
    restart: unless-stopped
    networks:
      - proxy

networks:
  proxy:
    external: true
docker compose up -d

Egyik szolgáltatásnál sincs ports rész: a konténerek a szerver egyetlen portján sem érhetők el, csak a proxy hálózaton, az NPM-en keresztül. A hálózat tagjait a docker network inspect proxy mutatja meg.

6. Proxy host felvétele

A felső menüben válaszd a Hosts › Proxy Hosts pontot, majd az Add Proxy Host gombot. A Details fülön:

  • Domain Names: a domain, amelyre a kérések érkeznek (app1.pelda.hu). Gépelés után nyomj Entert; több domain is megadható.
  • Scheme: http. A konténerek a belső hálózaton többnyire sima HTTP-n beszélnek, a HTTPS-t az NPM intézi.
  • Forward Hostname / IP: a konténer neve a közös hálózaton (app1).
  • Forward Port: a konténer belső portja, amelyen az alkalmazás hallgat (az Nginx-nél és a whoami-nál 80), nem egy közzétett port.
  • Block Common Exploits: néhány gyakori támadási mintát szűr; bekapcsolhatod.
  • Websockets Support: kapcsold be, ha az alkalmazás WebSocketet használ (például valós idejű felületek és csevegők).

Az Add Proxy Host ablak Details füle: Domain Names app1.pelda.hu, Scheme http, Forward Hostname app1, Forward Port 80, Access List Publicly Accessible, bekapcsolt Block Common Exploits

Mentés (Save) után vedd fel ugyanígy a második alkalmazást (app2.pelda.hu, app2, 80).

A Proxy Hosts lista három bejegyzéssel: app1.pelda.hu, app2.pelda.hu és wp.pelda.hu, a célcímmel, HTTP Only SSL-lel, az Access oszlopban az egyiknél a Csak jelszóval hozzáférési listával, mindegyik Online állapotban

Az Online állapot csak azt jelenti, hogy az Nginx beállítása érvényes, azt nem, hogy a cél konténer válaszol. A teszten egy rossz portra (app1:8080) és egy nem létező konténerre mutató bejegyzés is Online lett, a böngésző viszont mindkettőnél 502 Bad Gateway hibát kapott. A többi bejegyzés ettől közben hibátlanul működött.

Kipróbálás DNS nélkül

Mielőtt a DNS-t átállítanád, a szerveren a curl paranccsal is kipróbálhatod a proxyt: a -H "Host: ..." kapcsoló azt a domaint küldi, amelyet a böngésző küldene.

curl -s -H "Host: app1.pelda.hu" http://127.0.0.1/
curl -s -H "Host: app2.pelda.hu" http://127.0.0.1/ | head -3

A curl kimenete a szerveren: az app1.pelda.hu az Ez az app1 oldalt adja, az app2.pelda.hu a whoami válaszát jelszóval, jelszó nélkül 401-es kódot, alatta az NPM konténer portjai

A képen az app2 már a lent bemutatott hozzáférési listával védett, ezért kapott jelszó nélkül 401-es kódot.

A saját gépedről úgy próbálhatod ki a böngészőben, hogy a hosts fájlba (Linuxon és macOS-en /etc/hosts, Windowson C:\Windows\System32\drivers\etc\hosts) felveszed a domaint a szerver IP-címével.

Ha olyan domain érkezik, amelyhez nincs proxy host (vagy közvetlenül az IP-címet írják be), az NPM a saját „Congratulations” oldalát mutatja. Ezt a Settings › Default Site pontban cserélheted 404 Page, No Response (444), Redirect vagy Custom HTML beállításra; éles szerveren a 404-es oldal vagy a válasz nélküli lezárás (444) a szokásos.

Egy meglévő Compose projekt bekötése

Egy már futó alkalmazást úgy köthetsz be, hogy a webes szolgáltatását a compose.yaml-ban a proxy hálózatra is felteszed, és törlöd a ports részét. A WordPress és MariaDB példán ezt a Docker Compose használata cikk mutatja be, a fordított proxyról szóló részben. Az adatbázis maradjon a projekt saját hálózatán: a teszten a proxy felől a db név nem is volt feloldható.

A Forward Hostname mezőbe ilyenkor a konténer teljes nevét érdemes írni (a teszten wordpress-wordpress-1, a docker compose ps kiírja). A szolgáltatás rövid neve (wordpress) is működött, de ha két projektben is van azonos nevű szolgáltatás a proxy hálózaton, a rövid név nem egyértelmű.

A hivatalos WordPress Docker-kép wp-config.php fájlja figyeli a proxy által küldött X-Forwarded-Proto fejlécet, így HTTPS mögött sem kerül átirányítási hurokba; a teszten a X-Forwarded-Proto: https fejléccel érkező kérésre a WordPress már https:// címre irányított. Más alkalmazásoknál nézd meg a dokumentációban, hogyan kell beállítani a proxy mögötti működést (gyakran egy „trusted proxy” vagy „base URL” beállítás).

7. SSL tanúsítvány Let’s Encrypttel

A tanúsítványt a proxy host szerkesztőablakának SSL fülén kérheted (a listában a sor végi ⋮ › Edit nyitja meg):

  1. SSL Certificate: válaszd a Request a new Certificate lehetőséget.
  2. Kapcsold be a Force SSL kapcsolót (a HTTP-kéréseket HTTPS-re irányítja) és a HTTP/2 Support kapcsolót.
  3. Save.

Az Add Proxy Host ablak SSL füle: SSL Certificate Request a new Certificate, bekapcsolt Force SSL és HTTP/2 Support, kikapcsolt HSTS Enabled és Use DNS Challenge

Ezt a lépést nem tudtuk kipróbálni, mert a tesztszervernek nem volt nyilvános domainje; a következők a dokumentáción és a forráskódon alapulnak. Alapesetben az NPM HTTP-01 ellenőrzéssel kér tanúsítványt: a Let’s Encrypt a 80-as porton, a domain nevén keresi meg a szervert. Ezért a tanúsítvány csak akkor készül el, ha a domain DNS-e már a szerverre mutat és a 80-as port kívülről elérhető. Ha valamelyik nem teljesül, a kérés hibával leáll. A tanúsítványokat az NPM magától újítja meg: a teszten a naplóban induláskor megjelent a „Let’s Encrypt Renewal Timer initialized” és a „Renewing SSL certs expiring within 30 days” sor.

A HSTS Enabled kapcsolót csak akkor kapcsold be, ha biztos vagy benne, hogy az oldal tartósan HTTPS-en marad: a böngészők ezután egy ideig HTTP-n meg sem próbálják megnyitni.

A tanúsítványokat külön is kezelheted a Certificates menüben. Az Add Certificate gomb a Let’s Encrypt via HTTP, a Let’s Encrypt via DNS és a Custom Certificate (saját, például megvásárolt tanúsítvány feltöltése) lehetőséget kínálja. A HTTP-s ablakban a Test gomb a forráskód szerint egy külső szolgáltatással ellenőrzi, hogy a domain kívülről elérhető-e, mielőtt a Let’s Encrypthez fordulna; ezt érdemes a kérés előtt lefuttatni.

DNS-ellenőrzés és wildcard tanúsítvány

Ha a 80-as port nem lehet nyitva, vagy wildcard tanúsítvány kell (*.pelda.hu), kapcsold be a Use DNS Challenge kapcsolót. Ilyenkor az NPM a DNS-szolgáltató API-ján keresztül egy TXT rekordot hoz létre, és a Let’s Encrypt ezt ellenőrzi. A HTTP-s ellenőrzéssel wildcard nem kérhető, a felület ki is írja: „Wildcards not permitted for this type”.

Az SSL fül bekapcsolt Use DNS Challenge kapcsolóval: DNS Provider Cloudflare, a Credentials File Content mezőben a minta API-token, alatta a figyelmeztetés, hogy az adat titkosítatlanul tárolódik, és a Propagation Seconds mező

A DNS Provider listában a teszten 88 szolgáltató szerepelt, köztük a Cloudflare, a DigitalOcean, a Hetzner, az OVH, az Amazon Route 53 és a szabványos RFC 2136 (saját DNS-szerverhez). A Credentials File Content mezőbe a szolgáltató API-hozzáférése kerül, a mező a kitöltés mintáját előre mutatja. Az NPM figyelmeztet, hogy ezt titkosítatlanul tárolja az adatbázisban és egy fájlban („This data will be stored as plaintext in the database and in a file!”), ezért csak az adott zóna DNS-rekordjaira korlátozott API-tokent adj meg, ne a teljes fiók kulcsát. A Propagation Seconds üresen hagyható; ha a szolgáltató lassan teszi közzé a rekordokat, növeld.

Ha nem használsz NPM-et, a Let’s Encrypt tanúsítványt közvetlenül is kérheted, lásd: Let’s Encrypt tanúsítvány igénylése Certbottal.

8. Hozzáférési listák (Access Lists)

Egy alkalmazást jelszóval vagy IP-cím szerint korlátozhatsz, például egy adminfelületet vagy egy félkész tesztoldalt. Az Access Lists menüben az Add Access List gombbal hozz létre egy listát:

  • Details: a lista neve (Name). A Satisfy Any bekapcsolva azt jelenti, hogy elég a jelszó vagy az engedélyezett IP-cím; kikapcsolva mindkettő kell. A Pass Auth to Upstream a jelszavas fejlécet az alkalmazásnak is továbbadja.
  • Authorizations: felhasználónév és jelszó párok (Username, Password, Add).
  • Rules: Allow és Deny szabályok IP-címre vagy tartományra (például 192.168.1.0/24), a megadott sorrendben. Ha legalább egy szabály van, a lista végére automatikusan egy „deny all” kerül.

Az Add Access List ablak Authorizations füle: Username teszt, Password kitöltve, Add gomb

Mentés után a proxy host Access List mezőjében válaszd ki a listát a Publicly Accessible helyett. A teszten az így védett app2.pelda.hu jelszó nélkül 401-es kódot adott, a helyes felhasználónévvel és jelszóval (curl -u teszt:jelszo ...) pedig a whoami válaszát. A jelszó HTTP-n titkosítatlanul utazik, ezért jelszavas védelmet csak SSL tanúsítvánnyal együtt használj.

9. Streams: TCP és UDP továbbítás

A Hosts › Streams menüben nem webes forgalmat (például egy adatbázis- vagy játékszerver-portot) továbbíthatsz egy konténerhez. Ezt nem próbáltuk ki. A dokumentáció szerint a stream portját az NPM compose.yaml fájljában is közzé kell tenni (például - "5432:5432"), különben a kérés el sem jut az NPM-hez. Egy adatbázist csak akkor tegyél így elérhetővé, ha valóban kívülről kell elérni; a legtöbbször az SSH-alagút biztonságosabb.

10. A kezelőfelület védelme

  • Ne tedd közzé a 81-es portot. A fenti 127.0.0.1:81:81 beállítással a bejelentkezőoldal kívülről nem érhető el, csak SSH-alagúton. Hogy ez valóban így van, a szerveren a sudo ss -ltnp | grep ':81 ' mutatja: a teszten a 127.0.0.1:81 cím szerepelt, nem a 0.0.0.0:81.
  • Erős jelszó és kétlépcsős azonosítás a fiókon (Two-Factor Auth).
  • Saját fiók mindenkinek. A Users menüben további felhasználókat is felvehetsz; ne oszd meg az adminisztrátori fiókot, és az Administrator jogot csak annak add meg, akinek valóban kell.
  • Az SSH védelméről a SSH szerver biztonsági beállításai cikk szól, hiszen a kezelőfelület ezután az SSH-n keresztül érhető el.

11. Mentés

Az NPM teljes állapota a data és a letsencrypt mappában van. Mentsd őket a compose.yaml fájllal együtt, rövid leállítás mellett:

cd ~/npm
docker compose stop
sudo tar czf ~/npm-mentes-$(date +%F).tar.gz -C ~/npm data letsencrypt compose.yaml
docker compose start

A mappák tulajdonosa a root, ezért kell a sudo. A teszten a leállás csak néhány másodpercig tartott; ezalatt a proxyzott oldalak sem érhetők el, ezért forgalmas oldalnál a mentést csendes időszakra időzítsd. Visszaállításkor csomagold ki a mentést egy új szerver ~/npm mappájába, hozd létre a proxy hálózatot, és indítsd el a docker compose up -d paranccsal. A mentést másold egy másik gépre is.

A mentés a tanúsítványok titkos kulcsait és a DNS-szolgáltató API-tokenjeit is tartalmazza: kezeld ennek megfelelően.

12. Frissítés

Frissítés előtt készíts mentést, és olvasd el az új változat kiadási megjegyzéseit a projekt GitHub-oldalán. Ezután írd át a képet a compose.yaml-ban az új változatra (például jc21/nginx-proxy-manager:2.16.0 helyett az újabbra), majd:

cd ~/npm
docker compose pull
docker compose up -d

Az adatbázis-módosításokat az NPM induláskor magától elvégzi (a naplóban „Migrating Up…” sorokként látszanak). A régi kép törléséről a Docker képek, konténerek és kötetek törlése cikk szól.

Gyakori hibák

  • 502 Bad Gateway: az NPM nem éri el a cél konténert. Ellenőrizd, hogy a konténer fut-e (docker compose ps), rajta van-e a proxy hálózaton (docker network inspect proxy), és a Forward Port a konténer belső portja-e.
  • A tanúsítványkérés nem sikerül: a domain DNS-e még nem a szerverre mutat (a változás terjedése órákig is tarthat), vagy a 80-as port kívülről nem érhető el. Ha a 80-as portot nem tudod megnyitni, használd a DNS-ellenőrzést.
  • Az NPM konténer nem indul, „address already in use”: egy másik program foglalja a 80-as vagy a 443-as portot; a sudo ss -ltnp megmutatja, melyik.
  • Átirányítási hurok HTTPS mögött: az alkalmazás nem tudja, hogy HTTPS-en érik el. Állítsd be a proxy mögötti működést az alkalmazásban (lásd fent).
Vissza: Linux leírások (76)