ব্লগে ফিরে যান
আগস্ট 19, 2026গাইড

VPS-এ Gunicorn ও Nginx দিয়ে Python অ্যাপ কীভাবে চালাবেন

Ubuntu-তে Flask বা FastAPI অ্যাপ্লিকেশন virtualenv, Gunicorn systemd সার্ভিস, Nginx রিভার্স প্রক্সি, TLS, এনভায়রনমেন্ট ফাইল, লগিং এবং 502 ত্রুটি ও ওয়ার্কার সাইজের চেকলিস্টসহ ডিপ্লয় করুন।

VPS-এ Gunicorn ও Nginx দিয়ে Python অ্যাপ কীভাবে চালাবেন

অন্তর্নির্মিত Flask সার্ভার ও uvicorn --reload ডেভেলপমেন্টের জন্য। পাবলিক VPS-এ এমন প্রসেস ম্যানেজার চান যা ওয়ার্কার রিস্টার্ট করে, localhost-এ বাঁধে, এবং TLS ও ধীর ক্লায়েন্ট সামলানো রিভার্স প্রক্সির পেছনে বসে। Gunicorn Flask ও Django-এর জন্য সাধারণ WSGI পছন্দ। FastAPI Uvicorn ওয়ার্কার ক্লাস দিয়ে Gunicorn-এর নিচে চলতে পারে। Nginx (বা Caddy) HTTPS শেষ করে ও 127.0.0.1:8000-এ ফরোয়ার্ড করে।

এই গাইড রিবুট থেকে বেঁচে থাকা লেআউট চালায়: প্রজেক্ট /srv/app-এ, virtualenv, সিক্রেটসহ .env, gunicorn.service ইউনিট, Nginx সার্ভার ব্লক, Let's Encrypt, এবং লগ ফাইল যেখানে সত্যি grep করতে পারেন। আমরা ওয়ার্কার সংখ্যা, টাইমআউট, এবং কেন 502 Bad Gateway প্রায় কখনোই ‘Nginx ভাঙা’ নয় তাও বলব — প্রায় সবসময় Gunicorn চলছে না, ভুল সকেটে বাঁধা, বা ইমপোর্টে ক্র্যাশ করছে। উদাহরণ Flask ব্যবহার করে, কমান্ড আলাদা যেখানে FastAPI নোটসহ।

কেন এই স্ট্যাক

Gunicorn ওয়ার্কার প্রসেস আগে থেকে fork করে। অন্য ওয়ার্কার ক্লাস না ব্যবহার করলে প্রতি ওয়ার্কার এক সময়ে এক অনুরোধ সামলায়। Nginx ধীর ক্লায়েন্ট বাফার করে যাতে ওয়ার্কার মোবাইল নেটওয়ার্কে বাইট পাঠাতে আটকে না থাকে। systemd অ্যাপ মরলে রিস্টার্ট করে। একসঙ্গে এটা বিরক্তিকর, যা রাত ৩টায় চান।

  • Gunicorn: স্থিতিশীল WSGI/ASGI প্রসেস মডেল
  • systemd: বুটে শুরু, ক্র্যাশে রিস্টার্ট, journald লগ
  • Nginx: TLS, স্ট্যাটিক ফাইল, অনুরোধ আকার সীমা, gzip
  • venv: সিস্টেম Python পরিষ্কার থাকে
  • localhost বাইন্ড: অ্যাপ Nginx ছাড়া পৌঁছানো যায় না

প্রয়োজনীয়তা

Ubuntu 22.04/24.04-এ Python 3.10+ ঠিক আছে। pip root হিসেবে সিস্টেম site-packages-এ চালাবেন না। TLS-এর জন্য ডোমেইন লাগে। প্রক্সি হিসেবে Caddy পছন্দ করলে এই নিবন্ধের Gunicorn ইউনিট একই থাকে — শুধু ফ্রন্ট-এন্ড কনফিগ বদলায় (Caddy নিবন্ধ দেখুন)।

  • Ubuntu 22.04 বা 24.04 VPS
  • requirements.txt বা সমতুল্যসহ আপনার অ্যাপ্লিকেশন
  • WSGI এন্ট্রিপয়েন্ট (Flask-এর জন্য: app:app) বা ASGI (FastAPI-এর জন্য: uvicorn ওয়ার্কারসহ app:app)
  • HTTPS-এর জন্য ডোমেইন A রেকর্ড

ধাপ ১: সিস্টেম প্যাকেজ, ব্যবহারকারী ও প্রজেক্ট ডিরেক্টরি

ইন্টারঅ্যাকটিভ লগইন করতে পারে না, কোডের মালিক এবং Gunicorn চালায় এমন সিস্টেম ব্যবহারকারী তৈরি করুন। python3-venv ও বিল্ড টুল ইনস্টল করা এখনও C এক্সটেনশন কম্পাইল করা প্যাকেজে pip ব্যর্থতা এড়ায়।

bash
ssh root@YOUR_VPS_IP
apt update && apt -y upgrade
apt -y install python3 python3-venv python3-pip python3-dev build-essential nginx curl

adduser --system --group --home /srv/app appuser
mkdir -p /srv/app
chown appuser:appuser /srv/app

# Copy your code (example):
# rsync -a --delete ./myproject/ appuser@YOUR_VPS_IP:/srv/app/

ধাপ ২: Virtualenv ও নির্ভরতা

ফাইল মালিকানা সঠিক হতে venv appuser হিসেবে তৈরি করুন। উৎপাদনে সংস্করণ পিন করুন। ইনস্টলের পর নিশ্চিত করুন এককালীন gunicorn --check-config বা Python ইমপোর্টে অ্যাপ ইমপোর্ট করা যায়। এখানকার ইমপোর্ট ত্রুটি পরে 502 হওয়া সেই ত্রুটি।

bash
sudo -u appuser -H bash -lc '
cd /srv/app
python3 -m venv /srv/app/venv
/srv/app/venv/bin/pip install --upgrade pip
/srv/app/venv/bin/pip install -r /srv/app/requirements.txt gunicorn
'

# Flask example check:
sudo -u appuser -H /srv/app/venv/bin/python -c "from app import app; print('import ok')"

ধাপ ৩: এনভায়রনমেন্ট ফাইল

SECRET_KEY বা ডেটাবেস URL systemd ইউনিটে এমনভাবে হার্ডকোড করবেন না যা বিশ্ব-পঠনযোগ্য git-এ পৌঁছায়। EnvironmentFile ব্যবহার করুন। chmod 640, মালিক root, গ্রুপ appuser (বা পছন্দ হলে মালিক appuser)।

bash
cat >/srv/app/.env <<'EOF'
FLASK_ENV=production
SECRET_KEY=replace-with-openssl-rand-hex-32
DATABASE_URL=postgresql://app:password@127.0.0.1:5432/app
EOF
chown appuser:appuser /srv/app/.env
chmod 600 /srv/app/.env

ধাপ ৪: Gunicorn systemd সার্ভিস

Nginx এড়ানোর কারণ না থাকলে 0.0.0.0 নয় 127.0.0.1:8000-এ বাঁধুন। সিঙ্ক ওয়ার্কারের জন্য ওয়ার্কার সংখ্যা প্রায়ই (2 × CPU) + 1; 2 vCPU VPS-এ এটা 5, প্রতি ওয়ার্কার ভারী ML মডেল লোড করলে বেশি হতে পারে — তখন 2–3 ব্যবহার করুন। FastAPI-এর জন্য --worker-class uvicorn.workers.UvicornWorker সেট করুন ও uvicorn ইনস্টল করুন। টাইমআউট সবচেয়ে ধীর সৎ অনুরোধ ছাড়িয়ে যাবে, ২-মিনিট এক্সপোর্ট থাকলে ৩০ সেকেন্ড নয়।

bash
cat >/etc/systemd/system/gunicorn.service <<'EOF'
[Unit]
Description=Gunicorn for the web app
After=network.target

[Service]
User=appuser
Group=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/srv/app/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 --timeout 60 --access-logfile - --error-logfile - app:app
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now gunicorn
systemctl status gunicorn --no-pager
ss -tulpn | grep 8000

ধাপ ৫: Nginx রিভার্স প্রক্সি ও TLS

Nginx 80/443 শোনে ও Gunicorn-এ প্রক্সি করে। আপলোডের জন্য client_max_body_size গুরুত্বপূর্ণ। proxy_read_timeout Gunicorn টাইমআউটের সঙ্গে মিলবে বা ছাড়াবে। সার্ভার ব্লক HTTP-তে কাজ করলে Certbot দিয়ে সার্টিফিকেট ইস্যু করুন (বা ফ্রন্ট Caddy-তে বদলান)। নিচের স্নিপেট পরীক্ষার জন্য শুধু HTTP; তারপর ফাইল সম্পাদনা করতে পারে এমন Certbot চালান।

bash
cat >/etc/nginx/sites-available/app <<'EOF'
server {
    listen 80;
    server_name app.example.com;
    client_max_body_size 20m;

    location /static/ {
        alias /srv/app/static/;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        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_read_timeout 90s;
    }
}
EOF

ln -sf /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
nginx -t && systemctl reload nginx

ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable

apt -y install certbot python3-certbot-nginx
certbot --nginx -d app.example.com

ধাপ ৬: স্ট্যাটিক ফাইল, অনুমতি ও Flask/FastAPI বিবরণ

পারলে Nginx স্ট্যাটিক ফাইল সার্ভ করবে; Gunicorn-এর চেয়ে দ্রুত। Django collectstatic, ছোট অ্যাপের জন্য Flask send_from_directory, বা পরে CDN। appuser গাছ পড়তে পারবে। FastAPI ব্যবহার করলে venv-এ uvicorn[standard] ইনস্টল করুন ও ExecStart UvicornWorker ব্যবহার করুক। TCP-এর বদলে Unix সকেট ব্যবহার করলে proxy_pass সকেটে নির্দেশ করুন ও অনুমতি মেলান যাতে www-data লিখতে পারে।

bash
# FastAPI ExecStart example:
# ExecStart=/srv/app/venv/bin/gunicorn -k uvicorn.workers.UvicornWorker --workers 2 --bind 127.0.0.1:8000 app:app

# Unix socket variant:
# --bind unix:/run/gunicorn/app.sock
# Nginx: proxy_pass http://unix:/run/gunicorn/app.sock:

chown -R appuser:appuser /srv/app

ওয়ার্কার, মেমরি ও শূন্য-ডাউনটাইম রিলোড

সিঙ্ক Gunicorn ওয়ার্কার সরল এবং CPU-হালকা অনুরোধ/প্রতিক্রিয়া API-এর জন্য যথেষ্ট। অনেক সমবর্তী ধীর I/O অপেক্ষা লাগলে gevent বা ASGI ওয়ার্কার ভাবুন — মাপুন, অনুমান করবেন না। প্রতি ওয়ার্কার আপনার অ্যাপ লোড করে; RAM ~= ওয়ার্কার গুণ অ্যাপ RSS। 300 MB অ্যাপের 8 ওয়ার্কারসহ 2 GB VPS সোয়াপ করবে ও ‘এলোমেলো ধীর’ লাগবে। ফাইল জায়গায় ডিপ্লয় করলে systemctl reload gunicorn (HUP) নতুন কোডে ওয়ার্কার রিস্টার্ট করতে পারে; নির্ভরতা বদলালে পুরো রিস্টার্ট পরিষ্কার।

bash
# After git pull / rsync of new code:
sudo -u appuser -H /srv/app/venv/bin/pip install -r /srv/app/requirements.txt
systemctl restart gunicorn
curl -I https://app.example.com/health

502 ও নীরব ক্র্যাশ সমাধান

502 মানে Nginx আপস্ট্রিম থেকে বৈধ প্রতিক্রিয়া পায়নি। প্রথম কমান্ড journalctl -u gunicorn -e। সাধারণ কারণ: ভুল module:app নাম, অনুপস্থিত .env কী, Postgres চলছে না, 127.0.0.1-এ বাঁধা কিন্তু Nginx অন্য হোস্টে, SELinux (Ubuntu-তে বিরল), বা অ্যাপ শুধু IPv6 শুনছে। 504 টাইমআউট। অ্যাপ HTTP-তে রিডাইরেক্ট করলে আর X-Forwarded-Proto উপেক্ষিত থাকলে 301 লুপ হয়।

  • systemctl status gunicorn — সক্রিয়?
  • journalctl -u gunicorn -n 100 — ImportError, অনুপস্থিত env, ডেটাবেস
  • VPS থেকে curl -v http://127.0.0.1:8000/ — এটা ব্যর্থ হলে Nginx নির্দোষ
  • nginx -t ও error.log — upstream prematurely closed connection
  • ss -tulpn | grep 8000 — কিছু শুনছে না
  • ডিস্ক পূর্ণ — ওয়ার্কার রহস্যময় উপায়ে ক্র্যাশ করে

নিরাপত্তা

অ্যাপ কখনো পাবলিক বাঁধে না। সিক্রেট .env-এ থাকে। venv ও OS প্যাচ রাখুন। Gunicorn root হিসেবে চালাবেন না। লগইন সামলালে সেশন কুকি Secure ও SameSite সেট করুন, এবং ফ্রেমওয়ার্ককে শুধু Nginx থেকে X-Forwarded-Proto-তে বিশ্বাস করতে দিন। লগইন রুট Nginx-এ বা অ্যাপে রেট-সীমিত করুন।

  • 127.0.0.1 বা unix সকেটে বাঁধুন
  • chmod 600 .env
  • systemd-এ অ-root User=
  • Certbot বা Caddy দিয়ে TLS
  • উৎপাদনে ডিবাগ মোড ও অটো-রিলোড বন্ধ করুন

টিপস

  • Compose ও লোড ব্যালেন্সারের জন্য DB সংযোগ পরীক্ষা করা /health রুট যোগ করুন
  • Nginx-এ cache-control হেডারসহ স্ট্যাটিক অ্যাসেট পাঠান
  • ইমেইল ও ভারী কাজের জন্য আলাদা ওয়ার্কার বা কিউ ব্যবহার করুন (Redis + systemd)
  • requirements.txt-এ gunicorn ও uvicorn সংস্করণ পিন করুন
  • প্রথম উৎপাদন কাটওভারের আগে স্ন্যাপশট নিন

VPS-এ Python অ্যাপ তখন উৎপাদন-প্রস্তুত যখন Gunicorn-এর নিচে systemd সার্ভিস হিসেবে চলে, শুধু localhost-এ বাঁধে, এবং TLS সহ Nginx বা Caddy দিয়ে পৌঁছানো যায়। সিক্রেট EnvironmentFile-এ রাখুন, ওয়ার্কার ব্লগ সূত্র নয় RAM অনুসারে সাইজ করুন, এবং 502 আগে Gunicorn জার্নাল থেকে ডিবাগ করুন। এই পথ আপনার রেপোর জন্য নথিভুক্ত হলে প্রতি পরের ডিপ্লয় rsync বা git pull, pip install ও systemctl restart gunicorn।