{"id":23608345,"url":"https://github.com/stuartmackay/django-ansible-template","last_synced_at":"2026-05-03T15:34:33.680Z","repository":{"id":269533904,"uuid":"739102832","full_name":"StuartMacKay/django-ansible-template","owner":"StuartMacKay","description":"An Ansible playbook for deploying a Django-based website to a Virtual Private Server","archived":false,"fork":false,"pushed_at":"2025-07-18T15:49:27.000Z","size":125,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-18T19:58:09.008Z","etag":null,"topics":["ansible","deploy","django","playbook","website"],"latest_commit_sha":null,"homepage":"","language":"Jinja","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StuartMacKay.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-04T19:22:18.000Z","updated_at":"2025-07-18T15:49:31.000Z","dependencies_parsed_at":"2024-12-24T09:05:55.498Z","dependency_job_id":"3b84f000-3612-41bb-a5c1-e29552131c14","html_url":"https://github.com/StuartMacKay/django-ansible-template","commit_stats":null,"previous_names":["stuartmackay/django-ansible-template"],"tags_count":2,"template":true,"template_full_name":null,"purl":"pkg:github/StuartMacKay/django-ansible-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StuartMacKay%2Fdjango-ansible-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StuartMacKay%2Fdjango-ansible-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StuartMacKay%2Fdjango-ansible-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StuartMacKay%2Fdjango-ansible-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StuartMacKay","download_url":"https://codeload.github.com/StuartMacKay/django-ansible-template/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StuartMacKay%2Fdjango-ansible-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32575111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","deploy","django","playbook","website"],"created_at":"2024-12-27T14:13:56.953Z","updated_at":"2026-05-03T15:34:33.664Z","avatar_url":"https://github.com/StuartMacKay.png","language":"Jinja","funding_links":[],"categories":[],"sub_categories":[],"readme":"==================\nAnsible Virtualenv\n==================\nThis template contains an ansible playbook for deploying a Django-based\napp server running a Debian-based operating system, to either a staging\nor production environment running on a Virtual Private Server or a Dedicated\nServer. The project uses a virtualenv for running Django and Celery so the\napplication is completely isolated from the system python.\n\nThis template is intended to be used with Django sites created using the\n`django-project-template`_. It should be easily changed to suit any Django\nproject. Only the environment variables used to configure Django should\nneed changing.\n\n.. _django-project-template: https://github.com/StuartMacKay/django-project-template\n\nProject Layout\n--------------\n::\n\n    .\n    ├── .envrc\n    ├── group_vars\n    │   ├─── appserver\n    │   │    └── vars.yml\n    │   ├─── staging\n    │   │    ├── vars.yml\n    │   │    └── vault.yml\n    │   └─── production\n    │        ├── vars.yml\n    │        └── vault.yml\n    ├── inventories\n    │   └── single.yml\n    ├── keys\n    │   ├── id_rsa-project\n    │   └── id_rsa-project.pub\n    ├── molecule\n    │   └── default\n    ├── roles\n    │   ├── app\n    │   ├── base\n    │   ├── celery\n    │   ├── certbot\n    │   ├── ...\n    │   └── users\n    ├── playbook.yml\n    └── requirements.txt\n\n``group_vars`` contains the variable definitions for deploying appservers to\nstaging and production environments. Each environment has the sensitive\nvariables stored in a vault. The password for each vault is 'password'. You\nMUST at least change the password for production.\n\n``inventories`` contains sample inventories for deploying to different server\nconfigurations. ``single.yml`` is the only example included right now and if\nfor deploying the application, database, and message broker to a single server.\n\n``keys`` contains a sample SSH key which can be added to your key chain, using\n``ssh-add`` to get start with deployments to a development server. It is also\nused to test the playbook. The public key is used in the environment variables\nfor creating a user account for the deployment and for managing the server.\nSince this key is in a public repository it is insecure by default. You MUST\nreplace this with a secure key for your production deployments.\n\n``molecule`` contains all the files used to test the playbook using Docker.\nThe tests using the django-watchman end-point to verify the status of the\ndatabase, storage and cache backends. This will not cover everything but it\nis a good test of whether Django is functioning.\n\n``roles`` are organised by feature and contain everything needed to deploy\nthe app server. Within each role the tasks are organised with separate files\nfor each step. The intention is to make the playbook modular and so easy to\ncomprehend and easy to refactor and add new features. This means there is\nprobably more yaml than is healthy but you will find that things are easy\nto find and it's easy to throw away the stuff you don't want. There are\nseparate tasks for each operating system, for example, when installing\nnative packages. The variables for role define sensible defaults for each\ntask. You can override these as needed, in the group_vars.\n\n``playbook.yml`` simply runs through all the roles to install everything\nneeded for the app server. It is opinionated. It assumes there are two\nenvironments, staging and production, which can be deployed. For local\ndevelopment this is probably sufficient. For large production systems this\nis really only a starting point. Any medium or large-scale system will be\ndeployed across multiple servers, with load balancing, database failover,\netc.\n\n``requirements.txt`` contains all the packages to run anisble and molecule\nfrom a virtual environment. There is also an direnv configuration file,\n``.envrc`` so you can activate the virtualenv automatically whenever you\n``cd`` to the directory.\n\nVariables\n---------\nVariables can be defined at many levels in a playbook, each with different\npriorities. This project tries to keep things simple, easy to understand,\nand so stay sane. There are three levels:\n\n1. Role variables, which provide sensible defaults for configuring a service.\n   For example, roles/postgresql/defaults/main.yml\n\n2. Group variables, which define the environment for servers, either by the\n   role they play, e.g. appserver, or the environment, e.g. production.\n\n3. Finally there are deployment variables, which define how the application\n   is deployed - which service is deployed where.\n\nRole variables provide the basic definitions, which are then overridden by group\nvariables, which in turn are overridden by deployment variables. Ansible's variable\nprecedence rules are much more complex than this, but this provides a simple,\nwell-organised, easy to work with, easy to manage, model.\n\nA number of variables, e.g. ``app_repository`` are set to ``!!null`. You need\nto set these (obviously) according to your application's needs.\n\nDjango Layout\n-------------\n::\n\n    \u003cproject\u003e\n       ├── .env\n       ├── .venv/\n       ├── manage.py\n       ├── requirements.txt\n       ├── \u003cproject\u003e\n       │   ├─── gunicorn.py\n       │   ├─── settings.py\n       │   └─── wsgi.py\n       ├── media/\n       ├── static/\n       ...\n\nThe playbook tasks assume the typical layout for a Django project. \u003cproject\u003e\nis the name of your site, and the root directory of the checked out repository.\nThe config files: settings.py etc are in a sub-folder with the same name. The\nvirtual environment for the application is in the .venv folder. A dotenv file\nis used to set the environment variables for django or celery.\n\nIf you're project is different, for example, if you follow the Two Scoops layout,\nyou can set the following variables:\n\n.. code-block:: yaml\n\n    # The dependencies required to run the app\n    python_requirements_file: \"{{ app_root_dir }}/requirements.txt\"\n\n    # The wsgi settings module\n    gunicorn_settings_module: \"config.wsgi\"\n    # The configuration file for gunicorn\n    gunicorn_configuration_file: \"{{ app_root_dir }}/config/gunicorn.py\"\n\n    # The django settings module\n    django_settings_module: \"config.settings\"\n\nSecurity\n--------\nBoth the staging and production group variables are stored in vaults.\nThe password for each is 'password'. Keep the same password for staging\nbut you MUST change the password for production. Also make sure you change\nthe secret key for Django. The same value is used in both and besides they\nare public knowledge.\n\nIn addition to the vaults for storing all sensitive information, ansible is\nconfigured so you never stored passwords, unprotected in files. The config\nfile, ``ansible.cfg`` sets ``ask_vault_pass`` and ``become_ask_pass`` so you\nwill always be prompted when doing a deployment. This is done even for\nstaging, so healthy habits are reinforced.\n\nGetting Started\n---------------\nCheck out the repository:\n\n..  code-block:: shell\n\n    git clone git@github.com:StuartMacKay/django-ansible-template.git deploy\n\nNext, create the virtualenv and install the requirements:\n\n..  code-block:: shell\n\n    cd deploy\n    make venv\n\nUse direnv to automatically activate the virtualenv when you cd to the\nplaybook directory:\n\n..  code-block:: shell\n\n    direnv allow .\n\nCreate an inventory from the example in the ``deploy`` directory:\n\n.. code-block:: shell\n\n   cp inventory.example staging\n\nNext edit the inventory to set the IP address of a local virtual machine:\n\n.. code-block:: ini\n\n    [appserver]\n    192.168.10.22\n\n    [staging]\n    192.168.10.22\n\nThe ``app_domain_name`` only needs to be defined for production deployments.\nAll the other variables in ``group_vars`` have sensible defaults so you can\ndo a deployment immediately.\n\nDeployments\n-----------\nWhen a Virtual Machine or Virtual Private Server (VPS) is created there are\nthree scenarios which determine how the machine is can be accessed:\n\n#. authenticate with username / password (root)\n#. authenticate with ssh key (root)\n#. authenticate with username / password (set during install) + sudo\n\nThe command to run an initial deployment has different variations to provision\nthe machine:\n\n1. authenticate with username / password (root)\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml -u root --ask-pass\n\n2. authenticate with ssh key (root)\n\n   Copy the private key to your ``.ssh`` directory. Make sure you don't overwrite\n   existing keys with the same name. The add the key to your key-chain using ``ssh-add``.\n   Now run the playbook:\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml -u root\n\n3. authenticate with username / password\n\n   This is the same as the first scenario. Only the username has changed:\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml -u \u003cusername\u003e --ask-pass\n\n    The ansible configuration file, ``ansible.cfg`` has the ``become_ask_pass``\n    option set to ``true`` so you will be prompted to enter the password in order\n    to become the root user, via ``sudo``.\n\nThe initial deployment locks down access to the server. You can only login using\nan authorized key; root login is disabled; logins can only be by admins (listed\nin the staging or production group_vars files) and a password is required for\nsudo access.\n\nSubsequent deployments are now run using:\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml\n\nassuming the your username on the ansible control node (i.e. the local machine)\nmatches one of the admin accounts added to the server. Otherwise you will have\nto pass the username to login as using ``-u``.\n\nEach of the roles have tags so you can run each role independently. If you\nrun a local virtual machine you can use this to verify each role is working:\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml --tags=\"memcached\"\n\nThe roles often have tags for each group of tasks so you can test each\nstep separately:\n\n..  code-block:: shell\n\n    ansible-playbook -i staging playbook.yml --tags=\"memcached.install\"\n\nTesting\n-------\nThe playbook is tested with ``molecule`` using the Docker driver - you will\nneed to have the Docker Engine installed. The test creates the containers\n(one for each operating system supported - currently only Ubuntu 22.04 LTS),\nprovisions them and verifies everything is working using the ``django-watchman``\nend-point which reports the status of the database, storage and cache backends.\n\n..  code-block:: shell\n\n    molecule test\n\nMolecule runs through a series of steps (playbooks) for the life-cycle of a test.\nYou can execute these steps individually when testing whether a role is working:\n\n..  code-block:: shell\n\n    molecule create\n    molecule converge\n    molecule verify\n\nThe ``create`` step leaves the containers running so you can run ``converge``\nstep multiple times as you make adjustments to your roles to check that the\ndeployment is working. ``verify`` then calls the end-point and compares the\njson data returned to confirm the backend are ok. Once you are finished you\ncan shut everything down and delete the containers using:\n\n..  code-block:: shell\n\n    molecule destroy\n\nThe setup for the molecule tests in ``molecule/default/create.yml`` uses a\nmount point to map the ssh-agent socket to ``/ssh-agent`` in the container,\nand sets the ``SSH_AUTH_SOCK`` environment variable to the location. You\ncan then add your github private key to your keychain using ``ssh-add`` to\ncheck out code from a private repository.\n\n.. _issues: https://github.com/StuartMacKay/django-project-templates/issues\n\nAcknowledgements\n----------------\nThis playbook is based on the extremely useful `ansible-django-stack`_\nwhich has been used extensively across many personal projects.\n\n.. _ansible-django-stack: https://github.com/jcalazan/ansible-django-stack\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartmackay%2Fdjango-ansible-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstuartmackay%2Fdjango-ansible-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartmackay%2Fdjango-ansible-template/lists"}