From 6626cd90eca97513f4f7c81ff4f4fdb8060ec120 Mon Sep 17 00:00:00 2001 From: LukeVader-IV Date: Wed, 9 Jul 2025 20:42:41 +0200 Subject: [PATCH 1/5] Change docker compose env vars Previously, each container would be handed all the env vars int the .env file. This is bad practice for a variety of reasons. This commit changes it so the docker compose file specified the env file for each container. the benefits: - less env vars to be set by the end user - containers are only given vars relevant to them - when running docker compose up, only containers affected by changed vars are restarted --- .env.example | 15 +++++---------- docker-compose.yml | 30 ++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/.env.example b/.env.example index 8a923ae..6c0826b 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,9 @@ # 🌐 Frontend -PUBLIC_SERVER_URL=http://server:8000 # PLEASE DON'T CHANGE :) - Should be the service name of the backend with port 8000, even if you change the port in the backend service. Only change if you are using a custom more complex setup. -ORIGIN=http://localhost:8015 +FRONTEND_URL=http://localhost:8014 # URL that is allowed to be used for accessing the frontend BODY_SIZE_LIMIT=Infinity -FRONTEND_PORT=8015 +FRONTEND_PORT=8014 # port used in the internal network (outside docker) # 🐘 PostgreSQL Database -PGHOST=db POSTGRES_DB=database POSTGRES_USER=adventure POSTGRES_PASSWORD=changeme123 @@ -15,11 +13,8 @@ SECRET_KEY=changeme123 DJANGO_ADMIN_USERNAME=admin DJANGO_ADMIN_PASSWORD=admin DJANGO_ADMIN_EMAIL=admin@example.com -PUBLIC_URL=http://localhost:8016 # Match the outward port, used for the creation of image urls -CSRF_TRUSTED_ORIGINS=http://localhost:8016,http://localhost:8015 -DEBUG=False -FRONTEND_URL=http://localhost:8015 # Used for email generation. This should be the url of the frontend -BACKEND_PORT=8016 +BACKEND_URL=http://localhost:8017 # URL that is allowed to be used for accessing the backend, used for the creation of image urls +BACKEND_PORT=8017 # port exposed to the internal network (outside docker) # Optional: use Google Maps integration # https://adventurelog.app/docs/configuration/google_maps_integration.html @@ -44,4 +39,4 @@ DISABLE_REGISTRATION=False # Optional: Use Umami for analytics # https://adventurelog.app/docs/configuration/analytics.html # PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js # If you are using the hosted version of Umami -# PUBLIC_UMAMI_WEBSITE_ID= \ No newline at end of file +# PUBLIC_UMAMI_WEBSITE_ID= diff --git a/docker-compose.yml b/docker-compose.yml index 034ec06..e1450ac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,11 @@ services: image: ghcr.io/seanmorley15/adventurelog-frontend:latest container_name: adventurelog-frontend restart: unless-stopped - env_file: .env + environment: + - PUBLIC_SERVER_URL=http://server:8000 # PLEASE DON'T CHANGE :) - Should be the service name of the backend with port 8000, even if you change the port in the backend service. Only change if you are using a custom more complex setup. + - ORIGIN=${FRONTENT_URL:-http://localhost:8015} + - BODY_SIZE_LIMIT=${BODY_SIZE_LIMIT:-Infinity} + #- FRONTEND_PORT=${FRONTEND_PORT=:-8015} ports: - "${FRONTEND_PORT:-8015}:3000" depends_on: @@ -14,16 +18,34 @@ services: image: postgis/postgis:16-3.5 container_name: adventurelog-db restart: unless-stopped - env_file: .env + environment: + - POSTGRES_DB=${POSTGRES_DB:-database} + - POSTGRES_USER=${POSTGRES_USER:-adventure} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} volumes: - postgres_data:/var/lib/postgresql/data/ server: #build: ./backend/ - image: ghcr.io/seanmorley15/adventurelog-backend:latest + #image: ghcr.io/seanmorley15/adventurelog-backend:latest + image: 9f0471e8d7f872adf81dc41c9296f99fbadac01edb26e container_name: adventurelog-backend restart: unless-stopped - env_file: .env + environment: + - PGHOST=db + - POSTGRES_DB=${POSTGRES_DB:-database} + - POSTGRES_USER=${POSTGRES_USER:-adventure} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} + - SECRET_KEY=${SECRET_KEY:-changeme123} + - DJANGO_ADMIN_USERNAME=${DJANGO_ADMIN_USERNAME:-admin} + - DJANGO_ADMIN_PASSWORD=${DJANGO_ADMIN_PASSWORD:-admin} + - DJANGO_ADMIN_EMAIL=${DJANGO_ADMIN_EMAIL:-admin@example.com} + - PUBLIC_URL=${BACKEND_URL:-http://localhost:8016} + - CSRF_TRUSTED_ORIGINS=${FRONTEND_URL:-http://localhost:8015},${BACKEND_URL:-http://localhost:8016} + - DEBUG=False + - FRONTEND_URL=${FRONTEND_URL:-http://localhost:8015} # Used for email generation. This should be the url of the frontend + - BACKEND_PORT=${BACKEND_PORT:-8016} + ports: - "${BACKEND_PORT:-8016}:80" depends_on: From 6691949f7a18823391974f73329ce9ea16a59ead Mon Sep 17 00:00:00 2001 From: LukeVader-IV Date: Wed, 9 Jul 2025 20:47:59 +0200 Subject: [PATCH 2/5] change sample .env file name files starting with a `.` chatacter are "hidden files" in UNIX systems. some less knowledgable users may get confused by not seeing a file they expect. changing the example env file to not be a hidden file, making it easier to discover for a user --- .env.example => example.env | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .env.example => example.env (100%) diff --git a/.env.example b/example.env similarity index 100% rename from .env.example rename to example.env From c06eabf34fd14ce79f7af02ececc6fa75cf2c6b3 Mon Sep 17 00:00:00 2001 From: LukeVader-IV Date: Wed, 9 Jul 2025 21:01:36 +0200 Subject: [PATCH 3/5] reset ports to defaults --- example.env | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example.env b/example.env index 6c0826b..844ad0a 100644 --- a/example.env +++ b/example.env @@ -1,7 +1,7 @@ # 🌐 Frontend -FRONTEND_URL=http://localhost:8014 # URL that is allowed to be used for accessing the frontend +FRONTEND_URL=http://localhost:8015 # URL that is allowed to be used for accessing the frontend BODY_SIZE_LIMIT=Infinity -FRONTEND_PORT=8014 # port used in the internal network (outside docker) +FRONTEND_PORT=8015 # port used in the internal network (outside docker) # 🐘 PostgreSQL Database POSTGRES_DB=database @@ -13,8 +13,8 @@ SECRET_KEY=changeme123 DJANGO_ADMIN_USERNAME=admin DJANGO_ADMIN_PASSWORD=admin DJANGO_ADMIN_EMAIL=admin@example.com -BACKEND_URL=http://localhost:8017 # URL that is allowed to be used for accessing the backend, used for the creation of image urls -BACKEND_PORT=8017 # port exposed to the internal network (outside docker) +BACKEND_URL=http://localhost:8016 # URL that is allowed to be used for accessing the backend, used for the creation of image urls +BACKEND_PORT=8016 # port exposed to the internal network (outside docker) # Optional: use Google Maps integration # https://adventurelog.app/docs/configuration/google_maps_integration.html From 537790c7505743bcccd162e5f73cd56d3edf7bf0 Mon Sep 17 00:00:00 2001 From: LukeVader-IV Date: Wed, 9 Jul 2025 21:19:40 +0200 Subject: [PATCH 4/5] update docker repo to new docker compose structure note: unsure about the "required" field, as any required vars are now defined in the docker compose file --- documentation/docs/install/docker.md | 34 ++++++++++++---------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/documentation/docs/install/docker.md b/documentation/docs/install/docker.md index b698502..02b9cb8 100644 --- a/documentation/docs/install/docker.md +++ b/documentation/docs/install/docker.md @@ -10,15 +10,16 @@ Docker is the preferred way to run AdventureLog on your local machine. It is a l ## Getting Started -Get the `docker-compose.yml` and `.env.example` files from the AdventureLog repository. You can download them here: +Get the `docker-compose.yml` and `example.env` files from the AdventureLog repository. You can download them here: - [Docker Compose](https://github.com/seanmorley15/AdventureLog/blob/main/docker-compose.yml) -- [Environment Variables](https://github.com/seanmorley15/AdventureLog/blob/main/.env.example) +- [Environment Variables](https://github.com/seanmorley15/AdventureLog/blob/main/example.env) ```bash wget https://raw.githubusercontent.com/seanmorley15/AdventureLog/main/docker-compose.yml -wget https://raw.githubusercontent.com/seanmorley15/AdventureLog/main/.env.example -cp .env.example .env +wget https://raw.githubusercontent.com/seanmorley15/AdventureLog/main/example.env +cp example.env. .env +nano .env ``` ::: tip @@ -35,33 +36,28 @@ The `.env` file contains all the configuration settings for your AdventureLog in | Name | Required | Description | Default Value | | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | -| `PUBLIC_SERVER_URL` | Yes | Used by the frontend SSR server to connect to the backend. Almost every user user will **never have to change this from default**! | `http://server:8000` | -| `ORIGIN` | Sometimes | Needed only if not using HTTPS. Set it to the domain or IP you'll use to access the frontend. | `http://localhost:8015` | +| `FRONTEND_URL` | Yes | Set it to the domain or IP you'll use to access the frontend. | `http://localhost:8015` | | `BODY_SIZE_LIMIT` | Yes | Maximum upload size in bytes. | `Infinity` | -| `FRONTEND_PORT` | Yes | Port that the frontend will run on inside Docker. | `8015` | +| `FRONTEND_PORT` | Yes | Port that the frontend will run on in the internal network. | `8015` | ### 🐘 PostgreSQL Database | Name | Required | Description | Default Value | | ------------------- | -------- | --------------------- | ------------- | -| `PGHOST` | Yes | Internal DB hostname. | `db` | | `POSTGRES_DB` | Yes | DB name. | `database` | | `POSTGRES_USER` | Yes | DB user. | `adventure` | | `POSTGRES_PASSWORD` | Yes | DB password. | `changeme123` | ### 🔒 Backend (server) -| Name | Required | Description | Default Value | -| ----------------------- | -------- | ---------------------------------------------------------------------------------- | --------------------------------------------- | -| `SECRET_KEY` | Yes | Django secret key. Change this in production! | `changeme123` | -| `DJANGO_ADMIN_USERNAME` | Yes | Default Django admin username. | `admin` | -| `DJANGO_ADMIN_PASSWORD` | Yes | Default Django admin password. | `admin` | -| `DJANGO_ADMIN_EMAIL` | Yes | Default admin email. | `admin@example.com` | -| `PUBLIC_URL` | Yes | Publicly accessible URL of the **backend**. Used for generating image URLs. | `http://localhost:8016` | -| `CSRF_TRUSTED_ORIGINS` | Yes | Comma-separated list of frontend/backend URLs that are allowed to submit requests. | `http://localhost:8016,http://localhost:8015` | -| `FRONTEND_URL` | Yes | URL to the **frontend**, used for email generation. | `http://localhost:8015` | -| `BACKEND_PORT` | Yes | Port that the backend will run on inside Docker. | `8016` | -| `DEBUG` | No | Should be `False` in production. | `False` | +| Name | Required | Description | Default Value | +| ----------------------- | -------- | -----------------------------------------------------------------------------------------------------------------------|---------------------------------------------| +| `SECRET_KEY` | Yes | Django secret key. Change this in production! | `changeme123` | +| `DJANGO_ADMIN_USERNAME` | Yes | Default Django admin username. | `admin` | +| `DJANGO_ADMIN_PASSWORD` | Yes | Default Django admin password. | `admin` | +| `DJANGO_ADMIN_EMAIL` | Yes | Default admin email. | `admin@example.com` | +| `BACKEND_URL` | Yes | Publicly accessible URL of the **backend**. Used for generating image URLs, the admin UI, and OIDC/Social Auth. | `http://localhost:8016` | +| `BACKEND_PORT` | Yes | Port that the backend will run on inside Docker. | `8016` | ## Optional Configuration From 3039306953b011e1f06ff8ab6bdc4e5d1092709c Mon Sep 17 00:00:00 2001 From: LukeVader-IV Date: Mon, 14 Jul 2025 22:46:29 +0200 Subject: [PATCH 5/5] Base for docker secrets Note: this currently fails at compile time --- backend/entrypoint.sh | 11 +++++---- backend/server/main/settings.py | 18 ++++++++++---- docker-compose.yml | 42 +++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 15 deletions(-) diff --git a/backend/entrypoint.sh b/backend/entrypoint.sh index 1031cb1..f878d6f 100644 --- a/backend/entrypoint.sh +++ b/backend/entrypoint.sh @@ -16,12 +16,14 @@ check_postgres() { local db_host local db_user local db_name - local db_pass + #local db_pass db_host=$(get_env PGHOST) db_user=$(get_env PGUSER POSTGRES_USER) db_name=$(get_env PGDATABASE POSTGRES_DB) - db_pass=$(get_env PGPASSWORD POSTGRES_PASSWORD) + #db_pass=$(get_env PGPASSWORD POSTGRES_PASSWORD) + db_pass=$(< /run/secrets/POSTGRES_PASSWORD) + # NOTE: password should be handled with more care PGPASSWORD="$db_pass" psql -h "$db_host" -U "$db_user" -d "$db_name" -c '\q' >/dev/null 2>&1 } @@ -42,7 +44,8 @@ done python manage.py migrate # Create superuser if environment variables are set and there are no users present at all. -if [ -n "$DJANGO_ADMIN_USERNAME" ] && [ -n "$DJANGO_ADMIN_PASSWORD" ] && [ -n "$DJANGO_ADMIN_EMAIL" ]; then +# NOTE: unsure if this checks if a password actually exists +if [ -n "$DJANGO_ADMIN_USERNAME" ] && [ -f /run/secrets/DJANGO-ADMIN-PASSWORD ] && [ -n "$DJANGO_ADMIN_EMAIL" ]; then echo "Creating superuser..." python manage.py shell << EOF from django.contrib.auth import get_user_model @@ -56,7 +59,7 @@ if not User.objects.filter(username='$DJANGO_ADMIN_USERNAME').exists(): superuser = User.objects.create_superuser( username='$DJANGO_ADMIN_USERNAME', email='$DJANGO_ADMIN_EMAIL', - password='$DJANGO_ADMIN_PASSWORD' + password='$(cat /run/secrets/DJANGO-ADMIN-PASSWORD)' ) print("Superuser created successfully.") diff --git a/backend/server/main/settings.py b/backend/server/main/settings.py index 073fd77..2edb0c5 100644 --- a/backend/server/main/settings.py +++ b/backend/server/main/settings.py @@ -24,7 +24,9 @@ BASE_DIR = os.path.dirname(os.path.dirname(__file__)) # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = getenv('SECRET_KEY') +with open('/run/secret/DJANGO-ADMIN-PASSWORD') as fp: + v = fp.read() +SECRET_KEY = v.decode('base64') # SECURITY WARNING: don't run with debug turned on in production! DEBUG = getenv('DEBUG', 'true').lower() == 'true' @@ -112,12 +114,16 @@ def env(*keys, default=None): return value return default +with open('/run/secrets/POSTGRES_PASSWORD') as fp: + v = fp.read() +POSTGRES_PASSWORD = v.decode('base64') + DATABASES = { 'default': { 'ENGINE': 'django.contrib.gis.db.backends.postgis', 'NAME': env('PGDATABASE', 'POSTGRES_DB'), 'USER': env('PGUSER', 'POSTGRES_USER'), - 'PASSWORD': env('PGPASSWORD', 'POSTGRES_PASSWORD'), + 'PASSWORD': POSTGRES_PASSWORD, 'HOST': env('PGHOST', default='localhost'), 'PORT': int(env('PGPORT', default='5432')), 'OPTIONS': { @@ -126,6 +132,8 @@ DATABASES = { } } +POSTGRES_PASSWORD = "" + # Internationalization # https://docs.djangoproject.com/en/1.7/topics/i18n/ @@ -259,7 +267,7 @@ else: EMAIL_PORT = getenv('EMAIL_PORT', 587) EMAIL_USE_SSL = getenv('EMAIL_USE_SSL', 'false').lower() == 'true' EMAIL_HOST_USER = getenv('EMAIL_HOST_USER') - EMAIL_HOST_PASSWORD = getenv('EMAIL_HOST_PASSWORD') + EMAIL_HOST_PASSWORD = '$(< /run/secrets/EMAIL-HOST-PASSWORD)' DEFAULT_FROM_EMAIL = getenv('DEFAULT_FROM_EMAIL') # EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' @@ -327,4 +335,6 @@ LOGGING = { # https://github.com/dr5hn/countries-states-cities-database/tags COUNTRY_REGION_JSON_VERSION = 'v2.6' -GOOGLE_MAPS_API_KEY = getenv('GOOGLE_MAPS_API_KEY', '') \ No newline at end of file +with open('/run/secrets/GMAPS_API_KEY') as fp: + v = fp.read() +GOOGLE_MAPS_API_KEY = v.decode('base64') diff --git a/docker-compose.yml b/docker-compose.yml index e1450ac..2d6fdd9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,6 @@ services: - PUBLIC_SERVER_URL=http://server:8000 # PLEASE DON'T CHANGE :) - Should be the service name of the backend with port 8000, even if you change the port in the backend service. Only change if you are using a custom more complex setup. - ORIGIN=${FRONTENT_URL:-http://localhost:8015} - BODY_SIZE_LIMIT=${BODY_SIZE_LIMIT:-Infinity} - #- FRONTEND_PORT=${FRONTEND_PORT=:-8015} ports: - "${FRONTEND_PORT:-8015}:3000" depends_on: @@ -21,31 +20,50 @@ services: environment: - POSTGRES_DB=${POSTGRES_DB:-database} - POSTGRES_USER=${POSTGRES_USER:-adventure} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} + #- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} + - POSTGRES_PASSWORD_FILE=/run/secrets/POSTGRES_PASSWORD + secrets: + - POSTGRES_PASSWORD volumes: - postgres_data:/var/lib/postgresql/data/ server: #build: ./backend/ - #image: ghcr.io/seanmorley15/adventurelog-backend:latest - image: 9f0471e8d7f872adf81dc41c9296f99fbadac01edb26e + image: ghcr.io/seanmorley15/adventurelog-backend:latest container_name: adventurelog-backend restart: unless-stopped environment: - PGHOST=db - POSTGRES_DB=${POSTGRES_DB:-database} - POSTGRES_USER=${POSTGRES_USER:-adventure} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} + #- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme123} - SECRET_KEY=${SECRET_KEY:-changeme123} - DJANGO_ADMIN_USERNAME=${DJANGO_ADMIN_USERNAME:-admin} - - DJANGO_ADMIN_PASSWORD=${DJANGO_ADMIN_PASSWORD:-admin} + #- DJANGO_ADMIN_PASSWORD=${DJANGO_ADMIN_PASSWORD:-admin} - DJANGO_ADMIN_EMAIL=${DJANGO_ADMIN_EMAIL:-admin@example.com} - PUBLIC_URL=${BACKEND_URL:-http://localhost:8016} - CSRF_TRUSTED_ORIGINS=${FRONTEND_URL:-http://localhost:8015},${BACKEND_URL:-http://localhost:8016} - DEBUG=False - FRONTEND_URL=${FRONTEND_URL:-http://localhost:8015} # Used for email generation. This should be the url of the frontend - BACKEND_PORT=${BACKEND_PORT:-8016} - + - DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-False} + - DISABLE_REGISTRATION_MESSAGE=${DISABLE_REGISTRATION_MESSAGE} + - EMAIL_BACKEND=${EMAIL_BACKEND:-console} + - EMAIL_HOST=${EMAIL_HOST} + - EMAIL_USE_TLS=${EMAIL_USE_TLS} + - EMAIL_PORT=${EMAIL_PORT} + - EMAIL_USE_SSL=${EMAIL_USE_SSL} + - EMAIL_HOST_USER=${EMAIL_HOST_USER} + #- EMAIL_HOST_PASSWORD=${EMAIL_HOST_PASSWORD} + - DEFAULT_FROM_EMAIL=${DEFAULT_FROM_EMAIL} + #- GOOGLE_MAPS_API_KEY=${GOOGLE_MAPS_API_KEY} + - PUBLIC_UMAMI_SRC=${PUBLIC_UMAMI_SRC} + - PUBLIC_UMAMI_WEBSITE_ID=${PUBLIC_UMAMI_WEBSITE_ID} + secrets: + - DJANGO-ADMIN-PASSWORD + - POSTGRES_PASSWORD + - EMAIL-HOST-PASSWORD + - GMAPS-API-KEY ports: - "${BACKEND_PORT:-8016}:80" depends_on: @@ -53,6 +71,16 @@ services: volumes: - adventurelog_media:/code/media/ +secrets: + GMAPS-API-KEY: + file: gmaps-api-key.txt + EMAIL-HOST-PASSWORD: + file: email-host-password.txt + DJANGO-ADMIN-PASSWORD: + file: django-admin-password.txt + POSTGRES_PASSWORD: + file: postgres-password.txt + volumes: postgres_data: adventurelog_media: