diff --git a/CHANGELOG.md b/CHANGELOG.md index 3780e187..06e7bf0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Add admin action to log in as any user - Add a "Manager" role (#484) - Add support for 2FA using TOTP (#354) +- Add Whitenoise (#548) ### Bug Fixes - Fix dark mode styling issues in Cron Syntax Cheatsheet diff --git a/README.md b/README.md index 23624333..a08836cd 100644 --- a/README.md +++ b/README.md @@ -387,30 +387,36 @@ Here is a non-exhaustive list of pointers and things to check before launching a in production. * Environment variables, settings.py and local_settings.py. - * [DEBUG](https://docs.djangoproject.com/en/2.2/ref/settings/#debug). Make sure it is set to `False`. - * [ALLOWED_HOSTS](https://docs.djangoproject.com/en/2.2/ref/settings/#allowed-hosts). Make sure it - contains the correct domain name you want to use. - * Server Errors. When DEBUG=False, Django will not show detailed error pages, and will not print exception - tracebacks to standard output. To receive exception tracebacks in email, - review and edit the [ADMINS](https://docs.djangoproject.com/en/2.2/ref/settings/#admins) and - [SERVER_EMAIL](https://docs.djangoproject.com/en/2.2/ref/settings/#server-email) settings. - Another good option for receiving exception tracebacks is to use [Sentry](https://sentry.io/for/django/). + * [DEBUG](https://docs.djangoproject.com/en/2.2/ref/settings/#debug). Make sure it is + set to `False`. + * [ALLOWED_HOSTS](https://docs.djangoproject.com/en/2.2/ref/settings/#allowed-hosts). + Make sure it contains the correct domain name you want to use. + * Server Errors. When DEBUG=False, Django will not show detailed error pages, and + will not print exception tracebacks to standard output. To receive exception + tracebacks in email, review and edit the + [ADMINS](https://docs.djangoproject.com/en/2.2/ref/settings/#admins) and + [SERVER_EMAIL](https://docs.djangoproject.com/en/2.2/ref/settings/#server-email) + settings. Consider setting up exception logging with [Sentry](https://sentry.io/for/django/). * Management commands that need to be run during each deployment. - * This project uses [Django Compressor](https://django-compressor.readthedocs.io/en/stable/) - to combine the CSS and JS files. It is configured for offline compression – run the - `manage.py compress` command whenever files in the `/static/` directory change. - * This project uses Django's [staticfiles app](https://docs.djangoproject.com/en/2.2/ref/contrib/staticfiles/). - Run the `manage.py collectstatic` command whenever files in the `/static/` - directory change. This command collects all the static files inside the `static-collected` directory. - Configure your web server to serve files from this directory under the `/static/` prefix. - * Database migration should be run after each update to make sure the database schemas are up to date. You can do that with `./manage.py migrate`. + * `manage.py compress` – creates combined JS and CSS bundles and + places them in the `static-collected` directory. + * `manage.py collectstatic` – collects static files in the `static-collected` + directory. + * `manage.py migrate` – applies any pending database schema changes + and data migrations. * Processes that need to be running constantly. - * `manage.py runserver` is intended for development only. Do not use it in production, - instead consider using [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) or - [gunicorn](https://gunicorn.org/). - * Make sure the `manage.py sendalerts` command is running and can survive server restarts. - On modern linux systems, a good option is to - [define a systemd service](https://github.com/healthchecks/healthchecks/issues/273#issuecomment-520560304) for it. + * `manage.py runserver` is intended for development only. + **Do not use it in production**, instead consider using + [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) or + [gunicorn](https://gunicorn.org/). + * `manage.py sendalerts` is the process that monitors checks and sends out + monitoring alerts. It must be always running, it must be started on reboot, and it + must be restarted if it itself crashes. On modern linux systems, a good option is + to [define a systemd service](https://github.com/healthchecks/healthchecks/issues/273#issuecomment-520560304) + for it. +* Static files. Healthchecks serves static files on its own, no configuration + required. It uses the [Whitenoise library](http://whitenoise.evans.io/en/stable/index.html) + for this. * General * Make sure the database is secured well and is getting backed up regularly * Make sure the TLS certificates are secured well and are getting refreshed regularly diff --git a/docker/uwsgi.ini b/docker/uwsgi.ini index 30168e54..05761ddb 100644 --- a/docker/uwsgi.ini +++ b/docker/uwsgi.ini @@ -11,7 +11,6 @@ chdir = /opt/healthchecks module = hc.wsgi:application thunder-lock disable-write-exception -static-map = /static=/opt/healthchecks/static-collected hook-pre-app = exec:./manage.py migrate attach-daemon = ./manage.py sendalerts diff --git a/hc/settings.py b/hc/settings.py index af0d0a59..3373651f 100644 --- a/hc/settings.py +++ b/hc/settings.py @@ -60,6 +60,7 @@ INSTALLED_APPS = ( MIDDLEWARE = ( "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -171,6 +172,13 @@ STATICFILES_FINDERS = ( COMPRESS_OFFLINE = True COMPRESS_CSS_HASHING_METHOD = "content" + +def immutable_file_test(path, url): + return url.startswith("/static/CACHE/") or url.startswith("/static/fonts/") + + +WHITENOISE_IMMUTABLE_FILE_TEST = immutable_file_test + # SMTP credentials for sending email EMAIL_HOST = os.getenv("EMAIL_HOST", "") EMAIL_PORT = envint("EMAIL_PORT", "587") diff --git a/requirements.txt b/requirements.txt index 92a2800f..fc14b4c8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ pytz==2021.1 requests==2.26.0 segno==1.3.3 statsd==3.3.0 +whitenoise==5.3.0 \ No newline at end of file