Deploy Django With Easypanel

Deploy Django with Easypanel, a Docker-based server control panel: create an app service from GitHub with a Dockerfile or buildpacks, add Postgres and Redis services, set environment variables, mount volumes for media, and enable HTTPS on a custom domain.

Problem statement

You have a VPS and want a dashboard to deploy apps and databases with HTTPS, without learning Kubernetes or writing every Compose file and Nginx config by hand. Easypanel is a server control panel built on Docker that creates app and database services from a web interface and routes domains with automatic certificates. Django works well on it once the app listens on the configured port, reads its settings from environment variables, and keeps uploads in a volume or object storage.

Django on EasypanelInstall panelDocker on VPSApp serviceGitHub + DockerfilePostgres, Redispanel servicesDomainauto HTTPSEasypanel creates containers and routes; Django provides a port and environment settings.
  1. Install Easypanel on a fresh VPS with Docker using the official command, and set a strong admin password.
  2. Create a project, then add Postgres and Redis services; note their internal host names and credentials.
  3. Add an App service from GitHub, build with a Dockerfile (or buildpacks/Nixpacks), and set the start command to Gunicorn.
  4. Add environment variables (DATABASE_URL, SECRET_KEY, ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS) and set the proxy port to 8000.
  5. Attach your domain with HTTPS, mount a volume for media, and run migrations on deploy.

Step-by-step solution

1. Install Easypanel

On Ubuntu with ports 80 and 443 free:

curl -sSL https://get.docker.com | sh
docker run --rm -it \
  -v /etc/easypanel:/etc/easypanel \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  easypanel/easypanel setup

Open the panel on port 3000, create the admin user, and then set a panel domain with HTTPS so the dashboard is not served over plain HTTP. Check Easypanel's documentation for the current install command.

2. Create database services

In a project, add a Postgres service and a Redis service. Each shows connection details, including an internal host name of the form project_service. Use the internal URL from Django; do not expose database ports publicly.

DATABASE_URL=postgres://postgres:...@shop_db:5432/shop
REDIS_URL=redis://default:...@shop_redis:6379
service types and settingsCommand or imageDomain / volumeApp: webgunicorn on 8000domain + media volumeApp: workercelery workernonePostgrespostgres!data volumeRedisredisoptional volumeOnly the web app gets a domain; databases stay internaldjango-deployment.com
Configure backups for the Postgres service; volumes alone are not backups.

3. Create the app service

Add an App service, connect GitHub, and pick the repository and branch. Choose the build method:

  • Dockerfile for full control (recommended).
  • Buildpacks or Nixpacks for automatic Python detection.

Set the start command if the Dockerfile does not define one:

gunicorn config.wsgi --bind 0.0.0.0:8000 --workers 3 --access-logfile -

4. Environment, domain, and port

In the app's environment tab, paste the variables. In Domains, add shop.example.com, enable HTTPS, and set the proxy port to 8000. Point DNS at the server. In Django:

ALLOWED_HOSTS = os.environ["ALLOWED_HOSTS"].split(",")
CSRF_TRUSTED_ORIGINS = os.environ["CSRF_TRUSTED_ORIGINS"].split(",")
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

5. Migrations, media, and workers

Run migrations as part of the deploy, either in the container start command for a single instance, or with a deploy script. Mount a volume at /app/media for uploads, or better, configure object storage. Do not mount a volume over the static files directory; it hides new files after the next deploy. Add a second App service from the same repository with the command celery -A config worker -l info and no domain.

setup order1Add Postgres and Redisnote internal hosts2Add app from GitHubDockerfile build3Set environmentURLs, secrets, hosts4Domain + port 8000HTTPS on5Deploy and migratecheck logsDatabases first, so their URLs exist when the app startsdjango-deployment.com
The app log in the panel shows Django tracebacks if a setting is missing.

Explanation

Easypanel runs every service as a Docker container (in Swarm mode) and configures a Traefik-based proxy to route domains to the right container and port with Let's Encrypt certificates. App services are built from Git or pulled as images, and database services come from templates. From Django's point of view, it is a container with environment variables and a reverse proxy in front, the same as any Docker host.

Edge cases / notes

  • Licensing and plans. Easypanel has a free tier with limits and paid plans; check what the free tier allows for your number of projects.
  • Build load. Building on the production server uses its CPU and memory; small servers can slow down during builds.
  • Updates. Keep Easypanel, Docker, and the OS updated; the panel controls the Docker socket.

Next steps

FAQ

What port should Django use on Easypanel?

Any port, as long as Gunicorn binds 0.0.0.0 on it and the domain's proxy port matches. 8000 is common.

Can Easypanel run Celery?

Yes, as a second app service from the same repository with a Celery command.

Where should media files go?

In a mounted volume or, better, object storage. Container filesystems are replaced on each deploy.

Does Easypanel back up databases?

It offers backup options for database services; configure and test them to an off-server destination.

Keep going