Nginx বনাম Caddy বনাম Traefik: কোনটি বেছে নেবেন?
একটি VPS এবং একটি পাবলিক IP-তে একাধিক সার্ভিস চালানোর জন্য Nginx, Caddy এবং Traefik-এর মধ্যে পার্থক্য জানুন। TLS সার্টিফিকেট, Docker রাউটিং এবং কনফিগারেশনের জটিলতা বিশ্লেষণ করা হয়েছে।
Nginx বনাম Caddy বনাম Traefik: সংক্ষিপ্ত উত্তর
Nginx, Caddy এবং Traefik প্রত্যেকেই reverse proxy হিসেবে একই কাজ করে: port 443-এ অনুরোধ গ্রহণ করে, প্রতিটি অনুরোধের hostname পড়ে এবং সেটিকে আপনার VPS-এর সঠিক service-এ পাঠিয়ে দেয়। এই তিনটির যেকোনো একটি ব্যবহার করেই আপনি চারটি self-hosted অ্যাপকে একটি public IP address-এর পেছনে রাখতে পারবেন এবং এরা সবাই এতটাই দ্রুত যে আপনার অ্যাপগুলোই বরং ধীরগতির হবে। এদের মধ্যে পার্থক্য হলো প্রতিটি কীভাবে TLS (transport layer security) certificate সংগ্রহ করে এবং প্রতিটি নতুন অ্যাপ যোগ করতে আপনার কতটা configuration করতে হয়। অন্য পার্থক্যটি সামনে আসে সেই দিন, যেদিন আপনার এমন কিছু প্রয়োজন হয় যা সাধারণ টিউটোরিয়ালগুলোতে এড়িয়ে যাওয়া হয়েছে।
যদি আপনি চান যে HTTPS-এর বিষয়টি স্বয়ংক্রিয়ভাবে হ্যান্ডেল করা হোক এবং আপনার সার্ভিসগুলো সাধারণ web app হয়, তবে Caddy বেছে নিন। যদি সবকিছু Docker Compose-এ চলে এবং আপনি প্রতি কয়েক সপ্তাহ পরপর নতুন সার্ভিস যোগ করেন, তবে Traefik বেছে নিন। যদি আপনি ইতিমধ্যে Nginx ব্যবহার করেন, অথবা আপনার response caching, client certificates, raw TCP forwarding বা এমন কোনো বড় existing config প্রয়োজন হয় যা আপনি পুনরায় লিখতে চান না, তবে Nginx বেছে নিন।
How does each one get a TLS certificate?
This axis decides it for most people, so start here. All three end up holding the same certificate from the same authority. The work you do to get there is not the same.
Caddy asks for the certificate because you named a hostname. Write app.example.com as a site address and Caddy requests a certificate over ACME (automatic certificate management environment) from Let's Encrypt, falls back to ZeroSSL if that fails, serves the HTTP to HTTPS redirect on port 80, and renews on its own. There is no second tool and no timer to check. Certificates live in the caddy user's data directory, /var/lib/caddy/.local/share/caddy on a package install, so add that path to your backups or accept a fresh issuance after a rebuild. For a hostname that is not public, tls internal signs with Caddy's own local certificate authority instead. That gets you the same thing as creating a self-signed certificate on Ubuntu, with the renewal handled for you.
Nginx has no ACME client. Certbot obtains the certificate, and its --nginx plugin rewrites your server block to add the 443 listener and the redirect. Renewal runs from a systemd timer the package installs, so there are two moving parts and two things to verify: systemctl list-timers | grep certbot shows the timer exists, and sudo certbot renew --dry-run proves the renewal path still works. The step by step is in Certbot on Ubuntu 24.04 with Nginx, and the same tool covers a wildcard certificate through the DNS-01 challenge when you have more subdomains than you want to list.
Traefik carries its own ACME client. You configure one certificate resolver in the static configuration, and every router can then use it. All of the state, account key and certificates included, sits in a single acme.json file. Traefik refuses to use that file if it is readable by anyone but its owner, and it tells you so before it drops the resolver:
The ACME resolver "le" is skipped from the resolvers list because: unable to get ACME account: permissions 660 for /letsencrypt/acme.json are too open, please use 600Mount a directory and let Traefik create the file itself. Create it first with touch and it inherits your umask, which is how most people meet that line.
One thing is true for all three. The HTTP-01 challenge needs port 80 reachable from the internet, because the certificate authority connects back to it. Open 443 only and issuance fails in a way that reads like a DNS fault.
তিনটি কনফিগারেশনে একই দুই-অ্যাপ রাউটিংয়ের কাজ
কাজটি হলো: app.example.com যাবে 127.0.0.1:8080-এর একটি সার্ভিসে, files.example.com যাবে 127.0.0.1:8081-এর একটি সার্ভিসে, উভয়ই HTTPS-এর মাধ্যমে। প্রতিটি প্রক্সির সম্পূর্ণ কনফিগারেশন এখানে দেওয়া হলো, যাতে দাবির পরিবর্তে শব্দসংখ্যার পার্থক্যটি স্পষ্টভাবে বোঝা যায়।
Nginx
# /etc/nginx/sites-available/app.example.com
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
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;
}
}এরপর এটিকে লিঙ্ক করুন, পরীক্ষা করুন, রিলোড করুন এবং সার্টিফিকেট যোগ করুন।
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d app.example.comnginx -t কমান্ডের মাধ্যমে syntax is ok এবং test is successful প্রিন্ট করা হলো প্রতিটি রিলোডের আগে চালানোর মতো পরীক্ষা। দ্বিতীয় অ্যাপটির ক্ষেত্রে হোস্টনেম এবং পোর্ট পরিবর্তন করে একই ব্লক ব্যবহার করতে হবে। proxy_set_header লাইনগুলো কেবল সাজানোর জন্য নয়: যখন proxy_pass কোনো অ্যাড্রেসের নাম দেয়, Nginx ডিফল্টভাবে upstream-এ Host: 127.0.0.1:8080 পাঠায়। ফলে যে অ্যাপ Host header থেকে absolute URL তৈরি করে, তা আপনার ব্যবহারকারীদের localhost-এ পাঠিয়ে দেবে।
Caddy
app.example.com {
reverse_proxy 127.0.0.1:8080
}
files.example.com {
reverse_proxy 127.0.0.1:8081
}sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddyএটিই সম্পূর্ণ ফাইল। reverse_proxy নিজে থেকেই X-Forwarded-For, X-Forwarded-Proto এবং X-Forwarded-Host সেট করে নেয়। ডিফল্টভাবে এটি ক্লায়েন্ট ওই হেডারগুলোতে যা পাঠিয়েছে তা উপেক্ষা করে, তাই কোনো রিকোয়েস্ট আপনার ব্যাকএন্ডকে ভুল উৎস সম্পর্কে বিভ্রান্ত করতে পারে না। সার্টিফিকেট, পোর্ট 80 রিডাইরেক্ট এবং রিনিউয়াল—সবই এই দুটি সাইট অ্যাড্রেস থেকে স্বয়ংক্রিয়ভাবে সম্পন্ন হয়। ফাইলে অন্য কোনো নির্দেশনার প্রয়োজন নেই।
Traefik
কোনো কিছু রাউট করার আগে Traefik-এর একটি স্ট্যাটিক কনফিগারেশন প্রয়োজন। আগস্ট 2026 অনুযায়ী বর্তমান ইমেজ ট্যাগ ব্যবহার করে একটি Compose সার্ভিস হিসেবে:
services:
traefik:
image: traefik:v3.7
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.le.acme.email=you@example.com"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencryptপ্রতিটি অ্যাপ্লিকেশন তখন তার নিজস্ব রাউটিং বহন করে, যা লেবেলের মাধ্যমে নিজস্ব compose ফাইলে থাকে:
labels:
- "traefik.enable=true"
- "traefik.http.routers.app.rule=Host(`app.example.com`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls.certresolver=le"
- "traefik.http.services.app.loadbalancer.server.port=8080"loadbalancer.server.port হলো কন্টেইনারের ভেতরের পোর্ট, কোনো পাবলিশড পোর্ট নয়, কারণ Traefik একটি শেয়ারড Docker নেটওয়ার্কের মাধ্যমে কন্টেইনারে পৌঁছায়। অ্যাপটির জন্য কোনো ports: লাইনের প্রয়োজন নেই, এবং এটিই আসল সুবিধা: শুধুমাত্র Traefik-ই পাবলিশ করা থাকে। শেয়ারড নেটওয়ার্ক এবং রিডাইরেক্ট মিডলওয়্যারসহ সম্পূর্ণ বিল্ডটি এখানে দেখুন: Traefik এবং Docker Compose দিয়ে একাধিক অ্যাপ রাউটিং।
প্রতিটি অতিরিক্ত অ্যাপের জন্য কনফিগারেশনের খরচ কত?
The data behind this chart
[
{
"tool": "Nginx",
"proxy_setup_lines": 0,
"lines_per_app": 11
},
{
"tool": "Caddy",
"proxy_setup_lines": 0,
"lines_per_app": 3
},
{
"tool": "Traefik",
"proxy_setup_lines": 17,
"lines_per_app": 5
}
]উপরের ব্লকগুলো থেকে গণনা করা হয়েছে। Nginx সার্ভার ব্লকের জন্য 11 টি নন-ব্ল্যাঙ্ক লাইন প্রয়োজন এবং প্রতিটি হোস্টনেমের জন্য আপনাকে এটি পুনরায় লিখতে হয়। Caddy সাইট ব্লকের জন্য 3 টি লাইন প্রয়োজন। Traefik-এর ক্ষেত্রে একটি অনুরোধ সার্ভ করার আগে 17 লাইনের স্ট্যাটিক কনফিগারেশন প্রয়োজন হয়, এবং এরপর প্রতিটি অ্যাপের জন্য 5 টি লেবেল যোগ করতে হয়।
সুবিধা-অসুবিধার ভারসাম্যটি বুঝুন, কেবল বিজয়ীকে নয়। প্রথম অ্যাপটি যোগ করার আগে Traefik-এর খরচ সবচেয়ে বেশি, কিন্তু এরপর প্রতিটি অ্যাপের জন্য খরচ সবচেয়ে কম। প্রায় তিনটি সাইটের ক্ষেত্রে এই দুইয়ের মোট খরচ সমান হয়ে যায়। এর নিচে, স্ট্যাটিক কনফিগারেশন এমন একটি বাড়তি বোঝা যা আপনার প্রয়োজন ছিল না। এর উপরে, লেবেলগুলো এগিয়ে থাকে এবং এগিয়েই থাকে, কারণ রাউটিংটি সেই সার্ভিসের পাশেই থাকে যাকে এটি রাউট করে। সার্ভিসটি মুছে ফেললে এর রুটটিও মুছে যায়, যা একটি কেন্দ্রীয় কনফিগারেশন ফাইলের ক্ষেত্রে বড় সমস্যা: অনেক মাস আগে বন্ধ হয়ে যাওয়া অ্যাপের জন্য পুরনো সার্ভার ব্লকগুলো রয়ে যায়।
লাইনের সংখ্যা Nginx-এর ক্ষেত্রে কিছুটা বিভ্রান্তিকর হতে পারে। এই ব্লকগুলোর প্রতিটির জন্য একটি symlink, একটি nginx -t, একটি রিলোড এবং একটি certbot রান প্রয়োজন হয়। অন্যদিকে, Caddy এডিট করার জন্য কেবল একটি রিলোড এবং Traefik এডিট করার জন্য কোনো কমান্ডই চালানোর প্রয়োজন হয় না। তিনটিই লাইভ কানেকশন বিচ্ছিন্ন না করেই রিলোড হতে পারে। মূল পার্থক্য হলো সেই ধাপগুলোর সংখ্যা, যা আপনাকে গভীর রাতে মনে রাখতে হবে।
কোনটি আপনার কন্টেইনার সম্পর্কে জানে?
Traefik ডকার সকেট পর্যবেক্ষণ করে এবং কন্টেইনার চালু বা বন্ধ হওয়ার সাথে সাথে কন্টেইনার লেবেল থেকে রাউটার তৈরি করে। এখানে অন্য কোনো টুল এটি করে না। নতুন কন্টেইনার যুক্ত হলে Nginx এবং Caddy উভয়কেই কনফিগারেশন পরিবর্তন করে রিলোড করতে হয়। এছাড়া তাদের এমন একটি ঠিকানার প্রয়োজন হয় যেখানে তারা পৌঁছাতে পারে: হয় লুপব্যাক ইন্টারফেসে পাবলিশ করা কোনো পোর্ট, অথবা প্রক্সির সাথে সংযুক্ত একটি শেয়ারড ডকার নেটওয়ার্ক।
এই ফিচারের একটি মূল্য আছে এবং তা স্পষ্টভাবে বলা প্রয়োজন। Traefik /var/run/docker.sock ফাইলটি পড়ে। যে কেউ এই সকেটের সাথে যোগাযোগ করতে পারলে হোস্ট ফাইলসিস্টেম মাউন্ট করা একটি কন্টেইনার চালু করতে পারে, যা হোস্টের রুট অ্যাক্সেসের সমান। এটি রিড-অনলি (read-only) মোডে মাউন্ট করলে ঝুঁকি কিছুটা কমে, তবে পুরোপুরি দূর হয় না। যদি এটি আপনার থ্রেট মডেলের জন্য গুরুত্বপূর্ণ হয়, তবে মাঝখানে একটি সকেট প্রক্সি ব্যবহার করুন যা শুধুমাত্র Traefik-এর প্রয়োজনীয় কন্টেইনার লিস্ট এন্ডপয়েন্টগুলো উন্মুক্ত রাখে।
Caddy একটি কমিউনিটি প্লাগইনের মাধ্যমে লেবেল-ভিত্তিক ডিসকভারি করতে পারে, কিন্তু Caddy প্লাগইনগুলো বাইনারির সাথে কম্পাইল করতে হয়। তাই আপনাকে একটি কাস্টম বাইনারি বা xcaddy ব্যবহার করে কাস্টম ইমেজ তৈরি করতে হবে এবং সেই বিল্ড ও তার আপডেটগুলো আপনাকে নিজেই রক্ষণাবেক্ষণ করতে হবে। তিন বা চারটি সার্ভিসের ক্ষেত্রে Caddyfile এডিট করা অনেক কম পরিশ্রমের কাজ।
Websockets এবং streaming: কী ভেঙে যায় এবং কেন
Nginx-এর ক্ষেত্রে বাড়তি কনফিগারেশনের প্রয়োজন হয়। একটি WebSocket সংযোগ HTTP অনুরোধ হিসেবে শুরু হয় যাতে Upgrade: websocket থাকে, এবং আপনি নির্দেশ না দিলে Nginx hop-by-hop হেডারগুলো আপস্ট্রিমের দিকে পাঠায় না।
# /etc/nginx/conf.d/upgrade-map.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}এরপর, location ব্লকের ভেতরে, তিনটি লাইন অবশ্যই থাকতে হবে:
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;এগুলো বাদ দিলে ব্রাউজার কনসোলে WebSocket connection to 'wss://app.example.com/ws' failed দেখাবে, অথচ আপনার ব্যাকএন্ড লগে সাধারণ GET অনুরোধ দেখা যাবে। map-এর অস্তিত্বের কারণ হলো, একটি হার্ডকোডেড Connection: upgrade প্রতিটি অনুরোধের সাথে পাঠানো হতো, এমনকি সাধারণ অনুরোধেও, যেখানে close থাকা উচিত ছিল।
Nginx-এর আরও দুটি ডিফল্ট সেটিংস সমস্যা তৈরি করে। proxy_read_timeout হলো 60 সেকেন্ড, যা আপগ্রেডের পর টানেলের ক্ষেত্রেও প্রযোজ্য। ফলে কোনো ট্রাফিক না থাকলে এক মিনিট পর প্রক্সি সংযোগটি বন্ধ করে দেয়। এছাড়া, server-sent events দেরিতে বা একসাথে অনেকগুলো আসে যতক্ষণ না আপনি সেই লোকেশনে proxy_buffering off; সেট করছেন, কারণ Nginx আপনার পেজের জন্য অপেক্ষা করার সময় রেসপন্সটিকে বাফারে আটকে রাখে।
Caddy স্বয়ংক্রিয়ভাবে আপগ্রেড সম্পন্ন করে এবং কোনো বাড়তি নির্দেশ ছাড়াই সংযোগটিকে দ্বিমুখী টানেলে রূপান্তর করে। এছাড়া রেসপন্স যখন text/event-stream হয় বা এর দৈর্ঘ্য অজানা থাকে, তখন এটি তাৎক্ষণিকভাবে ডেটা পাঠিয়ে দেয়, ফলে স্ট্রিমিং কোনো বাধা ছাড়াই কাজ করে। Traefik আপগ্রেডগুলো সরাসরি পাস করে এবং আপনি নিজে থেকে এর buffering মিডলওয়্যার যোগ না করলে রেসপন্স বাফার করে না। আপনার সার্ভিসে যদি চ্যাট, ওয়েব টার্মিনাল, লগ টেইল বা লাইভ ড্যাশবোর্ড থাকে, তবে কনফিগারেশন এবং ডিবাগিংয়ের ক্ষেত্রে এটি একটি বড় পার্থক্য তৈরি করে।
সম্পূর্ণ Nginx সার্ভার ব্লক, Websockets এবং SSE সহ
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name app.example.com;
client_max_body_size 64m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
proxy_buffering off;
}
}map অংশটি http কনটেক্সটে থাকা উচিত, server-এর ভেতরে নয়, তাই এটিকে /etc/nginx/conf.d/-এর অধীনে আলাদা ফাইলে রাখুন। শুধুমাত্র স্ট্রিমিং হয় এমন লোকেশনেই proxy_buffering বন্ধ রাখুন, কারণ বাফারিংয়ের কারণেই Nginx সাধারণ রেসপন্সের ক্ষেত্রে ব্যাকএন্ড ওয়ার্কারকে দ্রুত মুক্ত করতে পারে। Certbot চালানোর সময় এটি এই ব্লকটি পুনরায় লিখে ফেলে, তাই কাজ শেষে ফাইলটি আবার যাচাই করে নিন।
যখন আপনার অস্বাভাবিক কোনো কিছুর প্রয়োজন হয় তখন কী ঘটে?
এই জায়গাতেই Nginx তার বাড়তি লাইনগুলোর যথার্থতা প্রমাণ করে।
- Client certificates, যাকে mTLS (mutual TLS)-ও বলা হয়, যেখানে ক্লায়েন্টকেও একটি সার্টিফিকেট প্রদান করতে হয়। Nginx-এর ক্ষেত্রে server ব্লকের ভেতরে
ssl_client_certificate /etc/ssl/ca.pem;এবংssl_verify_client on;প্রয়োজন হয়। Caddy-এর ক্ষেত্রেtls-এর ভেতরে একটিclient_authব্লক প্রয়োজন। Traefik-এর লেবেল দিয়ে এটি কোনোভাবেই প্রকাশ করা সম্ভব নয়: আপনাকে একটি file provider-এ TLS অপশন সংজ্ঞায়িত করতে হবে এবংtraefik.http.routers.app.tls.options=mtls@fileদিয়ে রাউটারকে সেটির দিকে নির্দেশ করতে হবে। সবকিছু লেবেলের ভেতরে রাখার মডেলে এটিই প্রথম ব্যতিক্রম, যখন আপনার এই ফিচারের প্রয়োজন হয়। - বড় ফাইল আপলোড। Nginx ডিফল্টভাবে রিকোয়েস্ট বডির সীমা 1 MB নির্ধারণ করে রাখে। এর চেয়ে বড় আপলোড করলে
413 Request Entity Too Largeরিটার্ন করে এবং এরর লগেclient intended to send too large bodyদেখায়। এক্ষেত্রেclient_max_body_sizeবাড়িয়ে নিতে হয়। Caddy এবং Traefik ডিফল্টভাবে কোনো বডি লিমিট সেট করে না, তাই রিকোয়েস্ট সরাসরি আপনার অ্যাপে পৌঁছায় এবং আপনার অ্যাপের নিজস্ব লিমিট অনুযায়ী সিদ্ধান্ত নেওয়া হয়। - রেসপন্স ক্যাশিং। Nginx-এ
proxy_cacheরয়েছে এবং এটি বেশ পরিপক্ক। Caddy-এর ক্ষেত্রে একটি প্লাগইন কম্পাইল করে নিতে হয়। Traefik-এর ওপেন সোর্স বিল্ডে কোনো HTTP ক্যাশ নেই, যা অনেককেই অবাক করে যারা মনে করেন প্রতিটি প্রক্সিতেই ক্যাশিং সুবিধা থাকে। - Raw TCP বা UDP, ডাটাবেস পোর্ট বা গেম সার্ভারের জন্য। Nginx-এ
streamমডিউল রয়েছে। Traefik-এর নিজস্ব এন্ট্রি পয়েন্টে TCP এবং UDP রাউটার রয়েছে। Caddy-এর জন্য আরেকটি প্লাগইন প্রয়োজন, যার মানে হলো আরেকটি কাস্টম বিল্ড। - প্রক্সির পেছনে আগে থেকেই থাকা কোনো ওয়েব সার্ভার। যদি সার্ভিসটি একটি ক্লাসিক PHP অ্যাপ্লিকেশন হয়, তবে Ubuntu 24.04-এ একটি LAMP stack-এ আগে থেকেই Apache অন্তর্ভুক্ত থাকে। এর সামনে একটি প্রক্সি বসালে আপনি দুটি জায়গা পাবেন যেখানে হেডার সেট করা যায় এবং দুটি জায়গা থেকে URL রিরাইট করা সম্ভব। সিদ্ধান্ত নিন কোনটি TLS টার্মিনেট করবে, তারপর অন্যটিকে loopback-এ plain HTTP-তে সীমাবদ্ধ রাখুন।
ফায়ারওয়ালের যে ফাঁদটি এই পছন্দের পরে আসে
রিভার্স প্রক্সির মূল উদ্দেশ্য হলো শুধুমাত্র 80 এবং 443 পোর্ট খোলা রাখা। Docker নীরবে সেই নিরাপত্তা নষ্ট করে দেয়। -p 8080:80 ব্যবহার করে কোনো পোর্ট পাবলিশ করলে তা nat টেবিলে একটি DNAT রুল লিখে রাখে। এই রুলটি ufw-এর ম্যানেজ করা INPUT রুলের আগেই কার্যকর হয়, তাই ufw deny 8080 এটিকে ব্লক করতে পারে না। ফলে আপনার অ্যাপটি প্রক্সির পাশাপাশি সরাসরি পাবলিক ইন্টারনেটে উন্মুক্ত হয়ে যায়, যদিও আপনি প্রক্সিটিকে অত্যন্ত সতর্কতার সাথে কনফিগার করেছিলেন। পাবলিশ করা পোর্টগুলোকে 127.0.0.1:8080:80 ব্যবহার করে লুপব্যাক (loopback) ইন্টারফেসে বাইন্ড করুন, অথবা ports: ব্যবহার করা পুরোপুরি বন্ধ করে দিন। এর পরিবর্তে প্রক্সিকে Docker নেটওয়ার্কের মাধ্যমে কন্টেইনারে পৌঁছাতে দিন, যা উপরের Traefik উদাহরণে করা হয়েছে। এই মেকানিজম এবং এর সমাধান সম্পর্কে বিস্তারিত জানতে কেন Docker পাবলিশ করা পোর্ট ufw-কে বাইপাস করে দেখুন।
আপনার VPS ছাড়া অন্য কোনো মেশিন থেকে এটি পরীক্ষা করুন, কারণ সার্ভারের ভেতর থেকে চেক করলে তা সবসময় সফল দেখাবে:
curl --max-time 5 http://your.server.address:8080Connection refused অথবা একটি টাইমআউট (timeout) হলো কাঙ্ক্ষিত ফলাফল। যদি কোনো HTTP রেসপন্স পান, তার মানে আপনার প্রক্সি ছাড়াই অ্যাপটি সরাসরি অ্যাক্সেস করা যাচ্ছে এবং আপনার করা সমস্ত কনফিগারেশন কেবল লোক দেখানো।
কোন প্রক্সিটি আপনার বেছে নেওয়া উচিত?
মূলত স্ট্যাটিক সাইট এবং সাথে এক বা দুটি অ্যাপ: Caddy। স্বয়ংক্রিয় HTTPS আপনার সবচেয়ে বড় পুনরাবৃত্তিমূলক কাজটিকে দূর করে। এর কনফিগারেশন এত ছোট যে এক স্ক্রিনেই পুরোটা পড়া যায় এবং একটি স্ট্যাটিক সাইট একই সাইট ব্লকের ভেতরে একটি root লাইন ও একটি file_server লাইনের মাধ্যমেই তৈরি করা সম্ভব। এর অসুবিধা হলো, কোনো জটিল সমস্যা হলে ইন্টারনেটে কপি-পেস্ট করার মতো সমাধানের ভাণ্ডার তুলনামূলক ছোট।
একটি docker-compose হোম-ল্যাব যেখানে আপনি নিয়মিত নতুন সার্ভিস যোগ করেন: Traefik। তিনটি সার্ভিসের বেশি হয়ে গেলে, একটি কেন্দ্রীয় ফাইল এডিট করার চেয়ে লেবেল (labels) ব্যবহার করা অনেক সহজ এবং কোনো সার্ভিস মুছে ফেললে তার রুটও স্বয়ংক্রিয়ভাবে মুছে যায়। প্রথমবার সেটআপের জন্য এক বিকেল সময় হাতে রাখুন, কারণ entrypoints, routers, services এবং middlewares—এই শব্দগুলো আপনার কাছে নতুন মনে হতে পারে। লেবেলে কোনো টাইপো থাকলে সাধারণত Traefik থেকে 404 এরর দেখায়, সার্ভিস স্টার্ট না হওয়ার বদলে। তাই অ্যাপটি নষ্ট হয়েছে মনে করার আগে docker logs traefik চেক করে দেখুন কোনো পার্স এরর আছে কি না।
বিদ্যমান Nginx কনফিগারেশন অথবা উপরের তালিকার যেকোনো প্রয়োজনীয়তা: Nginx। রেসপন্স ক্যাশিং এবং ক্লায়েন্ট সার্টিফিকেটের জন্য এর কাছে সমাধান আগে থেকেই আছে এবং প্রায় প্রতিটি থার্ড-পার্টি গাইড Nginx-কে ভিত্তি করেই লেখা। এর অসুবিধা হলো, সার্টিফিকেট এবং ওয়েবসকেট সাপোর্ট আপনাকে ম্যানুয়ালি কনফিগার করতে হবে, এগুলো ডিফল্টভাবে পাওয়া যায় না।
আপনি যা-ই বেছে নিন না কেন, একটি নিয়ম সবসময় মনে রাখবেন। পাবলিক ইন্টারফেসে কেবল একটি প্রসেস লিসেন করবে এবং বাকি সবকিছু লুপব্যাক (loopback) অথবা প্রাইভেট Docker নেটওয়ার্কে লিসেন করবে।
FAQ
একটি VPS-এ অল্প কিছু Docker অ্যাপ চালানোর জন্য সেরা reverse proxy কোনটি?
তিন বা চারটি সার্ভিসের জন্য যা আপনি মাঝে মাঝে যোগ করেন, Traefik ব্যবহার করা লাভজনক, কারণ প্রতিটি অ্যাপের নিজস্ব রাউটিং লেবেল থাকে এবং কোনো কেন্দ্রীয় ফাইল এডিট করার প্রয়োজন হয় না। যদি সার্ভিসগুলো স্থিতিশীল হয় এবং আপনি মূলত HTTPS-এর ঝামেলা থেকে মুক্তি পেতে চান, তবে Caddy শেখা সহজ এবং এতে ভুল হওয়ার সম্ভাবনা কম। Nginx বেছে নিন যদি আপনি এটি আগে থেকেই জানেন, অথবা যদি আপনার এমন কোনো ফিচারের প্রয়োজন হয় যা অন্য দুটিতে নেই, যেমন response caching বা সাধারণ TCP লিসেনার।
Caddy-তে কি সত্যিই কোনো certificate কনফিগারেশনের প্রয়োজন নেই?
সাধারণ ক্ষেত্রে, হ্যাঁ। একটি পাবলিক হোস্টনামকে সাইটের ঠিকানা হিসেবে উল্লেখ করাই হলো সম্পূর্ণ কনফিগারেশন: Caddy ACME-এর মাধ্যমে সার্টিফিকেট অনুরোধ করে, পোর্ট 80 থেকে রিডাইরেক্ট পরিচালনা করে এবং মেয়াদ শেষ হওয়ার আগেই তা রিনিউ করে। তবে দুটি শর্ত পূরণ হতে হবে। HTTP-01 চ্যালেঞ্জের জন্য পোর্ট 80 অবশ্যই ইন্টারনেট থেকে অ্যাক্সেসযোগ্য হতে হবে এবং হোস্টনামের DNS A বা AAAA রেকর্ড অবশ্যই VPS-এর দিকে নির্দেশ করা থাকতে হবে, কারণ সার্টিফিকেট অথরিটি নামটিকে রিজলভ করে এবং সেটিতে কানেক্ট করার চেষ্টা করে।
আমি কি একই VPS-এ Nginx এবং Traefik চালাতে পারি?
একই পোর্টে সম্ভব নয়। যেটি পরে চালু হবে সেটি বাইন্ড করতে ব্যর্থ হবে, এবং Nginx bind() to 0.0.0.0:443 failed (98: Address already in use) দেখাবে, অন্যদিকে Traefik একই ধরনের বাইন্ড এরর লগ করে বন্ধ হয়ে যাবে। একটি প্রক্সিকে 80 এবং 443 পোর্টে চালান এবং বাকি সবকিছুকে সেটির পেছনে রাখুন। যদি আপনি মাইগ্রেট করছেন, তবে একটি একটি করে হোস্টনাম সরান: ফ্রন্ট প্রক্সিকে লুপব্যাক পোর্টে পুরনোটির কাছে অনুরোধ পাঠাতে দিন যতক্ষণ না শেষ সাইটটি সরানো হচ্ছে।
Nginx-এর পেছনে আমার websockets কেন 60 সেকেন্ড পর বিচ্ছিন্ন হয়ে যায়?
proxy_read_timeout ডিফল্টভাবে 60 সেকেন্ডে সেট করা থাকে এবং আপগ্রেড সম্পন্ন হওয়ার পর এটি টানেলের ওপর প্রয়োগ হয়, তাই এক মিনিট কোনো ট্রাফিক না থাকলে প্রক্সি নিজেই কানেকশনটি বন্ধ করে দেয়, আপনার অ্যাপ নয়। সেই লোকেশনে proxy_read_timeout 3600s; ব্যবহার করে সময় বাড়িয়ে দিন, অথবা অ্যাপ্লিকেশনটিকে প্রতি 30 সেকেন্ডে একটি পিং ফ্রেম পাঠাতে বলুন। Caddy এবং Traefik এক মিনিটের টাইমার দিয়ে অলস আপগ্রেডেড কানেকশন বন্ধ করে না, যে কারণে একই অ্যাপ তাদের পেছনে স্থিতিশীল থাকলেও Nginx-এর পেছনে অস্থিতিশীল মনে হতে পারে।