mirror of
https://github.com/wger-project/wger.git
synced 2026-02-18 00:17:51 +01:00
Our react components' main.js could not be added in the compression, so sometimes users would get outdated files served. The LenientManifestStaticFilesStorage now makes sure that the static files get a hash in the filename. Django compressor was removed since most of the js and css files are already minified and modern http versions can handle files better.
279 lines
9.8 KiB
Python
279 lines
9.8 KiB
Python
# This file is part of wger Workout Manager.
|
|
#
|
|
# wger Workout Manager is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# wger Workout Manager is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
# ruff: noqa: F405
|
|
|
|
# Third Party
|
|
import environ
|
|
|
|
# wger
|
|
from .settings_global import * # noqa: F403
|
|
|
|
"""
|
|
Main settings file for a production deployment of wger.
|
|
|
|
For a more commented version of the options used here, please refer to
|
|
https://github.com/wger-project/docker/blob/master/config/prod.env
|
|
"""
|
|
|
|
env = environ.Env(
|
|
# set casting, default value
|
|
DJANGO_DEBUG=(bool, False)
|
|
)
|
|
|
|
# Use 'DEBUG = True' to get more details for server errors
|
|
DEBUG = env('DJANGO_DEBUG')
|
|
|
|
if os.environ.get('DJANGO_ADMINS'):
|
|
ADMINS = [
|
|
env.tuple('DJANGO_ADMINS'),
|
|
]
|
|
MANAGERS = ADMINS
|
|
|
|
if os.environ.get('DJANGO_DB_ENGINE'):
|
|
DATABASES = {
|
|
'default': {
|
|
'ENGINE': env.str('DJANGO_DB_ENGINE'),
|
|
'NAME': env.str('DJANGO_DB_DATABASE'),
|
|
'USER': env.str('DJANGO_DB_USER'),
|
|
'PASSWORD': env.str('DJANGO_DB_PASSWORD'),
|
|
'HOST': env.str('DJANGO_DB_HOST'),
|
|
'PORT': env.int('DJANGO_DB_PORT'),
|
|
}
|
|
}
|
|
else:
|
|
DATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.sqlite3',
|
|
'NAME': env.str('DJANGO_DB_DATABASE', '/home/wger/db/database.sqlite'),
|
|
}
|
|
}
|
|
|
|
# Timezone for this installation. Consult settings_global.py for more information
|
|
TIME_ZONE = env.str('TIME_ZONE', 'Europe/Berlin')
|
|
|
|
# Make this unique, and don't share it with anybody.
|
|
# Generate e.g. with: python -c "import secrets; print(secrets.token_urlsafe(50))" or https://djecrety.ir/
|
|
SECRET_KEY = env.str('SECRET_KEY', 'wger-docker-supersecret-key-1234567890!@#$%^&*(-_)')
|
|
|
|
# Your reCaptcha keys
|
|
RECAPTCHA_PUBLIC_KEY = env.str('RECAPTCHA_PUBLIC_KEY', '')
|
|
RECAPTCHA_PRIVATE_KEY = env.str('RECAPTCHA_PRIVATE_KEY', '')
|
|
|
|
# The site's URL (e.g. http://www.my-local-gym.com or http://localhost:8000)
|
|
# This is needed for uploaded files and images (exercise images, etc.) to be
|
|
# properly served.
|
|
SITE_URL = env.str('SITE_URL', 'http://localhost:8000')
|
|
|
|
# Path to uploaded files
|
|
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
|
MEDIA_ROOT = env.str('DJANGO_MEDIA_ROOT', '/home/wger/media')
|
|
STATIC_ROOT = env.str('DJANGO_STATIC_ROOT', '/home/wger/static')
|
|
|
|
# If you change these, adjust nginx alias definitions as well
|
|
MEDIA_URL = env.str('MEDIA_URL', '/media/')
|
|
STATIC_URL = env.str('STATIC_URL', '/static/')
|
|
|
|
LOGIN_REDIRECT_URL = env.str('LOGIN_REDIRECT_URL', '/')
|
|
|
|
# Allow all hosts to access the application. Change if used in production.
|
|
ALLOWED_HOSTS = [
|
|
'*',
|
|
]
|
|
|
|
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
|
|
|
|
# Configure a real backend in production
|
|
if DEBUG:
|
|
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
|
|
|
if env.bool('ENABLE_EMAIL', False):
|
|
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
|
|
EMAIL_HOST = env.str('EMAIL_HOST')
|
|
EMAIL_PORT = env.int('EMAIL_PORT')
|
|
EMAIL_HOST_USER = env.str('EMAIL_HOST_USER')
|
|
EMAIL_HOST_PASSWORD = env.str('EMAIL_HOST_PASSWORD')
|
|
EMAIL_USE_TLS = env.bool('EMAIL_USE_TLS', True)
|
|
EMAIL_USE_SSL = env.bool('EMAIL_USE_SSL', False)
|
|
EMAIL_TIMEOUT = 60
|
|
|
|
# Sender address used for sent emails
|
|
DEFAULT_FROM_EMAIL = env.str('FROM_EMAIL', 'wger Workout Manager <wger@example.com>')
|
|
WGER_SETTINGS['EMAIL_FROM'] = DEFAULT_FROM_EMAIL
|
|
SERVER_EMAIL = DEFAULT_FROM_EMAIL
|
|
EMAIL_FROM_ADDRESS = DEFAULT_FROM_EMAIL
|
|
|
|
# Management
|
|
WGER_SETTINGS['ALLOW_GUEST_USERS'] = env.bool('ALLOW_GUEST_USERS', True)
|
|
WGER_SETTINGS['ALLOW_REGISTRATION'] = env.bool('ALLOW_REGISTRATION', True)
|
|
WGER_SETTINGS['ALLOW_UPLOAD_VIDEOS'] = env.bool('ALLOW_UPLOAD_VIDEOS', True)
|
|
WGER_SETTINGS['DOWNLOAD_INGREDIENTS_FROM'] = env.str('DOWNLOAD_INGREDIENTS_FROM', 'WGER')
|
|
WGER_SETTINGS['EXERCISE_CACHE_TTL'] = env.int('EXERCISE_CACHE_TTL', 3600)
|
|
WGER_SETTINGS['MIN_ACCOUNT_AGE_TO_TRUST'] = env.int('MIN_ACCOUNT_AGE_TO_TRUST', 21) # in days
|
|
WGER_SETTINGS['SYNC_EXERCISES_CELERY'] = env.bool('SYNC_EXERCISES_CELERY', False)
|
|
WGER_SETTINGS['SYNC_EXERCISE_IMAGES_CELERY'] = env.bool('SYNC_EXERCISE_IMAGES_CELERY', False)
|
|
WGER_SETTINGS['SYNC_EXERCISE_VIDEOS_CELERY'] = env.bool('SYNC_EXERCISE_VIDEOS_CELERY', False)
|
|
WGER_SETTINGS['SYNC_INGREDIENTS_CELERY'] = env.bool('SYNC_INGREDIENTS_CELERY', False)
|
|
WGER_SETTINGS['SYNC_OFF_DAILY_DELTA_CELERY'] = env.bool('SYNC_OFF_DAILY_DELTA_CELERY', False)
|
|
WGER_SETTINGS['USE_RECAPTCHA'] = env.bool('USE_RECAPTCHA', False)
|
|
WGER_SETTINGS['USE_CELERY'] = env.bool('USE_CELERY', False)
|
|
WGER_SETTINGS['CACHE_API_EXERCISES_CELERY'] = env.bool('CACHE_API_EXERCISES_CELERY', False)
|
|
WGER_SETTINGS['CACHE_API_EXERCISES_CELERY_FORCE_UPDATE'] = env.bool(
|
|
'CACHE_API_EXERCISES_CELERY_FORCE_UPDATE', False
|
|
)
|
|
|
|
#
|
|
# Auth Proxy Authentication
|
|
# https://wger.readthedocs.io/en/latest/administration/auth_proxy.html
|
|
AUTH_PROXY_HEADER = env.str('AUTH_PROXY_HEADER', '')
|
|
AUTH_PROXY_TRUSTED_IPS = env.list('AUTH_PROXY_TRUSTED_IPS', default=[])
|
|
AUTH_PROXY_CREATE_UNKNOWN_USER = env.bool('AUTH_PROXY_CREATE_UNKNOWN_USER', False)
|
|
AUTH_PROXY_USER_EMAIL_HEADER = env.str('AUTH_PROXY_USER_EMAIL_HEADER', '')
|
|
AUTH_PROXY_USER_NAME_HEADER = env.str('AUTH_PROXY_USER_NAME_HEADER', '')
|
|
|
|
# Cache
|
|
if os.environ.get('DJANGO_CACHE_BACKEND'):
|
|
CACHES = {
|
|
'default': {
|
|
'BACKEND': env.str('DJANGO_CACHE_BACKEND'),
|
|
'LOCATION': env.str('DJANGO_CACHE_LOCATION', ''),
|
|
'TIMEOUT': env.int('DJANGO_CACHE_TIMEOUT', 300),
|
|
'OPTIONS': {'CLIENT_CLASS': env.str('DJANGO_CACHE_CLIENT_CLASS', '')},
|
|
}
|
|
}
|
|
|
|
if os.environ.get('DJANGO_CACHE_CLIENT_PASSWORD'):
|
|
CACHES['default']['OPTIONS']['PASSWORD'] = env.str('DJANGO_CACHE_CLIENT_PASSWORD')
|
|
|
|
CONNECTION_POOL_KWARGS = dict()
|
|
if 'DJANGO_CACHE_CLIENT_SSL_KEYFILE' in os.environ:
|
|
CONNECTION_POOL_KWARGS['ssl_keyfile'] = env.str('DJANGO_CACHE_CLIENT_SSL_KEYFILE')
|
|
|
|
if 'DJANGO_CACHE_CLIENT_SSL_CERTFILE' in os.environ:
|
|
CONNECTION_POOL_KWARGS['ssl_certfile'] = env.str('DJANGO_CACHE_CLIENT_SSL_CERTFILE')
|
|
|
|
if 'DJANGO_CACHE_CLIENT_SSL_CERT_REQS' in os.environ:
|
|
CONNECTION_POOL_KWARGS['ssl_cert_reqs'] = env.str('DJANGO_CACHE_CLIENT_SSL_CERT_REQS')
|
|
|
|
if 'DJANGO_CACHE_CLIENT_SSL_CHECK_HOSTNAME' in os.environ:
|
|
CONNECTION_POOL_KWARGS['ssl_check_hostname'] = env.bool(
|
|
'DJANGO_CACHE_CLIENT_SSL_CHECK_HOSTNAME'
|
|
)
|
|
|
|
if CONNECTION_POOL_KWARGS:
|
|
CACHES['default']['OPTIONS']['CONNECTION_POOL_KWARGS'] = CONNECTION_POOL_KWARGS
|
|
|
|
#
|
|
# Django Compressor
|
|
# Consult https://django-compressor.readthedocs.io/en/stable/ for more information
|
|
# (specially the offline compression part)
|
|
#
|
|
COMPRESS_ROOT = STATIC_ROOT
|
|
COMPRESS_ENABLED = env.bool('COMPRESS_ENABLED', not DEBUG)
|
|
COMPRESS_OFFLINE = env.bool('COMPRESS_OFFLINE', False)
|
|
|
|
# The site's domain as used by the email verification workflow
|
|
EMAIL_PAGE_DOMAIN = SITE_URL
|
|
|
|
#
|
|
# Django Axes
|
|
#
|
|
AXES_ENABLED = env.bool('AXES_ENABLED', True)
|
|
AXES_LOCKOUT_PARAMETERS = env.list('AXES_LOCKOUT_PARAMETERS', default=['ip_address'])
|
|
AXES_FAILURE_LIMIT = env.int('AXES_FAILURE_LIMIT', 10)
|
|
AXES_COOLOFF_TIME = timedelta(minutes=env.float('AXES_COOLOFF_TIME', 30))
|
|
AXES_HANDLER = env.str('AXES_HANDLER', 'axes.handlers.cache.AxesCacheHandler')
|
|
AXES_IPWARE_PROXY_COUNT = env.int('AXES_IPWARE_PROXY_COUNT', 0)
|
|
AXES_IPWARE_META_PRECEDENCE_ORDER = env.list(
|
|
'AXES_IPWARE_META_PRECEDENCE_ORDER', default=['REMOTE_ADDR']
|
|
)
|
|
|
|
#
|
|
# Django Rest Framework SimpleJWT
|
|
#
|
|
SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'] = timedelta(minutes=env.int('ACCESS_TOKEN_LIFETIME', 15))
|
|
SIMPLE_JWT['REFRESH_TOKEN_LIFETIME'] = timedelta(hours=env.int('REFRESH_TOKEN_LIFETIME', 24))
|
|
SIMPLE_JWT['SIGNING_KEY'] = env.str('SIGNING_KEY', SECRET_KEY)
|
|
|
|
#
|
|
# https://docs.djangoproject.com/en/4.1/ref/csrf/
|
|
#
|
|
CSRF_TRUSTED_ORIGINS = env.list(
|
|
'CSRF_TRUSTED_ORIGINS',
|
|
default=['http://127.0.0.1', 'http://localhost', 'https://localhost'],
|
|
)
|
|
|
|
if env.bool('X_FORWARDED_PROTO_HEADER_SET', False):
|
|
SECURE_PROXY_SSL_HEADER = (
|
|
env.str('SECURE_PROXY_SSL_HEADER', 'HTTP_X_FORWARDED_PROTO'),
|
|
'https',
|
|
)
|
|
|
|
REST_FRAMEWORK['NUM_PROXIES'] = env.int('NUMBER_OF_PROXIES', 1)
|
|
|
|
#
|
|
# Celery message queue configuration
|
|
#
|
|
CELERY_BROKER_URL = env.str('CELERY_BROKER', 'redis://cache:6379/2')
|
|
CELERY_RESULT_BACKEND = env.str('CELERY_BACKEND', 'redis://cache:6379/2')
|
|
|
|
#
|
|
# Prometheus metrics
|
|
#
|
|
EXPOSE_PROMETHEUS_METRICS = env.bool('EXPOSE_PROMETHEUS_METRICS', False)
|
|
PROMETHEUS_URL_PATH = env.str('PROMETHEUS_URL_PATH', 'super-secret-path')
|
|
|
|
#
|
|
# Logging
|
|
#
|
|
LOGGING = {
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'formatters': {
|
|
'simple': {
|
|
'format': 'level={levelname} ts={asctime} module={module} path={pathname} line={lineno} message={message}',
|
|
'style': '{',
|
|
},
|
|
},
|
|
'handlers': {
|
|
'console': {'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple'},
|
|
},
|
|
'loggers': {
|
|
'': {
|
|
'handlers': ['console'],
|
|
'level': env.str('LOG_LEVEL_PYTHON', 'INFO').upper(),
|
|
'propagate': True,
|
|
},
|
|
},
|
|
}
|
|
|
|
#
|
|
# Storage options
|
|
#
|
|
STORAGES = {
|
|
'default': {
|
|
'BACKEND': env.str(
|
|
'DJANGO_STORAGES_DEFAULT_BACKEND',
|
|
'django.core.files.storage.FileSystemStorage'
|
|
),
|
|
},
|
|
# django.contrib.staticfiles.storage.StaticFilesStorage
|
|
'staticfiles': {
|
|
'BACKEND': env.str(
|
|
'DJANGO_STORAGES_STATICFILES_BACKEND',
|
|
'wger.core.storage.LenientManifestStaticFilesStorage'
|
|
),
|
|
},
|
|
}
|