از runserver تا سرور واقعی
runserver فقط برای توسعه است: تکپروسه، بدون امنیت و کارایی لازم. معماری استاندارد استقرار جنگو روی لینوکس این است: nginx جلوی همه (HTTPS، فایلهای static و media، محدودیت حجم)، gunicorn با چند worker برای اجرای کد پایتون، PostgreSQL بهعنوان پایگاه داده و systemd برای روشن نگه داشتن همهچیز. در این درس سه لایهی اول پشتی را میسازیم؛ درس بعد nginx و HTTPS.
۱. آمادهسازی سرور
sudo apt update
sudo apt install -y python3.12-venv python3-dev build-essential libpq-dev \
postgresql nginx redis-server git
sudo adduser --system --group --home /srv/carpet carpet
برنامه با یک کاربر سیستمی بدون دسترسی root اجرا میشود؛ اگر روزی آسیبپذیری در کد باشد، مهاجم به کل سرور دسترسی ندارد.
۲. PostgreSQL
sudo -u postgres psql <<'SQL'
CREATE USER carpet WITH PASSWORD 'a-long-random-password';
CREATE DATABASE carpet OWNER carpet ENCODING 'UTF8';
ALTER ROLE carpet SET timezone TO 'UTC';
SQL
# settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("DB_NAME", "carpet"),
"USER": os.getenv("DB_USER", "carpet"),
"PASSWORD": os.getenv("DB_PASSWORD"),
"HOST": os.getenv("DB_HOST", "127.0.0.1"),
"PORT": "5432",
"CONN_MAX_AGE": 60, # استفادهی مجدد از اتصال
"CONN_HEALTH_CHECKS": True,
}
}
۳. کد، venv و مهاجرت
sudo -u carpet -H bash
cd /srv/carpet
git clone https://git.example.ir/team/carpet.git app
cd app
python3.12 -m venv .venv
.venv/bin/pip install -r requirements.txt gunicorn "psycopg[binary]"
nano .env # DJANGO_DEBUG=0 و بقیه
.venv/bin/python manage.py migrate
.venv/bin/python manage.py collectstatic --noinput
.venv/bin/python manage.py check --deploy
۴. gunicorn با systemd
# /etc/systemd/system/carpet.socket
[Unit]
Description=carpet gunicorn socket
[Socket]
ListenStream=/run/carpet.sock
SocketUser=www-data
[Install]
WantedBy=sockets.target
# /etc/systemd/system/carpet.service
[Unit]
Description=carpet gunicorn
Requires=carpet.socket
After=network.target postgresql.service
[Service]
User=carpet
Group=carpet
WorkingDirectory=/srv/carpet/app
EnvironmentFile=/srv/carpet/app/.env
ExecStart=/srv/carpet/app/.venv/bin/gunicorn config.wsgi:application \
--workers 3 --timeout 60 --max-requests 1000 --max-requests-jitter 100 \
--access-logfile -
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now carpet.socket carpet.service
sudo systemctl status carpet
journalctl -u carpet -n 50 --no-pager
نکتههایی که کمتر کسی میداند
- تعداد worker معمول
2 × هسته + 1است، اما روی VPSهای کمحافظهی ایرانی حافظه محدودکننده است نه CPU؛ هر worker جنگو ۸۰ تا ۱۵۰ مگابایت میگیرد. --max-requestsهر worker را پس از چند صد درخواست بازسازی میکند؛ درمان ساده و مؤثر نشت حافظهی تدریجی کتابخانهها.systemctl reload carpet(سیگنال HUP) workerها را بدون قطع درخواستهای در جریان عوض میکند؛ برای استقرار نسخهی جدید بهجای restart از آن استفاده کنید.- با socket activation، systemd سوکت را نگه میدارد و در لحظهی restart درخواستها در صف میمانند و 502 نمیگیرند.
- در ایران برای pip روی سرور، میرور داخلی را در
/etc/pip.confتنظیم کنید و برای apt هم از مخزنهای آینهی داخلی استفاده کنید؛ نصبها از ده دقیقه به چند ثانیه میرسند.