Ubuntu 18.04部署Django遇Gunicorn连接失败,求SECRET_KEY配置方案
Hey there, let's work through your questions and fix that connection reset issue you're hitting with Gunicorn and Django!
First off, Gunicorn doesn't need to "activate" a virtual environment the way you do in your shell. When you run the Gunicorn binary located inside your virtual environment (like you're doing in your systemd file: /home/<name>/.virtualenvs/<appname>/bin/gunicorn), it automatically uses that virtual environment's Python interpreter, installed packages, and isolated environment. The "activation" step in your shell is just for setting shell-specific variables (like PATH) to make it easier to run commands—Gunicorn doesn't require that.
The problem here is your SECRET_KEY setup: virtualenvwrapper's postactivate script only runs when you manually activate the virtual environment in a shell. Systemd doesn't trigger this script when starting the Gunicorn service, so your Django app can't pull the SECRET_KEY from the environment, leading to a startup failure (which causes the connection reset error you're seeing).
Since systemd doesn't run postactivate, you need to pass the SECRET_KEY directly to the Gunicorn process. Here are the most reliable methods:
1. 直接在systemd服务文件中设置环境变量
Modify your gunicorn.service file to add an Environment line under the [Service] section:
[Service] User=<name> Group=www-data WorkingDirectory=/home/<name>/projects/<projectname>/<appname> # Add this line to set SECRET_KEY Environment="SECRET_KEY=my-secret-key" ExecStart=/home/<name>/.virtualenvs/<appname>/bin/gunicorn \ --access-logfile - \ --workers 3 \ --bind unix:/run/gunicorn.sock \ <appname>.wsgi:application
After making this change, reload systemd and restart Gunicorn:
sudo systemctl daemon-reload sudo systemctl restart gunicorn.service
2. 从专用配置文件加载环境变量(更安全,推荐)
If you don't want to put your secret directly in the systemd file, create a .env file in your project directory (e.g., /home/<name>/projects/<projectname>/.env) with:
SECRET_KEY=my-secret-key
Then restrict access to this file so only your user can read it:
chmod 600 /home/<name>/projects/<projectname>/.env
Update your systemd service to load this file:
[Service] # Other config stays the same EnvironmentFile=/home/<name>/projects/<projectname>/.env
Again, reload systemd and restart Gunicorn after this change.
3. 手动调用postactivate(不推荐)
If you really want to use your existing postactivate script, you can wrap the Gunicorn command in a bash shell that sources the script first. This is less reliable though, as it depends on shell paths and virtualenvwrapper's setup:
ExecStart=/bin/bash -c "source /home/<name>/.virtualenvs/<appname>/bin/postactivate && /home/<name>/.virtualenvs/<appname>/bin/gunicorn ..."
Let's cover the do's and don'ts for handling Django's SECRET_KEY:
- Never hardcode it in
settings.py: This is a critical security risk—if your code gets pushed to a public repo (or even a private one with the wrong people), your secret is exposed. - Use environment variables or secure config files: As we covered above, keep the secret out of version control and only accessible to the server processes that need it.
- Rotate secrets regularly: If you suspect your
SECRET_KEYhas been leaked, generate a new one immediately with this command:
Note: Rotating the key will invalidate all existing user sessions, so plan for this (e.g., notify users they'll need to log back in).python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" - Lock down file permissions: Any file storing your
SECRET_KEYshould have600permissions, so only the owner (and root) can read it.
To confirm the SECRET_KEY issue is causing your connection reset, check Gunicorn's logs:
journalctl -u gunicorn.service
If you see an error like ImproperlyConfigured: Set the SECRET_KEY environment variable, that's the smoking gun. Fixing the environment variable setup should resolve the connection reset error.
内容的提问来源于stack exchange,提问作者Morten

