Recommended Free Tools
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
To install Django on a Linux VPS for production, you need more than pip install django. Build four layers: a secured Linux host, an isolated Python environment with your pinned application dependencies, a production WSGI or ASGI server, and Nginx as the public-facing web server. Add a production database, systemd supervision, DNS, HTTPS, backups, and deployment checks before exposing the site to the internet.
What a production Django VPS actually includes
A VPS is a virtual Linux server with its own CPU, memory, storage, network address, and operating-system instance. Django runs as an application inside that server; it is not itself a complete internet-facing web server.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →A maintainable single-VPS deployment normally contains these layers:
- Linux and SSH: the operating system, firewall, updates, and a non-root deployment account.
- Python environment: a virtual environment containing Django and the exact versions required by the project.
- Application server: Gunicorn for a conventional synchronous WSGI application, or an ASGI server when the project needs asynchronous request handling or long-lived connections.
- Front-end web server: Nginx terminates TLS, serves static or media files where appropriate, validates hosts, and proxies dynamic requests to the application server.
- Data and operations: PostgreSQL or another production database, systemd, logs, DNS, certificates, backups, and a rollback procedure.
Django’s deployment guidance describes the development server as unsuitable for production. The runserver command is for development and testing; it should not be the process receiving public traffic.
#1 Best Overall
Check compatibility before creating the VPS
Supported Python and Django versions change. Check the Django release supported by your project and the Python version required by every dependency before selecting an operating-system image. The currently published Gunicorn installation guidance states that Gunicorn requires Python 3.12 or newer, so a project using Gunicorn must be tested against a compatible interpreter before provisioning.
Distribution package names and paths differ between Ubuntu, Debian, Fedora, and other Linux distributions. The commands below use Debian/Ubuntu-style names and paths. Adapt package names, firewall commands, service locations, and database-driver packages to your distribution.
Have these values ready
- VPS public IP address and a DNS name such as
example.com. - An SSH key and a non-root deployment username.
- The project’s Git repository or release artifact.
- The Python version supported by the project.
- A dependency lock file or pinned
requirements.txt. - Database credentials and the intended database host.
- The project’s WSGI or ASGI module, commonly
project.wsgi:applicationorproject.asgi:application.
1. Provision the VPS and connect over SSH
Choose a supported Linux image, create or import an SSH key, and create a regular user for deployment. Do not perform routine application work as root. Use the provider’s console only for initial recovery or account setup.
- Record the server address and verify that the DNS name you will use is under your control.
- From your local computer, connect with the deployment account:
ssh deploy@example.com. Replace the name and host with your own values. - Confirm the operating system and Python versions:
cat /etc/os-releaseandpython3 --version. - Give the deployment account only the administrative access it needs, normally through a controlled
sudopolicy.
After SSH works, configure the host firewall to allow SSH and, later, HTTP and HTTPS. Keep the SSH port reachable from your administration network; do not lock yourself out before testing a second session.
2. Update Linux and install build prerequisites
Start with current security updates. On Debian or Ubuntu, a typical base installation is:
sudo apt update
sudo apt upgrade -y
sudo apt install -y python3 python3-venv python3-pip git build-essential nginx
Install additional development headers or database client libraries required by your project. For example, a PostgreSQL adapter may require PostgreSQL client development packages; the exact package depends on the adapter and distribution. Read the project’s installation instructions rather than adding packages speculatively.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteDo not assume the distribution’s Django package is the version your application needs. The virtual environment should receive the version selected by the project’s lock or requirements file.
3. Put the project in a controlled directory
Use a predictable directory such as /srv/myproject. Keep the application source separate from uploaded media, collected static files, logs, and secrets.
sudo mkdir -p /srv/myproject
sudo chown -R deploy:deploy /srv/myproject
cd /srv/myproject
git clone YOUR_REPOSITORY_URL app
cd app
Replace YOUR_REPOSITORY_URL with the repository address and substitute the branch or tag used for the release. If the source is copied as an archive instead, verify its checksum and ownership before installing it.
Rank #2
Create and activate the virtual environment
cd /srv/myproject/app
python3 -m venv /srv/myproject/venv
. /srv/myproject/venv/bin/activate
python -m pip install --upgrade pip
Install the project’s pinned dependencies, for example:
python -m pip install -r requirements.txt
Install Gunicorn inside this environment when the project uses WSGI. Gunicorn’s installation guidance specifically recommends installing it in a virtual environment so application dependencies remain isolated from the operating system. If the project uses ASGI, install the selected ASGI server and its pinned version instead.
Every command in later steps should use the same interpreter. A reliable pattern is /srv/myproject/venv/bin/python and /srv/myproject/venv/bin/gunicorn, which avoids accidentally invoking a system-wide package.
4. Configure production settings securely
Do not commit production secrets to Git. Supply them through environment variables or a root-readable environment file outside the repository. At minimum, production settings need a large random SECRET_KEY, DEBUG = False, and an accurate ALLOWED_HOSTS list.
Django’s deployment checklist warns that “The internet is a hostile environment.” Treat the secret key as a credential: restrict file permissions, rotate it through a planned process, and never paste it into public issue trackers or logs.
Example environment file
sudo install -o root -g www-data -m 640 /dev/null /etc/myproject.env
sudoedit /etc/myproject.env
DJANGO_SETTINGS_MODULE=project.settings.production
SECRET_KEY=replace-with-a-long-random-value
DEBUG=False
ALLOWED_HOSTS=example.com,www.example.com
DATABASE_URL=replace-with-your-database-connection
Your settings code must actually read these variables and convert booleans, lists, and connection values to the types it expects. Do not assume that writing DEBUG=False in a file automatically changes Django unless the settings module loads that file.
Set trusted origins, secure cookie options, CSRF configuration, email credentials, storage credentials, and allowed proxy settings according to the project. Ensure the public hostnames in ALLOWED_HOSTS exactly match the names users will send. With DEBUG = False, Django requires a suitable value; leaving it empty causes host validation failures.
5. Configure the production database and release files
A development SQLite file may be adequate for local work but should not be treated as the default production plan for a busy or multi-process application. PostgreSQL is a common production choice. You can run it on the VPS or use a managed database.
| Choice | Advantages | Responsibilities and trade-offs |
|---|---|---|
| PostgreSQL on the VPS | Local network latency and one-server simplicity. | You must patch the database, monitor storage, secure access, test backups, and recover it when the VPS fails. |
| Managed PostgreSQL | Provider-managed maintenance and backup features, with database access separated from the web host. | Recurring cost, network configuration, provider-specific recovery procedures, and possible latency between the VPS and database. |
Whichever option you choose, create a least-privilege application role, restrict network access, and test restoring a backup. Then apply schema migrations from the activated environment:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemscd /srv/myproject/app
/srv/myproject/venv/bin/python manage.py migrate --settings=project.settings.production
Only run migrations against the intended production database. Confirm the connection string and settings before executing the command.
Create an administrator when required
/srv/myproject/venv/bin/python manage.py createsuperuser --settings=project.settings.production
This command is interactive. Use a strong, unique password and protect the administration URL with the application’s normal authentication and HTTPS.
Collect static files
/srv/myproject/venv/bin/python manage.py collectstatic --noinput --settings=project.settings.production
Set STATIC_ROOT to a directory Nginx can read, and configure MEDIA_ROOT separately for user uploads. Static files are release artifacts; media files are user data and need independent backup and access rules. If the project uses remote or manifest-based storage, follow that backend’s configuration instead of exposing arbitrary directories.
6. Choose WSGI or ASGI deliberately
WSGI is the conventional synchronous interface and works with Gunicorn. ASGI is the asynchronous-friendly standard supported by Django for async request handling and features such as long-lived connections. Select the interface that matches the application, not merely the server most often mentioned in tutorials.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →| Consideration | WSGI with Gunicorn | ASGI deployment |
|---|---|---|
| Workload | Synchronous views and ordinary HTTP requests. | Async views, WebSockets, streaming, or other long-lived connections. |
| Application entry point | project.wsgi:application |
project.asgi:application |
| Operations | Simple, widely understood process model. | Requires an ASGI-capable server and careful validation of async-compatible dependencies. |
| Proxying | Nginx forwards ordinary HTTP requests. | Nginx must preserve the headers and upgrade behavior required by the protocol used. |
Do not move a synchronous project to ASGI expecting automatic speed improvements. Confirm that the application and its dependencies support the execution model you select.
7. Test the application server locally
Before adding Nginx, run the production server on loopback or a Unix socket and test it from the VPS. For a WSGI project using Gunicorn:
cd /srv/myproject/app
/srv/myproject/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 project.wsgi:application
Replace project with the package containing wsgi.py. The worker count is an operational starting point, not a universal performance prescription; size it against available memory and workload, then measure.
From another SSH session, request the local endpoint with curl -I http://127.0.0.1:8000/. Stop the foreground process after confirming that Django loads. If it fails, read the traceback, verify the settings module, confirm that the virtual environment contains every dependency, and check database connectivity.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
8. Create a systemd service
A foreground Gunicorn command ends when the SSH session closes. systemd starts the service at boot, restarts it after failure, and records its standard output in the journal.
Rank #4
Create a service file such as /etc/systemd/system/myproject.service:
[Unit]
Description=Gunicorn for myproject
After=network.target
[Service]
User=deploy
Group=www-data
WorkingDirectory=/srv/myproject/app
EnvironmentFile=/etc/myproject.env
ExecStart=/srv/myproject/venv/bin/gunicorn --workers 3 --bind unix:/run/myproject.sock project.wsgi:application
Restart=on-failure
[Install]
WantedBy=multi-user.target
Adjust the user, paths, worker count, entry point, and environment-file location. The service account needs read access to the source and write access only where the application genuinely requires it. A Unix socket keeps the application server off the public network and gives Nginx a simple local endpoint.
- Reload unit files:
sudo systemctl daemon-reload. - Enable startup and start the service:
sudo systemctl enable --now myproject. - Check status:
sudo systemctl status myproject. - Read recent logs:
sudo journalctl -u myproject -n 100 --no-pager.
If the service fails, systemd will report an exit status, but the application traceback is usually in the journal. Correct the underlying path, permission, import, or configuration error rather than repeatedly restarting it.
Unix socket versus loopback binding
A Unix socket is local-only and avoids a TCP port for the proxy connection. A loopback address such as 127.0.0.1:8000 is easy to inspect with ordinary network tools and can simplify some container or monitoring setups. Both keep the application off the public interface when Nginx is the only externally exposed service. Whichever you choose, make the socket path, ownership, and Nginx configuration agree.
9. Put Nginx in front of Django
Nginx should accept public HTTP and HTTPS traffic, reject unknown hosts, serve collected static files, and forward dynamic requests to the local application server. Create a site configuration such as /etc/nginx/sites-available/myproject:
server {
listen 80;
server_name example.com www.example.com;
location /static/ {
alias /srv/myproject/static/;
}
location /media/ {
alias /srv/myproject/media/;
}
location / {
proxy_pass http://unix:/run/myproject.sock;
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;
}
}
Use the project’s actual static and media directories. Verify that the Nginx worker can read them, and do not expose the whole project directory. Some Nginx versions require a socket proxy syntax with a trailing colon or a separate upstream block; validate the syntax on the installed version rather than copying an incompatible form.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Enable the site, for example with
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled/myproject. - Check the configuration:
sudo nginx -t. - Reload only after the test succeeds:
sudo systemctl reload nginx.
Configure a default server that rejects unknown hostnames instead of accidentally serving your application for every address on the VPS. Django’s deployment checklist also recommends host validation in the web server.
DNS and HTTPS
Create an A or AAAA record for the chosen hostname pointing to the VPS address. Wait for the record to resolve, then obtain a certificate from a trusted certificate authority using your distribution’s supported ACME tooling. Configure Nginx to listen on 443, reference the certificate and private key, and redirect port 80 to HTTPS.
After TLS is active, enable Django’s secure-cookie and proxy-aware settings appropriate to your configuration. Test the redirect, certificate chain, login flow, CSRF-protected forms, static files, uploads, and any WebSocket or streaming endpoint. Never send production credentials over an unencrypted HTTP connection.
Best Value
10. Run deployment checks before opening the site
Use the production settings explicitly:
/srv/myproject/venv/bin/python manage.py check --deploy --settings=project.settings.production
Django recommends this check before release. Treat every warning as a decision to investigate, not as harmless output. Then exercise the application through its public HTTPS hostname.
- Open the home page and a representative authenticated page.
- Log in and log out; verify session cookies are secure.
- Submit a CSRF-protected form.
- Load CSS, JavaScript, images, and user-uploaded media.
- Confirm database reads and writes.
- Inspect Nginx access/error logs and the systemd journal.
- Verify that an invalid host is rejected.
- Confirm that the certificate is valid and HTTP redirects to HTTPS.
Keep a release record containing the deployed commit, migration result, configuration version, and rollback target. A deployment is not complete until you know how to return to the previous working release.
Security and maintenance checklist
- Keep Linux, Python dependencies, Django, Nginx, and the database patched within their supported versions.
- Use SSH keys, disable password authentication when practical, and restrict administrative access.
- Keep
SECRET_KEY, database passwords, API keys, and certificate private keys out of source control. - Keep
DEBUG = Falsein production and configureALLOWED_HOSTSprecisely. - Expose only required network ports; the application server and database should not be publicly reachable unless a documented design requires it.
- Separate static assets from media uploads and back up media and database data independently.
- Monitor disk space, memory, worker restarts, certificate expiry, and failed login or error spikes.
- Test restoration, not merely backup creation. Record where backups live and who can restore them.
- Use a documented rollback: identify the previous code revision, reverse or safely manage migrations, restore compatible environment values, and restart services in a controlled order.
Troubleshooting common failures
“502 Bad Gateway” from Nginx
Check sudo systemctl status myproject and sudo journalctl -u myproject. Confirm that the service is running, that the socket exists at the exact path in the Nginx configuration, and that Nginx has permission to connect to it. If using loopback instead, verify that the port and address match.
Django reports “DisallowedHost”
Add the exact public hostname to ALLOWED_HOSTS, reload the application service, and ensure Nginx passes the original Host header. Do not solve this by allowing every host.
Static files return 404
Run collectstatic with production settings, verify STATIC_ROOT, compare it with Nginx’s alias, and check directory permissions. A successful application response does not prove that Nginx is serving the correct static directory.
Recommended Free Tools
Database connection errors during migration
Check the environment file loaded by systemd and by your shell, confirm the database hostname, port, role, password, SSL requirement, and firewall rules, and test connectivity from the VPS. Ensure the migration command uses the same settings module as the service.
Changes are not visible after deployment
Confirm that the intended Git revision is installed, restart or reload the application service when code or environment values changed, rerun static collection when assets changed, and inspect logs for import or migration errors. Browser and proxy caches may also retain old assets; use versioned static filenames or the project’s cache-busting configuration.
When a single VPS is no longer enough
A single VPS is a useful starting architecture, but it combines application, proxy, and often database failure domains. As traffic or availability requirements grow, separate the database, add a second application instance behind a load balancer, move static and media storage to durable object storage, and centralize logs and monitoring. The same principles remain: pinned dependencies, explicit production settings, supervised processes, HTTPS, tested backups, and a reversible release process.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.

