We use cookies in order to improve your experience


Develatio’s Django AMI will let you deploy a full Django project in less than a minute and with zero configuration, enabling you to focus on what’s really important: your own code!


This AMI is provisioned with several core components, configured for production usage.

  • Debian Buster (10) - The latest stable version of Debian
  • NGINX - Provided with a simple configuration for reverse proxying uWSGI and the ability to add a custom SSL cert with zero effort
  • uWSGI - Sane settings for production services, like auto reloading a Django app, default harakiri, threaded-enabled, etc…
  • Python 3.7 and PIP
  • Netdata - Monitor your EC2 instance without further complications, get alerts when something goes wrong. Accessible behind a basic auth login with user/password

Bonus components available in the Develatio - Celery Celerybeat - Python 3 AMI:

  • Celery - A task queue for Django
  • Celery beat - Runs your scheduled tasks
  • Flower - Monitor your celery tasks and queues easily. Accessible behind a basic auth login


Aside from easy deployments, security is another topic that we're really concerned about. That's why this AMI is also provisioned with some extra components that will let you secure, prevent and monitor your EC2 instance for attacks, intrusions, FS modification attempts, etc…

  • SSH hardening - SSH login using root has been disabled. Only key-based logins are enabled. Only v2 of SSH protocol is enabled
  • RKHunter - Daily scanning and automatic updates
  • Fail2ban - Block any IP trying to brute-force your EC2 instance
  • Auditd and ACCT - Any suspicious activity will be recorded. This includes tampering Auditd itself, configuration files and logs, kernel modprobing, kexec usage, mount operations, time and date modification attempts, user/group operations, logins, access failure (unauthenticated file access/modification/deletion), power state changes, DAC modifications, any 32 API usage, ptrace-based code injections/debugs, any commands executed by root, etc…

System tweaks

  • SSH tweaks:
    • increased connection timeout
  • sysctl tweaks:
    • Increased file descriptor limit
    • Increased inotify limit
    • Enabled execshield
    • Network stack tuning (increased TCP buffer size, queue for input packets, selective logging, reverse path filtering, no routing modifications, prevent TCP time-wait attacks, prevent SYN attacks, etc…)
    • Discourage swapping idle processes
  • Bash tweaks:
    • readonly HISTFILE
    • readonly HISTIGNORE
    • don't ignore commands
    • increased HISTSIZE
  • A swap file has been added
  • Improved I/O scheduler and I/O related tweaks

Folders structure

The AMI is designed in such a way that you only need to deal with one folder: /var/www/webapp. In that folder you'll have all your configurations and your source code.

This is how the AMI will look like when you launch it:

├── conf
│   ├── autorun.sh
│   ├── celery
│   │   └── celery.conf
│   ├── cron
│   │   ├── d
│   │   ├── daily
│   │   ├── hourly
│   │   ├── monthly
│   │   └── weekly
│   ├── global
│   │   ├── hostname
│   │   └── timezone
│   ├── mail
│   │   ├── msmtprc
│   │   └── notifications
│   ├── netdata
│   │   └── password
│   ├── nginx
│   │   ├── helloworld.crt
│   │   ├── helloworld.key
│   │   └── web.conf
│   └── uwsgi
│       └── uwsgi.ini
└── src
    ├── helloworld
    │   ├── __init__.py
    │   ├── celeryapp.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── manage.py
    └── requirements.txt

You can check the contents of our demo project here

Let's start with the more obvious part, the src folder. This is the usual Django folder structure and a requirements.txt file.

That said, let's move on to the conf folder. That folder contains the configuration files for each service. You'll be able to edit the behavior of all the services from here, without having to edit anything else. Just apply your changes and restart the services using the usual systemd commands.

Basic settings

Here's a quick run-trough the basic conf files:

  • celery/celery.conf - This file won't be used in this AMI, but in the Develatio - Celery - Python 3.7 AMI, so you'll most probably want to keep it in the same repository as the other configuration files. You can tweak the logs path, the node's names, the concurrency, and any other usual stuff you'd expect to be able to configure in Celery. Make sure to change Flower‘s default user/password: flower:flower

  • cron/* - This folder contains the usual /etc/cron.* folders structure you'd expect to have. Scripts inside these folders (d, daily, hourly, monthly, weekly) will be copied to the corresponding folder in /etc/cron.*.

  • global/hostname - Sets the hostname. Use any of the available variables:








    • OS

    • IP_ADDR

      Keep in mind that the value of the resulting string will be slugified according to RFC 1123, which means that only letters, digits and hyphens are allowed

  • global/timezone - Sets the timezone. Use whatever you'd normally put in your /etc/timezone file. Check /usr/share/zoneinfo/.

  • mail/msmtprc - You can configure an SMTP server which will be used to send alerts from Auditd, RKHunter, Fail2ban, etc…

  • mail/notifications - Write a single line containing a valid email address to which the alerts should be sent

  • netdata/password - This is the file you'll want to edit in order to change Netdata's basic auth user/password. Use the usual command to generate a valid NGINX username and hash: openssl passwd -apr1 netdata. The user/password in the demo AMI is netdata/netdata

  • nginx/web.conf - This is the NGINX's website configuration. The default file is configured to reverse proxy everything to the uWSGI server. It will listen by default on port 80, but there is a commented section in the configuration that will enable HTTPS using your certificates (nginx/helloworld.crt and nginx/helloworld.key)

  • uwsgi/uwsgi.ini - The uWSGI server configuration. Keep in mind that it will load the HelloWorld Django app, so you'll have to change this

Advanced settings

There are some extra stuff you must know. First of all, let's start with the one file that hasn't been covered yet: the autorun.sh. This script will be executed at every boot, using the admin user. Keep in mind that the AMI will make read-only the file on every boot, and it will chown it to admin.

Why is this script useful? You might want to execute some extra tasks after booting. Maybe collect static files or maybe run migrations.

Secondly, there are some commands that you can run at any time in order to apply the changes you've made in the configuration files:

  • configure_cron - Removes all user-provided scripts from all /etc/cron.* folders and then moves a fresh copy of the user-provided scripts, as described in the description of the cron/ folder
  • configure_hostname - Applies the configuration from global/hostname (in /var/www/webapp/conf/)
  • configure_notifications - Applies the configuration from conf/mail/notifications (in /var/www/webapp/conf/)
  • configure_timezone - Applies the configuration from global/timezone (in /var/www/webapp/conf/)

Tips & tricks

Unattended updates

This AMI has two systemd services that will run unattended updates: apt-daily.service and apt-daily.timer. If you don't want to automatically keep your system updated, feel free to disable those services using the usual systemd commands (systemctl stop | disable).


We strongly recommend to set proper permission to your conf and your src folders. We set the following permissions in our base AMI.

chown root:root /var/www/webapp

setfacl -R -d -m u:admin:rwx /var/www/webapp
setfacl -R -d -m g:www-data:rx /var/www/webapp
setfacl -R -d -m o::--- /var/www/webapp

setfacl -R -m u:admin:rwx /var/www/webapp
setfacl -R -m g:www-data:rx /var/www/webapp
setfacl -R -m o::--- /var/www/webapp

This will make the files

  • to be owned by root
  • to be read-only by the group www-data
  • to be writeable by the user admin

You'll probably want to set write permissions to some folders (files uploaded by users?). We recommend using the autorun.sh. Keep in mind that the autorun.sh will be ran with the admin user, so you'll need to use sudo.

sudo setfacl -R -d -m u:admin:rwx /var/www/webapp/src/user_uploads/
sudo setfacl -R -d -m g:www-data:rwx /var/www/webapp/src/user_uploads/
sudo setfacl -R -d -m o::--- /var/www/webapp/src/user_uploads/

sudo setfacl -R -m u:admin:rwx /var/www/webapp/src/user_uploads/
sudo setfacl -R -m g:www-data:rwx /var/www/webapp/src/user_uploads/
sudo setfacl -R -m o::--- /var/www/webapp/src/user_uploads/

Service management

The AMI provides the following systemd services, which you can use using the usual commands (systemctl status | start | stop) in order to manage your application:

  • celery - Control Celery
  • celerybeat - Control Celery Beat
  • flower - Control Flower (Celery's web monitor)
  • uwsgi - Control the uWSGI server (NGINX will reverse proxy to this server)
  • nginx - Control the NGINX web server

In case of failure or unexpected errors, use journalctl -f -u <service> to monitor the services.


We recommend to use Packer and this AMI as a base image to build your own AMIs right from your CI/CD pipeline. Use the provisioners section in your Packer script in order to copy your configuration files to the conf folder and your source code to the src folder. You might also want to run any additional scripts or commands that don't require the project to be running, for example, package managers install process (npm, composer, pip, etc…).

Task queue with Celery

The Develatio - Celery Celerybeat - Python 3 is configured with a dummy in-memory broker. You'll probably want to replace it with a Redis server.

Django settings

All the settings are hardcoded in the settings.py file. We recommend using django-decouple in order to be able to decouple Django's config from the code itself.


v0.4.0 - 08/01/2020

  • Fixed a bug that was causing cron configuration files to be skipped

v0.3.0 - 31/08/2019

  • Fix hostname not routing to localhost
  • Fix pip related installation problems

v0.2.0 - 29/08/2019

  • Add cron support
  • Extra documentation

v0.1.0 - 21/08/2019

  • This AMI and it's components where created