From 25e43256ad0c9a11bece29c149b0c82a72f67755 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 24 Mar 2023 13:56:33 +0100 Subject: [PATCH 1/8] WIP --- .dockerignore | 154 +++++++++++++++++++++++++++++++++++++++++++ .envrc | 0 config/entrypoint.sh | 2 +- flake.lock | 40 +++++++++++ flake.nix | 23 +++++++ fly.toml | 39 +++++++++++ 6 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 fly.toml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..ddd84ed --- /dev/null +++ b/.dockerignore @@ -0,0 +1,154 @@ +# flyctl launch added from .gitignore +# Byte-compiled / optimized / DLL files +**/__pycache__ +**/*.py[cod] +**/*$py.class + +# C extensions +**/*.so + +# Distribution / packaging +**/.Python +**/build +**/develop-eggs +**/dist +**/downloads +**/eggs +**/.eggs +**/lib +**/lib64 +**/parts +**/sdist +**/var +**/wheels +**/pip-wheel-metadata +**/share/python-wheels +**/*.egg-info +**/.installed.cfg +**/*.egg +**/MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +**/*.manifest +**/*.spec + +# Installer logs +**/pip-log.txt +**/pip-delete-this-directory.txt + +# Unit test / coverage reports +**/htmlcov +**/.tox +**/.nox +**/.coverage +**/.coverage.* +**/.cache +**/nosetests.xml +**/coverage.xml +**/*.cover +**/*.py,cover +**/.hypothesis +**/.pytest_cache + +# Translations +**/*.pot + +# Django stuff: +**/*.log +**/local_settings.py +**/db.sqlite3 +**/db.sqlite3-journal + +# Flask stuff: +**/instance +**/.webassets-cache + +# Scrapy stuff: +**/.scrapy + +# Sphinx documentation +**/docs/_build + +# PyBuilder +**/target + +# Jupyter Notebook +**/.ipynb_checkpoints + +# IPython +**/profile_default +**/ipython_config.py + +# pyenv +**/.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +**/__pypackages__ + +# Celery stuff +**/celerybeat-schedule +**/celerybeat.pid + +# SageMath parsed files +**/*.sage.py + +# Environments +**/.venv +**/env +**/venv +**/ENV +**/env.bak +**/venv.bak + +# Spyder project settings +**/.spyderproject +**/.spyproject + +# Rope project settings +**/.ropeproject + +# mkdocs documentation +site + +# mypy +**/.mypy_cache +**/.dmypy.json +**/dmypy.json + +# Pyre type checker +**/.pyre + +# Pycharm +**/.idea + +# website files +**/website/*.sqlite3 +**/**/media/* +**/database +**/*.sqlite + +# secrets +**/config/secrets.env + +**/.vscode + +**/**/main.css + +# flyctl launch added from .idea/.gitignore +# Default ignored files +.idea/shelf +.idea/workspace.xml +# Datasource local storage ignored files +.idea/dataSources +.idea/dataSources.local.xml +# Editor-based HTTP Client requests +.idea/httpRequests diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..e69de29 diff --git a/config/entrypoint.sh b/config/entrypoint.sh index fa3ddda..0815a01 100755 --- a/config/entrypoint.sh +++ b/config/entrypoint.sh @@ -23,4 +23,4 @@ echo "Collecting static files" chown --recursive www-data:www-data /bf2-www/ echo "Starting server" -gunicorn --bind :8000 website.wsgi:application \ No newline at end of file +gunicorn --bind :8080 website.wsgi:application \ No newline at end of file diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..e16d13f --- /dev/null +++ b/flake.lock @@ -0,0 +1,40 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1679472241, + "narHash": "sha256-VK2YDic2NjPvfsuneJCLIrWS38qUfoW8rLLimx0rWXA=", + "path": "/nix/store/g8yl8wpnl0pvx021zgjcyij76k6jbb58-source", + "rev": "9ef6e7727f4c31507627815d4f8679c5841efb00", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index e69de29..971140d 100644 --- a/flake.nix +++ b/flake.nix @@ -0,0 +1,23 @@ +{ + description = "BF2 djangocms website"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + devShell = pkgs.mkShell { + nativeBuildInputs = [ pkgs.bashInteractive ]; + buildInputs = with pkgs; [ + python311 + gtranslator + poedit + poetry + flyctl + openssl + httpie + ]; + shellHook = "fish"; + }; + }); +} \ No newline at end of file diff --git a/fly.toml b/fly.toml new file mode 100644 index 0000000..ee888ee --- /dev/null +++ b/fly.toml @@ -0,0 +1,39 @@ +# fly.toml file generated for bf2-website on 2023-03-24T13:30:48+01:00 + +app = "bf2-website" +kill_signal = "SIGINT" +kill_timeout = 5 +processes = [] + +[env] +DOMAIN="bfrisbee2s.nl" +EMAIL_HOST_USER="support@bfrisbee2s.nl" + +[experimental] + auto_rollback = true + +[[services]] + http_checks = [] + internal_port = 8080 + processes = ["app"] + protocol = "tcp" + script_checks = [] + [services.concurrency] + hard_limit = 25 + soft_limit = 20 + type = "connections" + + [[services.ports]] + force_https = true + handlers = ["http"] + port = 80 + + [[services.ports]] + handlers = ["tls", "http"] + port = 443 + + [[services.tcp_checks]] + grace_period = "1s" + interval = "15s" + restart_limit = 0 + timeout = "2s" From e45848cb7b500a37efbb2bb0df0a999b7d0783eb Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 24 Mar 2023 15:09:38 +0100 Subject: [PATCH 2/8] Add whitenoise and fix security things --- poetry.lock | 17 ++++++++++++++++- pyproject.toml | 1 + website/website/settings/base.py | 8 +++++++- website/website/settings/production.py | 7 ++++--- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index 56da6dc..49b2c70 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1483,6 +1483,21 @@ files = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] +[[package]] +name = "whitenoise" +version = "6.4.0" +description = "Radically simplified static file serving for WSGI applications" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "whitenoise-6.4.0-py3-none-any.whl", hash = "sha256:599dc6ca57e48929dfeffb2e8e187879bfe2aed0d49ca419577005b7f2cc930b"}, + {file = "whitenoise-6.4.0.tar.gz", hash = "sha256:a02d6660ad161ff17e3042653c8e3f5ecbb2a2481a006bde125b9efb9a30113a"}, +] + +[package.extras] +brotli = ["Brotli"] + [[package]] name = "xlrd" version = "2.0.1" @@ -1518,4 +1533,4 @@ production = ["gunicorn", "psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "a0ab05ae15fed530c92b043d42cf86e730470bdbc23e8e313d861bade896c5f7" +content-hash = "ee4268218249a5f4178a82cab4fac5c436781755768e24f0e199169fc74138b8" diff --git a/pyproject.toml b/pyproject.toml index 0fae8ed..e33a827 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ libsass = "^0.22.0" ics = "^0.7.2" djangocms-4-migration = "^0.0.1" setuptools = "^67.6.0" +whitenoise = "^6.4.0" [tool.poetry.dev-dependencies] black = "^22.8.0" diff --git a/website/website/settings/base.py b/website/website/settings/base.py index 6204e6e..c6657f1 100644 --- a/website/website/settings/base.py +++ b/website/website/settings/base.py @@ -20,7 +20,7 @@ SITE_ID = 1 -X_FRAME_OPTIONS = "SAMEORIGIN" +X_FRAME_OPTIONS = "DENY" LOGIN_URL = "/user/login/" @@ -58,6 +58,7 @@ # Application definition INSTALLED_APPS = [ + "whitenoise.runserver_nostatic", "djangocms_admin_style", # Django "django.contrib.admin", @@ -101,6 +102,7 @@ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", @@ -115,6 +117,8 @@ "cms.middleware.utils.ApphookReloadMiddleware", ] +CSRF_COOKIE_SECURE=True + ROOT_URLCONF = "website.urls" TEMPLATES = [ @@ -171,6 +175,8 @@ "sass_processor.finders.CssFinder", ] +STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" + SASS_PRECISION = 8 # TODO remove when no longer needed in future update diff --git a/website/website/settings/production.py b/website/website/settings/production.py index 1a0a229..cca92ed 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -1,12 +1,10 @@ -import os - from website.settings.base import * # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = False ALLOWED_HOSTS = [".bfrisbee2s.nl", "bf2.luko.dev", "localhost"] @@ -17,6 +15,9 @@ ] SESSION_COOKIE_SECURE = True +SECURE_HSTS_SECONDS = True +SECURE_HSTS_INCLUDE_SUBDOMAINS = True +SECURE_HSTS_PRELOAD = True DATABASES = { "default": { From 6616c50a38fd7ad711ab7fede6f39a4faca81095 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Fri, 24 Mar 2023 16:35:31 +0100 Subject: [PATCH 3/8] Added support for fly, migrate later --- Dockerfile | 9 +++++---- config/entrypoint.sh | 7 ------- poetry.lock | 17 ++++++++++++++++- pyproject.toml | 1 + website/website/settings/base.py | 2 +- website/website/settings/production.py | 16 +++++++--------- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/Dockerfile b/Dockerfile index edc9c97..5f39182 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,13 +7,14 @@ ENV PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=off \ PIP_DISABLE_PIP_VERSION_CHECK=on \ PIP_DEFAULT_TIMEOUT=100 \ - POETRY_VERSION=1.1.3 \ + POETRY_VERSION=1.4.0 \ POETRY_VIRTUALENVS_IN_PROJECT=true \ - POETRY_NO_INTERACTION=1 + POETRY_NO_INTERACTION=1 \ + POETRY_HOME="/opt/poetry" # Use production settings ENV DJANGO_SETTINGS_MODULE website.settings.production # Add poetry to PATH -ENV PATH="/root/.poetry/bin:$PATH" +ENV PATH="$POETRY_HOME/bin:$PATH" RUN apt-get update \ && apt-get install --no-install-recommends -y \ @@ -25,7 +26,7 @@ RUN apt-get update \ postgresql-client # install poetry - respects $POETRY_VERSION & $POETRY_HOME -RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python +RUN curl -sSL https://install.python-poetry.org | python3 - WORKDIR /bf2-www diff --git a/config/entrypoint.sh b/config/entrypoint.sh index 0815a01..c1c7b22 100755 --- a/config/entrypoint.sh +++ b/config/entrypoint.sh @@ -2,13 +2,6 @@ set -e -echo "Waiting for postgres at host ${DATABASE_HOST}" -until pg_isready --host="${DATABASE_HOST}" --port="${DATABASE_PORT}" --username="${POSTGRES_USER}" --quiet; do - sleep 1; -done - -echo "Postgres database is up" - . .venv/bin/activate echo "Performing migrations" diff --git a/poetry.lock b/poetry.lock index 49b2c70..5c1c202 100644 --- a/poetry.lock +++ b/poetry.lock @@ -173,6 +173,21 @@ files = [ {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, ] +[[package]] +name = "dj-database-url" +version = "1.2.0" +description = "Use Database URLs in your Django Application." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "dj-database-url-1.2.0.tar.gz", hash = "sha256:b23b15046cb38180e0c95207bcc90fe5e9dbde8eef16065907dd85cf4ca7036c"}, + {file = "dj_database_url-1.2.0-py3-none-any.whl", hash = "sha256:5c2993b91801c0f78a8b19e642b497b90831124cbade0c265900d4c1037b4730"}, +] + +[package.dependencies] +Django = ">=3.2" + [[package]] name = "django" version = "4.1.7" @@ -1533,4 +1548,4 @@ production = ["gunicorn", "psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "ee4268218249a5f4178a82cab4fac5c436781755768e24f0e199169fc74138b8" +content-hash = "f37338780723d4d7ee51059c029160210b3d27b1ff828614d2fbfc449f5047ba" diff --git a/pyproject.toml b/pyproject.toml index e33a827..0090372 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,7 @@ ics = "^0.7.2" djangocms-4-migration = "^0.0.1" setuptools = "^67.6.0" whitenoise = "^6.4.0" +dj-database-url = "^1.2.0" [tool.poetry.dev-dependencies] black = "^22.8.0" diff --git a/website/website/settings/base.py b/website/website/settings/base.py index c6657f1..c452e95 100644 --- a/website/website/settings/base.py +++ b/website/website/settings/base.py @@ -31,7 +31,7 @@ # about 3 months ACCOUNT_ACTIVATION_TIMEOUT = 60 * 60 * 24 * 30 * 3 -CSRF_TRUSTED_ORIGINS = ["https://.bfrisbee2s.nl"] +CSRF_TRUSTED_ORIGINS = ["https://bf2-website.fly.dev", "https://.bfrisbee2s.nl"] CMS_PAGE_CACHE = False diff --git a/website/website/settings/production.py b/website/website/settings/production.py index cca92ed..a217609 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -1,3 +1,5 @@ +import dj_database_url + from website.settings.base import * # SECURITY WARNING: keep the secret key used in production secret! @@ -6,7 +8,7 @@ # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False -ALLOWED_HOSTS = [".bfrisbee2s.nl", "bf2.luko.dev", "localhost"] +ALLOWED_HOSTS = ["bf2-website.fly.dev", ".bfrisbee2s.nl", "bf2.luko.dev", "localhost"] CSRF_TRUSTED_ORIGINS = [ "https://bfrisbee2s.nl", @@ -20,14 +22,10 @@ SECURE_HSTS_PRELOAD = True DATABASES = { - "default": { - "ENGINE": "django.db.backends.postgresql", - "HOST": os.environ.get("DATABASE_HOST"), - "PORT": int(os.environ.get("DATABASE_PORT", 5432)), - "NAME": os.environ.get("POSTGRES_DB"), - "USER": os.environ.get("POSTGRES_USER"), - "PASSWORD": os.environ.get("POSTGRES_PASSWORD"), - } + 'default': dj_database_url.config( + conn_max_age=600, + conn_health_checks=True, + ), } DJANGOCMS_GOOGLEMAP_API_KEY = os.environ.get("GOOGLE_MAPS_KEY") From 8fc55914e82dba1a375cd9c3c056cd200e0ff980 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Sat, 25 Mar 2023 11:55:19 +0100 Subject: [PATCH 4/8] add fly domain to csrf domains --- website/website/settings/production.py | 1 + 1 file changed, 1 insertion(+) diff --git a/website/website/settings/production.py b/website/website/settings/production.py index a217609..52c6ccd 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -14,6 +14,7 @@ "https://bfrisbee2s.nl", "http://localhost", "https://bf2.luko.dev", + "https://bf2-website.fly.dev" ] SESSION_COOKIE_SECURE = True From 4ee6bbf0aa2f862a6393aaf334ea185da7b08bbf Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Sat, 25 Mar 2023 14:54:09 +0100 Subject: [PATCH 5/8] Working prometheus --- fly.toml | 8 +++++-- poetry.lock | 32 +++++++++++++++++++++++++- pyproject.toml | 1 + website/website/settings/production.py | 7 ++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/fly.toml b/fly.toml index ee888ee..0bc5327 100644 --- a/fly.toml +++ b/fly.toml @@ -5,6 +5,10 @@ kill_signal = "SIGINT" kill_timeout = 5 processes = [] +[metrics] +port = 9091 # default for most prometheus clients +path = "/metrics" # default for most prometheus clients + [env] DOMAIN="bfrisbee2s.nl" EMAIL_HOST_USER="support@bfrisbee2s.nl" @@ -33,7 +37,7 @@ EMAIL_HOST_USER="support@bfrisbee2s.nl" port = 443 [[services.tcp_checks]] - grace_period = "1s" + grace_period = "15s" interval = "15s" - restart_limit = 0 + restart_limit = 40 timeout = "2s" diff --git a/poetry.lock b/poetry.lock index 5c1c202..19dc073 100644 --- a/poetry.lock +++ b/poetry.lock @@ -428,6 +428,21 @@ files = [ [package.dependencies] Django = ">=2.1" +[[package]] +name = "django-prometheus" +version = "2.2.0" +description = "Django middlewares to monitor your application with Prometheus.io." +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "django-prometheus-2.2.0.tar.gz", hash = "sha256:240378a1307c408bd5fc85614a3a57f1ce633d4a222c9e291e2bbf325173b801"}, + {file = "django_prometheus-2.2.0-py2.py3-none-any.whl", hash = "sha256:e6616770d8820b8834762764bf1b76ec08e1b98e72a6f359d488a2e15fe3537c"}, +] + +[package.dependencies] +prometheus-client = ">=0.7" + [[package]] name = "django-sass-processor" version = "1.2.2" @@ -1054,6 +1069,21 @@ files = [ docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +[[package]] +name = "prometheus-client" +version = "0.16.0" +description = "Python client for the Prometheus monitoring system." +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "prometheus_client-0.16.0-py3-none-any.whl", hash = "sha256:0836af6eb2c8f4fed712b2f279f6c0a8bbab29f9f4aa15276b91c7cb0d1616ab"}, + {file = "prometheus_client-0.16.0.tar.gz", hash = "sha256:a03e35b359f14dd1630898543e2120addfdeacd1a6069c1367ae90fd93ad3f48"}, +] + +[package.extras] +twisted = ["twisted"] + [[package]] name = "psycopg2-binary" version = "2.9.5" @@ -1548,4 +1578,4 @@ production = ["gunicorn", "psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "f37338780723d4d7ee51059c029160210b3d27b1ff828614d2fbfc449f5047ba" +content-hash = "e445165e1f4080e507f0bc507a9ec40afd3b9986121b27047a931a9166bb1b92" diff --git a/pyproject.toml b/pyproject.toml index 0090372..e15c2f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ djangocms-4-migration = "^0.0.1" setuptools = "^67.6.0" whitenoise = "^6.4.0" dj-database-url = "^1.2.0" +django-prometheus = "^2.2.0" [tool.poetry.dev-dependencies] black = "^22.8.0" diff --git a/website/website/settings/production.py b/website/website/settings/production.py index 52c6ccd..367bdc5 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -48,3 +48,10 @@ MEDIA_ROOT = "/bf2-www/media" MEDIA_URL = "/media/" + +INSTALLED_APPS += ['django_prometheus'] +MIDDLEWARE.insert(0, 'django_prometheus.middleware.PrometheusBeforeMiddleware') +MIDDLEWARE.append('django_prometheus.middleware.PrometheusAfterMiddleware') + +PROMETHEUS_METRICS_EXPORT_PORT = 9091 +PROMETHEUS_METRICS_EXPORT_ADDRESS = '0.0.0.0' From a6f2291ba4464a6265ea7893523c7177a87145fc Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Mon, 27 Mar 2023 15:54:48 +0200 Subject: [PATCH 6/8] almost fix django storages --- Dockerfile | 6 ++ poetry.lock | 112 ++++++++++++++++++++++++- pyproject.toml | 2 + website/website/settings/base.py | 4 +- website/website/settings/production.py | 61 +++++++++++--- 5 files changed, 172 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5f39182..cc44988 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,4 +42,10 @@ COPY config/entrypoint.sh ./ # Copy the rest of the code. COPY website ./ +# Compile scss to css +#RUN ./manage.py compilescss +# +## Collect all static files for serving +#RUN ./manage.py collectstatic --no-input + ENTRYPOINT ["./entrypoint.sh"] diff --git a/poetry.lock b/poetry.lock index 19dc073..49dd2d1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -102,6 +102,46 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "boto3" +version = "1.26.99" +description = "The AWS SDK for Python" +category = "main" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "boto3-1.26.99-py3-none-any.whl", hash = "sha256:536d9e7a074f4f16cc87b426f91b3079edd5c6927541a04f7e3fa28c53293532"}, + {file = "boto3-1.26.99.tar.gz", hash = "sha256:d9fd57d6e98fd919cdbd613428f685e05b48c71477fda1aa7fbf51867262c7d1"}, +] + +[package.dependencies] +botocore = ">=1.29.99,<1.30.0" +jmespath = ">=0.7.1,<2.0.0" +s3transfer = ">=0.6.0,<0.7.0" + +[package.extras] +crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] + +[[package]] +name = "botocore" +version = "1.29.99" +description = "Low-level, data-driven core of boto 3." +category = "main" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "botocore-1.29.99-py3-none-any.whl", hash = "sha256:15c205e4578253da1e8cc247b9d4755042f5f873f68ac6e5fed48f4bd6f008c6"}, + {file = "botocore-1.29.99.tar.gz", hash = "sha256:d1770b4fe5531870af7a81e9897b2092d2f89e4ba8cb7abbbaf3ab952f6b8a6f"}, +] + +[package.dependencies] +jmespath = ">=0.7.1,<2.0.0" +python-dateutil = ">=2.1,<3.0.0" +urllib3 = ">=1.25.4,<1.27" + +[package.extras] +crt = ["awscrt (==0.16.9)"] + [[package]] name = "click" version = "8.1.3" @@ -474,6 +514,29 @@ files = [ django = ">=3.2" django-classy-tags = ">=3.0" +[[package]] +name = "django-storages" +version = "1.13.2" +description = "Support for many storage backends in Django" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "django-storages-1.13.2.tar.gz", hash = "sha256:cbadd15c909ceb7247d4ffc503f12a9bec36999df8d0bef7c31e57177d512688"}, + {file = "django_storages-1.13.2-py3-none-any.whl", hash = "sha256:31dc5a992520be571908c4c40d55d292660ece3a55b8141462b4e719aa38eab3"}, +] + +[package.dependencies] +Django = ">=3.2" + +[package.extras] +azure = ["azure-storage-blob (>=12.0.0)"] +boto3 = ["boto3 (>=1.4.4)"] +dropbox = ["dropbox (>=7.2.1)"] +google = ["google-cloud-storage (>=1.27.0)"] +libcloud = ["apache-libcloud"] +sftp = ["paramiko (>=1.10.0)"] + [[package]] name = "django-treebeard" version = "4.4" @@ -778,6 +841,18 @@ python-dateutil = "*" six = ">1.5" tatsu = ">4.2" +[[package]] +name = "jmespath" +version = "1.0.1" +description = "JSON Matching Expressions" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"}, + {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, +] + [[package]] name = "libsass" version = "0.22.0" @@ -1358,6 +1433,24 @@ files = [ {file = "rjsmin-1.2.1.tar.gz", hash = "sha256:1f982be8e011438777a94307279b40134a3935fc0f079312ee299725b8af5411"}, ] +[[package]] +name = "s3transfer" +version = "0.6.0" +description = "An Amazon S3 Transfer Manager" +category = "main" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"}, + {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"}, +] + +[package.dependencies] +botocore = ">=1.12.36,<2.0a.0" + +[package.extras] +crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] + [[package]] name = "setuptools" version = "67.6.0" @@ -1516,6 +1609,23 @@ files = [ {file = "Unidecode-1.1.2.tar.gz", hash = "sha256:a039f89014245e0cad8858976293e23501accc9ff5a7bdbc739a14a2b7b85cdc"}, ] +[[package]] +name = "urllib3" +version = "1.26.15" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + [[package]] name = "webencodings" version = "0.5.1" @@ -1578,4 +1688,4 @@ production = ["gunicorn", "psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "e445165e1f4080e507f0bc507a9ec40afd3b9986121b27047a931a9166bb1b92" +content-hash = "f10c335ea61077eb0cfc355ace13870a955dcee1f8ac168106528b0405fad970" diff --git a/pyproject.toml b/pyproject.toml index e15c2f5..a3335a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,8 @@ setuptools = "^67.6.0" whitenoise = "^6.4.0" dj-database-url = "^1.2.0" django-prometheus = "^2.2.0" +django-storages = "^1.13.2" +boto3 = "^1.26.99" [tool.poetry.dev-dependencies] black = "^22.8.0" diff --git a/website/website/settings/base.py b/website/website/settings/base.py index c452e95..73a9374 100644 --- a/website/website/settings/base.py +++ b/website/website/settings/base.py @@ -20,7 +20,7 @@ SITE_ID = 1 -X_FRAME_OPTIONS = "DENY" +X_FRAME_OPTIONS = "SAMEORIGIN" LOGIN_URL = "/user/login/" @@ -117,7 +117,7 @@ "cms.middleware.utils.ApphookReloadMiddleware", ] -CSRF_COOKIE_SECURE=True +CSRF_COOKIE_SECURE = True ROOT_URLCONF = "website.urls" diff --git a/website/website/settings/production.py b/website/website/settings/production.py index 367bdc5..db82e4f 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -6,7 +6,7 @@ SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False +DEBUG = True ALLOWED_HOSTS = ["bf2-website.fly.dev", ".bfrisbee2s.nl", "bf2.luko.dev", "localhost"] @@ -14,7 +14,7 @@ "https://bfrisbee2s.nl", "http://localhost", "https://bf2.luko.dev", - "https://bf2-website.fly.dev" + "https://bf2-website.fly.dev", ] SESSION_COOKIE_SECURE = True @@ -23,7 +23,7 @@ SECURE_HSTS_PRELOAD = True DATABASES = { - 'default': dj_database_url.config( + "default": dj_database_url.config( conn_max_age=600, conn_health_checks=True, ), @@ -32,26 +32,67 @@ DJANGOCMS_GOOGLEMAP_API_KEY = os.environ.get("GOOGLE_MAPS_KEY") EMAIL_HOST = "smtp-relay.gmail.com" +EMAIL_HOST_USER = "support@bfrisbee2s.nl" EMAIL_PORT = 587 EMAIL_USE_TLS = True DEFAULT_FROM_EMAIL = "no-reply@bfrisbee2s.nl" -SERVER_EMAIL = "ohnee@bfrisbee2s.nl" +SERVER_EMAIL = "support@bfrisbee2s.nl" -ADMINS = [("Webmasters", "webmaster@bfrisbee2s.nl")] +ADMINS = [("Webmasters", "webmasters@bfrisbee2s.nl")] + +# Static files +DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" +AWS_S3_REGION_NAME = "us-west-000" +AWS_STORAGE_BUCKET_NAME = "BFrisBee2s-Media" +AWS_S3_ENDPOINT_URL = "https://s3.us-west-000.backblazeb2.com" +AWS_PRELOAD_METADATA = False STATIC_ROOT = "/bf2-www/static/" STATIC_URL = "/static/" SASS_PROCESSOR_ROOT = STATIC_ROOT -MEDIA_ROOT = "/bf2-www/media" MEDIA_URL = "/media/" -INSTALLED_APPS += ['django_prometheus'] -MIDDLEWARE.insert(0, 'django_prometheus.middleware.PrometheusBeforeMiddleware') -MIDDLEWARE.append('django_prometheus.middleware.PrometheusAfterMiddleware') +# Logging +INSTALLED_APPS += ["django_prometheus"] +MIDDLEWARE.insert(0, "django_prometheus.middleware.PrometheusBeforeMiddleware") +MIDDLEWARE.append("django_prometheus.middleware.PrometheusAfterMiddleware") PROMETHEUS_METRICS_EXPORT_PORT = 9091 -PROMETHEUS_METRICS_EXPORT_ADDRESS = '0.0.0.0' +PROMETHEUS_METRICS_EXPORT_ADDRESS = "0.0.0.0" + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}}, + "handlers": { + "mail_admins": { + "level": "ERROR", + "filters": ["require_debug_false"], + "class": "django.utils.log.AdminEmailHandler", + }, + "applogfile": { + "level": "DEBUG", + "class": "logging.handlers.RotatingFileHandler", + "filename": os.path.join("/APPNAME.log"), + "maxBytes": 1024 * 1024 * 15, # 15MB + "backupCount": 10, + }, + }, + "loggers": { + "django.request": { + "handlers": ["mail_admins"], + "level": "ERROR", + "propagate": True, + }, + "APPNAME": { + "handlers": [ + "applogfile", + ], + "level": "DEBUG", + }, + }, +} From 8308a1494e67e3ab667bac6499b3352f9da381c6 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Thu, 30 Mar 2023 15:55:01 +0200 Subject: [PATCH 7/8] WIP --- .env | 1 - .envrc | 0 .gitignore | 4 +++- website/website/settings/development.py | 7 ++++++- website/website/settings/production.py | 4 ++-- 5 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 .env delete mode 100644 .envrc diff --git a/.env b/.env deleted file mode 100644 index 5892416..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -DOMAIN=beta.bfrisbee2s.nl \ No newline at end of file diff --git a/.envrc b/.envrc deleted file mode 100644 index e69de29..0000000 diff --git a/.gitignore b/.gitignore index b9b6b76..41f894f 100644 --- a/.gitignore +++ b/.gitignore @@ -142,4 +142,6 @@ config/secrets.env **/main.css -.direnv/ \ No newline at end of file +.direnv/ +.envrc +.env \ No newline at end of file diff --git a/website/website/settings/development.py b/website/website/settings/development.py index dedd1e5..80097ad 100644 --- a/website/website/settings/development.py +++ b/website/website/settings/development.py @@ -29,7 +29,12 @@ SASS_PROCESSOR_ROOT = STATIC_ROOT MEDIA_URL = "/media/" -MEDIA_ROOT = os.path.join(BASE_DIR, "media") +# MEDIA_ROOT = os.path.join(BASE_DIR, "media") +DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" +AWS_S3_REGION_NAME = "eu-central-003" +AWS_STORAGE_BUCKET_NAME = "BFrisBee2s-Media" +AWS_S3_ENDPOINT_URL = "https://s3.eu-central-003.backblazeb2.com" +AWS_PRELOAD_METADATA = False # Email settings # https://docs.djangoproject.com/en/3.1/topics/email/ diff --git a/website/website/settings/production.py b/website/website/settings/production.py index db82e4f..6e37b7e 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -44,9 +44,9 @@ # Static files DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" -AWS_S3_REGION_NAME = "us-west-000" +AWS_S3_REGION_NAME = "eu-central-003" AWS_STORAGE_BUCKET_NAME = "BFrisBee2s-Media" -AWS_S3_ENDPOINT_URL = "https://s3.us-west-000.backblazeb2.com" +AWS_S3_ENDPOINT_URL = "https://s3.eu-central-003.backblazeb2.com" AWS_PRELOAD_METADATA = False STATIC_ROOT = "/bf2-www/static/" From 6d9a5a248a1d3a1d0ec48a06eb881e376a13be76 Mon Sep 17 00:00:00 2001 From: Luko van der Maas Date: Wed, 19 Apr 2023 14:17:52 +0200 Subject: [PATCH 8/8] Add wip django storages stuff --- flake.nix | 1 - poetry.lock | 43 ++++++++++++++++++++++++- website/website/settings/development.py | 2 ++ website/website/settings/production.py | 1 + 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 971140d..2472b9c 100644 --- a/flake.nix +++ b/flake.nix @@ -17,7 +17,6 @@ openssl httpie ]; - shellHook = "fish"; }; }); } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 49dd2d1..dc54e36 100644 --- a/poetry.lock +++ b/poetry.lock @@ -800,6 +800,47 @@ gevent = ["gevent (>=1.4.0)"] setproctitle = ["setproctitle"] tornado = ["tornado (>=0.2)"] +[[package]] +name = "guppy3" +version = "3.1.2" +description = "Guppy 3 -- Guppy-PE ported to Python 3" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "guppy3-3.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e62be11076538a0bd7edc520c687af1f7adf29d73388b0c6aea1b4ae2cab6166"}, + {file = "guppy3-3.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b65c8b3f05e3385039fc38a93cd4d77e182791ed765716d7f3a05654cb7c04"}, + {file = "guppy3-3.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:209f0fb5cbdb48466efb6d359bbee1217c6975850e87c397156f0f699afee96b"}, + {file = "guppy3-3.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b6f3bd78b41736b02cf7b1999d55bb7cdb56188834499235ee3e090287dc9154"}, + {file = "guppy3-3.1.2-cp310-cp310-win32.whl", hash = "sha256:f090e5e8e161d303b79dab7f2cac1ef4dd34e1445a750ed4e24d2137ca0c2b76"}, + {file = "guppy3-3.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:08dcd39b03bcfd421d4b47a7c990a05d4c74b295b1913dbb9fd372b5413b5f54"}, + {file = "guppy3-3.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c960e2426682d37f6023970e53a96074eddd785fd2284d084c87d3812dec2e56"}, + {file = "guppy3-3.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:761b8e9f66399a597196399481f37ef2ddde3ef701b92ab3121f6b24f522c709"}, + {file = "guppy3-3.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b13810c923b0af1669355effa23eb46d99279ca53d8c41e5703523b0de01b144"}, + {file = "guppy3-3.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f696abf521e37ccacd5998cf9a237418e86c35dc09499d549697eeead919080e"}, + {file = "guppy3-3.1.2-cp36-cp36m-win32.whl", hash = "sha256:7aa6b3ebb04fe316b6b862520a50e211295981d36245134d5ea72a1f9b045838"}, + {file = "guppy3-3.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:9ee1c64406bc0a0f062f8ea4816f92475f52ad72158d896cd99195a4d340b662"}, + {file = "guppy3-3.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3d9ba91a116f307f99017a3f6d0296ec9faa14cf7de1dda0251a65046addba83"}, + {file = "guppy3-3.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b95152c530e95de656d04f39da28cae54feb22a347431a81f61cdaa48f4089fa"}, + {file = "guppy3-3.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92ca5166db307b72ae392bdf464709c2fb074a69cdcf5b14258ad17b14b11117"}, + {file = "guppy3-3.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9036605f12e7a276f37b25b007ec1be2a55dd617e1955890adf2426027f0de77"}, + {file = "guppy3-3.1.2-cp37-cp37m-win32.whl", hash = "sha256:69ad8645f1bd5a7c038b4e0b0c0f8c55f9abaf48fddd7e8c548e7966f195ead7"}, + {file = "guppy3-3.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:413b40ba376a4053556f789d87cc7d27e09386b8036e8457fe43a5a12d9a5d1f"}, + {file = "guppy3-3.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:11331da76eb6ee09f1d3da3b67301450df9992593d41ac9cec9bb6e35c716be0"}, + {file = "guppy3-3.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9bc94a74fe923d22a1bf11746ef5fd3576e26219411dccba0a26056d37dfd44"}, + {file = "guppy3-3.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:04507ad33d29a29d3cb61cdc1cc7f2949a08bbe854b6219092d499ae58cb52c8"}, + {file = "guppy3-3.1.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:53b8f89bbaf861c0eb3ebc87139903f863e9c4c1b3094df8b22e9e80d959bfff"}, + {file = "guppy3-3.1.2-cp38-cp38-win32.whl", hash = "sha256:6f4f30fb4e751ccaa3313597970eb72b555e8b184d9f748379d2bbdb899ac318"}, + {file = "guppy3-3.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:dfe0ae2b2175f76eb5cd58568173e10c52501abdd59f269fbc3859f7176003fb"}, + {file = "guppy3-3.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cb116d1b7e0f951cc29fb7d69d769835bdb9604d17ee4f2ee328d342ade8e5ef"}, + {file = "guppy3-3.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:521b0eb27f6875f4237000c92c75f8e631f9c950247692e5b983c72ec0314119"}, + {file = "guppy3-3.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:89b2056397a4f86fd96b7585d7ea3586001079423fd70c880bd8d475c30d0fe7"}, + {file = "guppy3-3.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb40137aba3f50662584fafe74cfd3fb4204e48394c9dfb23d280977304ed460"}, + {file = "guppy3-3.1.2-cp39-cp39-win32.whl", hash = "sha256:1670fcd91e61969cb9190014f557f13e051cc73a53f89fa4403a238bd2f1955a"}, + {file = "guppy3-3.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:1a1f98f9158082c5a3277661b56c7efd8b4634625f864477bb010382cebde83a"}, + {file = "guppy3-3.1.2.tar.gz", hash = "sha256:af580bec5269b1621f45bd589d76aa1a7c1986742a84ab016f0a0de9ff06086d"}, +] + [[package]] name = "html5lib" version = "1.1" @@ -1688,4 +1729,4 @@ production = ["gunicorn", "psycopg2-binary"] [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "f10c335ea61077eb0cfc355ace13870a955dcee1f8ac168106528b0405fad970" +content-hash = "e45e7995878924da82c9291a7a49985ee2fab2cb7f28b9408c1a639d8995ad93" diff --git a/website/website/settings/development.py b/website/website/settings/development.py index 80097ad..f9cfca3 100644 --- a/website/website/settings/development.py +++ b/website/website/settings/development.py @@ -34,8 +34,10 @@ AWS_S3_REGION_NAME = "eu-central-003" AWS_STORAGE_BUCKET_NAME = "BFrisBee2s-Media" AWS_S3_ENDPOINT_URL = "https://s3.eu-central-003.backblazeb2.com" +AWS_S3_MAX_MEMORY_SIZE = 10 * 1000000 # 10MB AWS_PRELOAD_METADATA = False + # Email settings # https://docs.djangoproject.com/en/3.1/topics/email/ EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" diff --git a/website/website/settings/production.py b/website/website/settings/production.py index 6e37b7e..8a5d8c4 100644 --- a/website/website/settings/production.py +++ b/website/website/settings/production.py @@ -47,6 +47,7 @@ AWS_S3_REGION_NAME = "eu-central-003" AWS_STORAGE_BUCKET_NAME = "BFrisBee2s-Media" AWS_S3_ENDPOINT_URL = "https://s3.eu-central-003.backblazeb2.com" +AWS_S3_MAX_MEMORY_SIZE = 10 * 1000000 # 10MB AWS_PRELOAD_METADATA = False STATIC_ROOT = "/bf2-www/static/"