Repository: inventree/InvenTree

Issue:
Secrets file should be configurable.
For docker config and other secrets systems, the secrets come into a file inside the docker container.  

This would be nice to be configured.  Right now it has to be copied, but it could just be done in the following manner.

NOTE:  Whether you do it based upon the config.yaml or the envvars, is up to you, but if you want to scale it out past 1 docker container, this will make it easier for people to deploy it in docker.

``` python
if os.getenv("INVENTREE_SECRET_KEY",""):
    # The secret key is passed in as an envvar directly
    SECRET_KEY = os.getenv("INVENTREE_SECRET_KEY")
elif os.getenv("INVENTREE_SECRET_KEY_FILE",""):
    # Docker compose secrets come in as a file to the container
    SECRET_KEY = open(os.getenv("INVENTREE_SECRET_KEY_FILE", "r")).read().strip()
else:
    # Works only for one docker instance which is probably okay.  
    SECRET_KEY = generate_secret_key()
```

The docker compose config would then look like this:

``` docker-compose
inventree:
    build: ./inventree-docker
    container_name: inventree
    expose:
      - 9767/tcp
    networks:
      - proxy
      - db
    depends_on:
      - db
    volumes:
      - /mnt/dockerdata/inventree/static:/usr/src/static
      - /mnt/dockerdata/inventree/media:/usr/src/media
    secrets:
      - postgres_password
      - postgres_user
      - django_secret_key
    environment:
      - SECRET_KEY_FILE=/run/secrets/django_secret_key
      - DATABASE_USER_FILE=/run/secrets/postgres_user
      - DATABASE_PASSWORD_FILE=/run/secrets/postgres_password
      [...]
```



Discussion:
@rcludwick I am happy with this suggestion - I have little (to none) experience with docker but I can 100% see the utility of such a feature.
It's worth while checking out the linuxserver.io collection of projects for good examples of servers that can easily be deployed.  

Also, if you go down the celery path, no one will want to try to administrate rabbitmq, which is a pain the butt.  Better to run it in a docker container with a simple config so it's at least running in isolation.  Also makes development of those long running tasks easier, since you can just bring it up with a docker compose config file and a one liner command.

Resolving patch:
diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py
--- a/InvenTree/InvenTree/settings.py
+++ b/InvenTree/InvenTree/settings.py
@@ -11,17 +11,20 @@
 
 """
 
-import sys
-import os
 import logging
+import os
+import sys
 import tempfile
-import yaml
-
 from datetime import datetime
 
+import yaml
 from django.utils.translation import gettext_lazy as _
 
 
+def _is_true(x):
+    return x in [True, "True", "true", "Y", "y", "1"]
+
+
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
@@ -36,11 +39,14 @@
 
 # Default action is to run the system in Debug mode
 # SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = CONFIG.get('debug', True)
+DEBUG = _is_true(os.getenv("INVENTREE_DEBUG", CONFIG.get("debug", True)))
 
 # Configure logging settings
-
 log_level = CONFIG.get('log_level', 'DEBUG').upper()
+logging.basicConfig(
+    level=log_level,
+    format="%(asctime)s %(levelname)s %(message)s",
+)
 
 if log_level not in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
     log_level = 'WARNING'
@@ -59,20 +65,31 @@
     },
 }
 
-logging.basicConfig(
-    level=log_level,
-    format='%(asctime)s %(levelname)s %(message)s',
-)
-
 # Get a logger instance for this setup file
 logger = logging.getLogger(__name__)
 
-# Read the autogenerated key-file
-key_file_name = os.path.join(BASE_DIR, 'secret_key.txt')
-logger.info(f'Loading SECRET_KEY from {key_file_name}')
-key_file = open(key_file_name, 'r')
-
-SECRET_KEY = key_file.read().strip()
+if os.getenv("INVENTREE_SECRET_KEY"):
+    # Secret key passed in directly
+    SECRET_KEY = os.getenv("INVENTREE_SECRET_KEY").strip()
+    logger.info("SECRET_KEY loaded by INVENTREE_SECRET_KEY")
+else:
+    # Secret key passed in by file location
+    key_file = os.getenv("INVENTREE_SECRET_KEY_FILE")
+    if key_file:
+        if os.path.isfile(key_file):
+            logger.info("SECRET_KEY loaded by INVENTREE_SECRET_KEY_FILE")
+        else:
+            logger.error(f"Secret key file {key_file} not found")
+            exit(-1)
+    else:
+        # default secret key location
+        key_file = os.path.join(BASE_DIR, "secret_key.txt")
+        logger.info(f"SECRET_KEY loaded from {key_file}")
+    try:
+        SECRET_KEY = open(key_file, "r").read().strip()
+    except Exception:
+        logger.exception(f"Couldn't load keyfile {key_file}")
+        sys.exit(-1)
 
 # List of allowed hosts (default = allow all)
 ALLOWED_HOSTS = CONFIG.get('allowed_hosts', ['*'])
@@ -112,7 +129,7 @@
 
 if DEBUG:
     logger.info("InvenTree running in DEBUG mode")
-    
+
 logger.info(f"MEDIA_ROOT: '{MEDIA_ROOT}'")
 logger.info(f"STATIC_ROOT: '{STATIC_ROOT}'")
 
@@ -315,7 +332,7 @@
     - However there may be reason to configure the DB via environmental variables
     - The following code lets the user "mix and match" database configuration
     """
-    
+
     logger.info("Configuring database backend:")
 
     # Extract database configuration from the config.yaml file
@@ -341,7 +358,7 @@
 
     # Check that required database configuration options are specified
     reqiured_keys = ['ENGINE', 'NAME']
-    
+
     for key in reqiured_keys:
         if key not in db_config:
             error_msg = f'Missing required database configuration value {key} in config.yaml'


Test patch: