This project structure is in active development and continuously evolves. It utilizes:
- The batteries-included super-fast template Jinja2.
- The wrapper around it (to make our lives easier) django-jinja.
- The command-like tool Invoke.
- The IT automation tool Ansible.
- The CLI command for expoiting DigitalOcean API beauty-ocean.
- Requests to make our lives easier.
- The package management tool, pipenv. A
Pipfileis already included with sane defaults. - PyYAML to parse
yamlfiles.
Before run pipenv install --dev, have a look in the file and add/remove (Django) packages according to your needs.
This Django skeleton tries to handle the most boilerplate for you (me) in order to facilitate the deployment procedure. When we say deployment, we mean DigitalOcean. I do not work for them, nor I get paid by them. I just love their services, VPS pricing plans and UX. That's all. I have tried Linode too, but no luck there. That's just personal preference.
Before running the usual command django-admin startproject project_name (in order to create your brand new Django project),
try running the following command instead:
django-admin startproject --template https://github.com/manikos/cc_do/archive/master.zip --extension py,json,html --name constants.yml,gitignore project_name
When the command completes, you'll have a project structure which is (almost) deployment ready. Read below for more information.
(HINT): Create a virtualenv (i.e django_env) which will be used only for Django-specific commands (like django-admin) and install django inside it: $ mkvirtualenv -p $(which python3.6) django_env.
(HINT): Maybe take a look at pyenv).
- Ensure that you have
pipenvinstalled to your machine. If not, install it:$ pip install --user pipenv(never use sudo) - Activate the previously created
django_env:$ workon django_envand$ cd path/to/projects/dir - Create the project skeleton
(django_env)$ django-admin startproject --template https://github.com/manikos/cc_do/archive/master.zip --extension py,json,html --name constants.yml,gitignore project_name - Deactivate
django_env(job's done):(django_env)$ deactivate - Take a look at the
Pipfileand remove any dependencies according to your needs. - Install dependencies (including dev-packages)
$ cd /path/to/project/ && pipenv install --dev. - Activate the virtualenv in order not to do
pipenv run <command>and instead do<command>,$ pipenv shell. (project-<hash>)$ cd path/to/automation/dev && inv --list, it will list all available (dev) commands to create a BitBucket private repo and/or a PostgreSQL local database.
Take a look at automation/dev/tasks.py for some useful commands to get you started. Also, take a look at the TODO: sections spread accross the skeleton
and tweak values according to your needs.
-
Ensure that you have looked the values to be changed at
automation/prod/group_vars/all/constants.yml. -
Ensure that you have provided a
automation/prod/group_vars/all/vault.ymlfile which is encrypted using ansible-vault command.- This file is a
ymlfile. - Must contain the below keys:
Keys Description user_groupuser's group (usually same as user_name)user_nameuser's username user_salta random string of up to 8 characters [a-zA-Z0-9./] user_pwduser's password (used for sudocommands)user_commentuser's full name (optional) bb_useryour bitbucket username bb_pwdyour bitbucket password db_userproduction postgres database user (usually the same a user_name)db_pwdproduction postgres database password For example, a
vault.ymlfile could look like this:--- user_group: mike user_name: mike user_salt: aThko86z user_pwd: mikeSudoPassword user_comment: Mike Michael bb_user: mike bb_pwd: mikeBitBucketPwd db_user: mike db_pwd: mikePostgresPwd- Usually, you want the same values for every project you deploy, in order not to get lost when you must
sshin the server. So, create thisvault.ymlfile once and then forget about it. Just don't forget the password in case you have to edit/viewvault.yml!
- This file is a
-
To deploy the project on DigitalOcean
(venv)$ cd path/to/project/automation/prod && inv deploy. Done!
The produced project structure looks like this:
.
├── dtl_utils
│ ├── apps.py
│ ├── __init__.py
│ └── templatetags
│ ├── dtl_tags.py
│ └── __init__.py
├── gitignore
├── logs
│ ├── db.log
│ ├── dev.log
│ ├── my_apps.log
│ └── production.log
├── manage.py
├── media_root
│ └── README.md
├── Pipfile
├── project_name
│ ├── automation
│ │ ├── dev
│ │ │ └── tasks.py
│ │ └── prod
│ │ ├── ansible.cfg
│ │ ├── deploy_root.yml
│ │ ├── deploy_user.yml
│ │ ├── filter_plugins
│ │ │ └── db_filters.py
│ │ ├── group_vars
│ │ │ └── all
│ │ │ └── constants.yml
│ │ ├── hosts
│ │ ├── README.md
│ │ ├── roles
│ │ │ ├── manikos.app
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.birth
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.bitbucket
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.common
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ │ └── vimrc
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ │ └── bash_aliases.j2
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.django
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.fail2ban
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ │ └── jail.local.j2
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.nginx
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ │ ├── nginx.conf.j2
│ │ │ │ │ └── nginx_sites_avail.j2
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.pipenv
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.postgres
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.pyenv
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ │ └── pyenvrc.j2
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ ├── manikos.ufw
│ │ │ │ ├── defaults
│ │ │ │ │ └── main.yml
│ │ │ │ ├── files
│ │ │ │ ├── handlers
│ │ │ │ │ └── main.yml
│ │ │ │ ├── meta
│ │ │ │ │ └── main.yml
│ │ │ │ ├── README.md
│ │ │ │ ├── tasks
│ │ │ │ │ └── main.yml
│ │ │ │ ├── templates
│ │ │ │ ├── tests
│ │ │ │ │ ├── inventory
│ │ │ │ │ └── test.yml
│ │ │ │ └── vars
│ │ │ │ └── main.yml
│ │ │ └── manikos.uwsgi
│ │ │ ├── defaults
│ │ │ │ └── main.yml
│ │ │ ├── files
│ │ │ ├── handlers
│ │ │ │ └── main.yml
│ │ │ ├── meta
│ │ │ │ └── main.yml
│ │ │ ├── README.md
│ │ │ ├── tasks
│ │ │ │ └── main.yml
│ │ │ ├── templates
│ │ │ │ ├── uwsgi.ini.j2
│ │ │ │ └── uwsgi.service.j2
│ │ │ ├── tests
│ │ │ │ ├── inventory
│ │ │ │ └── test.yml
│ │ │ └── vars
│ │ │ └── main.yml
│ │ └── tasks.py
│ ├── __init__.py
│ ├── jinja2
│ │ ├── filters.py
│ │ ├── __init__.py
│ │ └── methods.py
│ ├── locale
│ │ └── el
│ │ └── LC_MESSAGES
│ │ └── README.md
│ ├── settings
│ │ ├── base.py
│ │ ├── __init__.py
│ │ ├── local.py
│ │ ├── prod.py
│ │ └── secret.json
│ ├── sitemap.py
│ ├── urls.py
│ └── wsgi.py
├── READ_ME
├── README.md
├── robots.txt
├── static
│ ├── css
│ │ └── style.css
│ ├── fonts
│ │ └── font.ttf
│ ├── img
│ │ ├── empty.png
│ │ └── favicons
│ │ └── favicon.ico
│ ├── js
│ │ ├── adminPreviewImage.js
│ │ └── main.js
│ └── src
│ └── various_original_files
├── static_root
│ └── README.md
└── templates
├── admin
│ ├── base_site.html
│ └── change_form.html
├── base
│ ├── base.html
│ └── index.html
└── sitemap
└── sitemap.xml
137 directories, 154 files
The next thing I like to build is a docker-ready fully functional website skeleton, batteries included.