diff options
author | 2019-01-20 09:52:57 +0100 | |
---|---|---|
committer | 2019-01-20 09:52:57 +0100 | |
commit | bdc337d70a386cae954399e55bb128119f601128 (patch) | |
tree | f1b90e9a2c028478e1b82325704ffdd943c4b3b6 /docs | |
parent | Merge branch 'django' into django+add-logs-api. (diff) | |
parent | Add an example `docker-compose.yml`. (diff) |
Merge branch 'django' into django+add-logs-api
Diffstat (limited to 'docs')
-rw-r--r-- | docs/configuration.md | 25 | ||||
-rw-r--r-- | docs/deployment.md | 147 |
2 files changed, 172 insertions, 0 deletions
diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 00000000..037f029f --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,25 @@ +# Configuration +The website is configured through the following environment variables: + +## Essential +- **`DATABASE_URL`**: A string specifying the PostgreSQL database to connect to, + in the form `postgresql://user:password@host/database`, such as + `postgresql://joethedestroyer:ihavemnesia33@localhost/pysite_dev` + +- **`DEBUG`**: Controls Django's internal debugging setup. Enable this when + you're developing locally. Optional, defaults to `False`. + +- **`LOG_LEVEL`**: Any valid Python `logging` module log level - one of `DEBUG`, + `INFO`, `WARN`, `ERROR` or `CRITICAL`. When using debug mode, this defaults to + `INFO`. When testing, defaults to `ERROR`. Otherwise, defaults to `WARN`. + +## Deployment +- **`ALLOWED_HOSTS`**: A comma-separated lists of alternative hosts to allow to + host the website on, when `DEBUG` is not set. Optional, defaults to the + `pythondiscord.com` family of domains. + +- **`SECRET_KEY`**: The secret key used in various parts of Django. Keep this + secret as the name suggests! This is managed for you in debug setups. + +- **`STATIC_ROOT`**: The root in which `python manage.py collectstatic` collects + static files. Optional, defaults to `/var/www/pythondiscord.com`. diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 00000000..841e08c7 --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,147 @@ +# Deployment +The default Dockerfile should do a good job at running a solid web server that +automatically adjusts its worker count based on traffic. This is managed by +uWSGI. You need to configure the `DATABASE_URL` and `SECRET_KEY` variables. If +you want to deploy to a different host than the default, configure the +`ALLOWED_HOSTS` variable. + +## Static file hosting +You can either collect the static files in the container and use uWSGI to host +them, or put them on your host and manage them through a web server running on +the host like nginx. + +## Database migrations +To bring the schema up-to-date, first stop an existing database container, then +start a container that just runs the migrations and exits, and then starts the +main container off the new container again. + +## Ansible task +An example Ansible task to deploy the site is shown below, it should read fairly +humanly and give you a rough idea of steps needed to deploy the site. + +```yml +--- +- name: ensure the `{{ pysite_pg_username }}` postgres user exists + become: yes + become_user: postgres + postgresql_user: + name: "{{ pysite_pg_username }}" + password: "{{ pysite_pg_password }}" + when: pysite_pg_host == 'localhost' + +- name: ensure the `{{ pysite_pg_database }}` postgres database exists + become: yes + become_user: postgres + postgresql_db: + name: "{{ pysite_pg_database }}" + owner: "{{ pysite_pg_username }}" + when: pysite_pg_host == 'localhost' + +- name: ensure the `{{ pysite_hub_repository }}` image is up-to-date + become: yes + docker_image: + name: "{{ pysite_hub_repository }}" + force: yes + +- name: ensure the nginx HTTP vhosts are up-to-date + become: yes + template: + src: "nginx/{{ item.key }}.http.conf.j2" + dest: "/etc/nginx/sites-available/{{ item.value }}.http.conf" + with_dict: "{{ pysite_domains }}" + notify: reload nginx + +- name: ensure the nginx HTTPS vhosts are up-to-date + become: yes + template: + src: "nginx/{{ item.key }}.https.conf.j2" + dest: "/etc/nginx/sites-available/{{ item.value }}.https.conf" + with_dict: "{{ pysite_domains }}" + notify: reload nginx + +- name: ensure the nginx HTTP vhosts are symlinked to `/etc/nginx/sites-enabled` + become: yes + file: + src: /etc/nginx/sites-available/{{ item.value }}.http.conf + dest: /etc/nginx/sites-enabled/{{ item.value }}.http.conf + state: link + with_dict: "{{ pysite_domains }}" + notify: reload nginx + +- name: ensure we have HTTPS certificates + include_role: + name: thefinn93.letsencrypt + vars: + letsencrypt_cert_domains: "{{ pysite_domains | dict2items | map(attribute='value') | list }}" + letsencrypt_email: "[email protected]" + letsencrypt_renewal_command_args: '--renew-hook "systemctl restart nginx"' + letsencrypt_webroot_path: /var/www/_letsencrypt + +- name: ensure the nginx HTTPS vhosts are symlinked to `/etc/nginx/sites-enabled` + become: yes + file: + src: /etc/nginx/sites-available/{{ item.value }}.https.conf + dest: /etc/nginx/sites-enabled/{{ item.value }}.https.conf + state: link + with_dict: "{{ pysite_domains }}" + notify: reload nginx + +- name: ensure the web container is absent + become: yes + docker_container: + name: pysite + state: absent + +- name: ensure the `{{ pysite_static_file_dir }}` directory exists + become: yes + file: + path: "{{ pysite_static_file_dir }}" + state: directory + owner: root + group: root + +- name: collect static files + become: yes + docker_container: + image: "{{ pysite_hub_repository }}" + name: pysite-static-file-writer + command: python manage.py collectstatic --noinput + detach: no + cleanup: yes + network_mode: host + env: + DATABASE_URL: "{{ pysite_pg_database_url }}" + SECRET_KEY: "me-dont-need-no-secret-key" + STATIC_ROOT: "/html" + volumes: + - "/var/www/pythondiscord.com:/html" + +- name: ensure the database schema is up-to-date + become: yes + docker_container: + image: "{{ pysite_hub_repository }}" + name: pysite-migrator + detach: no + cleanup: yes + command: python manage.py migrate + network_mode: host + env: + DATABASE_URL: "postgres://{{ pysite_pg_username }}:{{ pysite_pg_password }}@{{ pysite_pg_host }}/{{ pysite_pg_database }}" + SECRET_KEY: "me-dont-need-no-secret-key" + +- name: ensure the website container is started + become: yes + docker_container: + image: "{{ pysite_hub_repository }}" + name: pysite + network_mode: host + restart: yes + restart_policy: unless-stopped + ports: + - "127.0.0.1:4000:4000" + env: + ALLOWED_HOSTS: "{{ pysite_domains | dict2items | map(attribute='value') | join(',') }}" + DATABASE_URL: "postgres://{{ pysite_pg_username }}:{{ pysite_pg_password }}@{{ pysite_pg_host }}/{{ pysite_pg_database }}" + PARENT_HOST: pysite.example.com + SECRET_KEY: "{{ pysite_secret_key }}" +``` |