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.
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 -ltnpmegmutatja. - 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:81miatt 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 alatestcímkét használd, így a frissítés a te döntésed marad. - Kötetek: a
datamappában van az adatbázis (SQLite), a beállítások és a naplók, aletsencryptmappában a tanúsítványok. Ez a kettő a mentés tárgya. networks: az NPM a fent létrehozottproxyhálózatra csatlakozik; azexternal: truejelzi, 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.
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:
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).
Mentés (Save) után vedd fel ugyanígy a második alkalmazást (app2.pelda.hu, app2, 80).
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 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):
- SSL Certificate: válaszd a Request a new Certificate lehetőséget.
- Kapcsold be a Force SSL kapcsolót (a HTTP-kéréseket HTTPS-re irányítja) és a HTTP/2 Support kapcsolót.
- Save.
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”.
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.
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:81beá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 asudo ss -ltnp | grep ':81 'mutatja: a teszten a127.0.0.1:81cím szerepelt, nem a0.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 aproxyhá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 -ltnpmegmutatja, 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).








