1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-08-04 12:45:17 +02:00
This commit is contained in:
UndyingSoul 2025-07-27 18:34:14 +02:00 committed by GitHub
commit 4ae72bed80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 1302 additions and 657 deletions

View file

@ -1,47 +1,50 @@
# 🌐 Frontend # 🌐 Frontend
FRONTEND_PORT=8015 # Don't forget to update CSRF_TRUSTED_ORIGINS in backend and FRONTEND_URL in backend and ORIGIN in frontend if you make changes to this.
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. 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 ORIGIN=http://localhost:8015
BODY_SIZE_LIMIT=Infinity BODY_SIZE_LIMIT=Infinity
FRONTEND_PORT=8015
# 🐘 PostgreSQL Database # 🐘 PostgreSQL Database
PGHOST=db PGHOST=db # Supposed to match the host of the postgis database
POSTGRES_DB=database POSTGRES_DB=adventurelog
POSTGRES_USER=adventure POSTGRES_USER=adventurelog
POSTGRES_PASSWORD=changeme123 POSTGRES_PASSWORD=changeme123
# POSTGRES_PASSWORD_FILE=/run/secrets/postgres-password # Uncomment this block if you'd rather use docker secrets (more-secure)
# 🔒 Django Backend # 🔒 Django Backend
SECRET_KEY=changeme123 SECRET_KEY=changeme123 # Replace with the actual secret key
DJANGO_ADMIN_USERNAME=admin # SECRET_KEY_FILE=/run/secrets/secret-key # Uncomment this block if you'd rather use docker secrets (more-secure)
DJANGO_ADMIN_PASSWORD=admin DJANGO_ADMIN_USERNAME=admin # Replace with the actual admin username
DJANGO_ADMIN_EMAIL=admin@example.com DJANGO_ADMIN_PASSWORD=admin # Replace with the actual admin password
PUBLIC_URL=http://localhost:8016 # Match the outward port, used for the creation of image urls # DJANGO_ADMIN_PASSWORD_FILE=/run/secrets/django-admin-password # Uncomment this block if you'd rather use docker secrets (more-secure)
CSRF_TRUSTED_ORIGINS=http://localhost:8016,http://localhost:8015 DJANGO_ADMIN_EMAIL=admin@example.com # Replace with the actual admin email
DEBUG=False BACKEND_PORT=8016 # Don't forget to update CSRF_TRUSTED_ORIGINS and PUBLIC_URL in backend, and PUBLIC_SERVER_URL in frontend if you make changes to this.
FRONTEND_URL=http://localhost:8015 # Used for email generation. This should be the url of the frontend PUBLIC_URL=http://localhost:8016 # Replace with your domain where the backend is accessible publicly, used for the creation of image urls
BACKEND_PORT=8016 CSRF_TRUSTED_ORIGINS=http://localhost:8016,http://localhost:8015 # Replace with your domain, if applicable
FRONTEND_URL=http://localhost:8015 # Replace with your domain where the frontend is accessible, used for email generation.
# Disabling Registration: https://adventurelog.app/docs/configuration/disable_registration.html
# DISABLE_REGISTRATION=False
# DISABLE_REGISTRATION_MESSAGE='Registration is disabled for this instance of AdventureLog.'
# Optional: use Google Maps integration
# https://adventurelog.app/docs/configuration/google_maps_integration.html
# GOOGLE_MAPS_API_KEY=your_google_maps_api_key
# Optional: disable registration # Integrations
# https://adventurelog.app/docs/configuration/disable_registration.html ## Email: https://adventurelog.app/docs/configuration/email.html
DISABLE_REGISTRATION=False
# DISABLE_REGISTRATION_MESSAGE=Registration is disabled for this instance of AdventureLog.
# Optional: Use email
# https://adventurelog.app/docs/configuration/email.html
# EMAIL_BACKEND=email # EMAIL_BACKEND=email
# EMAIL_HOST=smtp.gmail.com # EMAIL_HOST=smtp.mail.com
# EMAIL_USE_TLS=True # EMAIL_USE_TLS=False
# EMAIL_PORT=587 # EMAIL_PORT=587
# EMAIL_USE_SSL=False # EMAIL_USE_SSL=True
# EMAIL_HOST_USER=user # EMAIL_HOST_USER=user
# EMAIL_HOST_PASSWORD=password # EMAIL_HOST_PASSWORD=password
# DEFAULT_FROM_EMAIL=user@example.com # # EMAIL_HOST_PASSWORD_FILE=/run/secrets/email-host-password # Uncomment this block if you'd rather use docker secrets (more-secure)
# DEFAULT_FROM_EMAIL=adventurelog@example.com
# Optional: Use Umami for analytics ## Google Maps: https://adventurelog.app/docs/configuration/google_maps_integration.html
# https://adventurelog.app/docs/configuration/analytics.html # GOOGLE_MAPS_API_KEY=your_google_maps_api_key
## 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_SRC=https://cloud.umami.is/script.js # If you are using the hosted version of Umami
# PUBLIC_UMAMI_WEBSITE_ID= # PUBLIC_UMAMI_WEBSITE_ID=
# Extra configuration
DEBUG=false # Use to enable debugging

View file

@ -6,8 +6,8 @@ services:
ports: ports:
- "127.0.0.1:5432:5432" - "127.0.0.1:5432:5432"
environment: environment:
POSTGRES_DB: database POSTGRES_DB: adventurelog
POSTGRES_USER: adventure POSTGRES_USER: adventurelog
POSTGRES_PASSWORD: changeme123 POSTGRES_PASSWORD: changeme123
volumes: volumes:
- postgres_data:/var/lib/postgresql/data/ - postgres_data:/var/lib/postgresql/data/

View file

@ -36,11 +36,42 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:beta -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta ./backend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/$REPO_OWNER/$IMAGE_NAME:beta \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta \
./backend
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for backend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for backend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -35,12 +35,43 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: '${{ github.repository_owner }}' OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:latest -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest ./backend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/${{ steps.vars.outputs.REPO_OWNER }}/$IMAGE_NAME:latest \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest \
./backend
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for backend latest\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for backend latest\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -33,11 +33,43 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:${{ github.event.release.tag_name }} -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} ./backend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/${{ steps.vars.outputs.REPO_OWNER }}/$IMAGE_NAME:${{ github.event.release.tag_name }} \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} \
./backend
# # Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for backend release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for backend release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -37,10 +37,10 @@ jobs:
working-directory: backend/server working-directory: backend/server
env: env:
PGHOST: "127.0.0.1" PGHOST: "127.0.0.1"
PGDATABASE: "database" POSTGRES_DB: "adventurelog"
PGUSER: "adventure" POSTGRES_USER: "adventurelog"
PGPASSWORD: "changeme123" POSTGRES_PASSWORD: "changeme123"
SECRET_KEY: "changeme123" SECRET_KEY: "secretkey"
DJANGO_ADMIN_USERNAME: "admin" DJANGO_ADMIN_USERNAME: "admin"
DJANGO_ADMIN_PASSWORD: "admin" DJANGO_ADMIN_PASSWORD: "admin"
DJANGO_ADMIN_EMAIL: "admin@example.com" DJANGO_ADMIN_EMAIL: "admin@example.com"

View file

@ -36,11 +36,40 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:beta -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta ./cdn run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/${{ steps.vars.outputs.REPO_OWNER }}/$IMAGE_NAME:beta \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta \
./cdn
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for CDN beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for CDN beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -36,11 +36,40 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:latest -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest ./cdn run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/${{ steps.vars.outputs.REPO_OWNER }}/$IMAGE_NAME:latest \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest \
./cdn
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for CDN latest\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for CDN latest\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -33,11 +33,41 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:${{ github.event.release.tag_name }} -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} ./cdn run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/${{ steps.vars.outputs.REPO_OWNER }}/$IMAGE_NAME:${{ github.event.release.tag_name }} \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} \
./cdn
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for CDN release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for CDN release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -36,11 +36,42 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:beta -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta ./frontend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/$REPO_OWNER/$IMAGE_NAME:beta \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:beta \
./frontend
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for frontend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for frontend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -35,12 +35,43 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: '${{ github.repository_owner }}' OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:latest -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest ./frontend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/$REPO_OWNER/$IMAGE_NAME:latest \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:latest \
./frontend
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for frontend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for frontend beta\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

View file

@ -33,11 +33,42 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: set lower case owner name - name: Set build metadata
run: | id: vars
echo "REPO_OWNER=${OWNER,,}" >>${GITHUB_ENV}
env: env:
OWNER: "${{ github.repository_owner }}" OWNER: '${{ github.repository_owner }}'
run: |
echo "GIT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "GIT_TAG=$(git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo unknown)" >> $GITHUB_OUTPUT
echo "BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
echo "REPO_OWNER=${OWNER,,}" >> $GITHUB_OUTPUT
- name: Build Docker images - name: Build and push Docker images
run: docker buildx build --platform linux/amd64,linux/arm64 --push -t ghcr.io/$REPO_OWNER/$IMAGE_NAME:${{ github.event.release.tag_name }} -t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} ./frontend run: |
docker buildx build \
--platform linux/amd64,linux/arm64 \
--push \
--build-arg GIT_SHA=${{ steps.vars.outputs.GIT_SHA }} \
--build-arg GIT_TAG=${{ steps.vars.outputs.GIT_TAG }} \
--build-arg BUILD_DATE=${{ steps.vars.outputs.BUILD_DATE }} \
-t ghcr.io/$REPO_OWNER/$IMAGE_NAME:${{ github.event.release.tag_name }} \
-t ${{ secrets.DOCKERHUB_USERNAME }}/$IMAGE_NAME:${{ github.event.release.tag_name }} \
./frontend
# Notify on success
# - name: Notify Discord on success
# if: success()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"✅ Build and push succeeded for frontend release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}
# # Notify on failure
# - name: Notify Discord on failure
# if: failure()
# run: |
# curl -H "Content-Type: application/json" \
# -X POST \
# -d "{\"username\": \"CI Bot\", \"content\": \"❌ Build or push failed for frontend release ${{ github.event.release.tag_name }}\"}" \
# ${{ secrets.DISCORD_WEBHOOK_BUILD }}

1
.gitignore vendored
View file

@ -3,3 +3,4 @@
.vscode/settings.json .vscode/settings.json
.pnpm-store/ .pnpm-store/
.env .env
.secrets

7
backend/.dockerignore Normal file
View file

@ -0,0 +1,7 @@
.env.example
.devcontainer
.github
server/build_files.sh
.gitignore
Dockerfile
.dockerignore

View file

@ -1,7 +1,49 @@
# Use the official Python slim image as the base image # -------------------
FROM python:3.13-slim # Stage 1: Build Stage
# -------------------
FROM docker.io/python:3.13-alpine AS builder
# Build-time metadata
ARG GIT_SHA=unknown
ARG GIT_TAG=latest
ARG BUILD_DATE=unknown
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PYTHONPATH=/install
# Install build dependencies for Alpine
RUN apk add --no-cache \
build-base \
libpq \
libpq-dev \
gdal \
gdal-dev \
geos \
geos-dev \
postgresql-dev \
musl-dev \
python3-dev \
linux-headers \
git
# Set working directory
WORKDIR /build
# Copy entire project into /tmp
COPY . /tmp/
# Install Python dependencies into /install
RUN pip install --upgrade pip && \
pip install --target=/install -r /tmp/server/requirements.txt && \
python3 /tmp/server/manage.py collectstatic --noinput --verbosity 2
# -------------------------
# Stage 2: Final Production
# -------------------------
FROM docker.io/python:3.13-alpine AS final
# Metadata labels for the AdventureLog image
LABEL maintainer="Sean Morley" \ LABEL maintainer="Sean Morley" \
version="v0.10.0" \ version="v0.10.0" \
description="AdventureLog — the ultimate self-hosted travel companion." \ description="AdventureLog — the ultimate self-hosted travel companion." \
@ -12,49 +54,51 @@ LABEL maintainer="Sean Morley" \
org.opencontainers.image.url="https://raw.githubusercontent.com/seanmorley15/AdventureLog/refs/heads/main/brand/banner.png" \ org.opencontainers.image.url="https://raw.githubusercontent.com/seanmorley15/AdventureLog/refs/heads/main/brand/banner.png" \
org.opencontainers.image.source="https://github.com/seanmorley15/AdventureLog" \ org.opencontainers.image.source="https://github.com/seanmorley15/AdventureLog" \
org.opencontainers.image.vendor="Sean Morley" \ org.opencontainers.image.vendor="Sean Morley" \
org.opencontainers.image.created="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \ org.opencontainers.image.version="${GIT_TAG}" \
org.opencontainers.image.revision="${GIT_SHA}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.licenses="GPL-3.0" org.opencontainers.image.licenses="GPL-3.0"
# Set environment variables ENV PYTHONDONTWRITEBYTECODE=1 \
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 \
ENV PYTHONUNBUFFERED=1 PYTHONPATH="/install:/code" \
PATH="/install/bin:${PATH}" \
GDAL_LIBRARY_PATH="/usr/lib/libgdal.so.36.3.10.3" \
GEOS_LIBRARY_PATH="/usr/lib/libgeos_c.so"
# Set the working directory
# Copy all from builder, organize in one RUN step
COPY --from=builder /install /install
COPY --from=builder /tmp /tmp
RUN apk add --no-cache \
nginx\
supervisor\
bash\
curl\
libpq\
gdal\
gdal-dev\
geos\
geos-dev\
postgresql-client && \
mv /tmp/server /code && \
mkdir -p /code/static /code/media && \
mv /tmp/nginx.conf /etc/nginx/nginx.conf && \
mkdir -p /etc/supervisor/conf.d/ && \
mv /tmp/supervisord.conf /etc/supervisor/conf.d/supervisord.conf && \
mv /tmp/entrypoint.sh /code/entrypoint.sh && \
chmod +x /code/entrypoint.sh && \
rm -rf /tmp && \
addgroup -g 349 adventurelog && \
adduser -D -u 349 -G adventurelog adventurelog && \
chown -R 349:349 /code
WORKDIR /code WORKDIR /code
# Install system dependencies (Nginx included)
RUN apt-get update \
&& apt-get install -y git postgresql-client gdal-bin libgdal-dev nginx supervisor \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install Python dependencies
COPY ./server/requirements.txt /code/
RUN pip install --upgrade pip \
&& pip install -r requirements.txt
# Create necessary directories
RUN mkdir -p /code/static /code/media
# RUN mkdir -p /code/staticfiles /code/media
# Copy the Django project code into the Docker image
COPY ./server /code/
# Copy Nginx configuration
COPY ./nginx.conf /etc/nginx/nginx.conf
# Copy Supervisor configuration
COPY ./supervisord.conf /etc/supervisor/conf.d/supervisord.conf
# Collect static files
RUN python3 manage.py collectstatic --noinput --verbosity 2
# Set the entrypoint script
COPY ./entrypoint.sh /code/entrypoint.sh
RUN chmod +x /code/entrypoint.sh
# Expose ports for NGINX and Gunicorn
EXPOSE 80 8000 EXPOSE 80 8000
# Command to start Supervisor (which starts Nginx and Gunicorn) CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=5 \
CMD curl --fail --silent --show-error http://localhost:80/ || exit 1

View file

@ -1,4 +1,17 @@
#!/bin/bash #!/usr/bin/env bash
# Load environment variables from *_FILE if set
for file_var in $(env | grep -E '^[A-Z0-9_]+_FILE=' | sed -E 's/=.*//'); do
var_name="${file_var%_FILE}"
file_path="${!file_var}"
if [ -r "$file_path" ]; then
export "$var_name"="$(< "$file_path")"
unset "$file_var"
else
>&2 echo "Warning: Cannot read file for $file_var: $file_path"
fi
done
# Function to check PostgreSQL availability # Function to check PostgreSQL availability
# Helper to get the first non-empty environment variable # Helper to get the first non-empty environment variable
@ -13,22 +26,27 @@ get_env() {
} }
check_postgres() { check_postgres() {
if ! command -v psql > /dev/null 2>&1; then
>&2 echo "psql command not found — PostgreSQL client is not installed"
return 1
fi
local db_host local db_host
local db_user local db_user
local db_name local db_name
local db_pass local db_pass
db_host=$(get_env PGHOST) db_host="$(get_env PGHOST)"
db_user=$(get_env PGUSER POSTGRES_USER) db_user="$(get_env PGUSER POSTGRES_USER)"
db_name=$(get_env PGDATABASE POSTGRES_DB) db_name="$(get_env PGDATABASE POSTGRES_DB)"
db_pass=$(get_env PGPASSWORD POSTGRES_PASSWORD) db_pass="$(get_env PGPASSWORD POSTGRES_PASSWORD)"
PGPASSWORD="$db_pass" psql -h "$db_host" -U "$db_user" -d "$db_name" -c '\q' >/dev/null 2>&1 PGPASSWORD="$db_pass" psql -h "$db_host" -U "$db_user" -d "$db_name" -c '\q' >/dev/null 2>&1
} }
# Wait for PostgreSQL to become available # Wait for PostgreSQL to become available
until check_postgres; do until check_postgres; do
>&2 echo "PostgreSQL is unavailable - sleeping" >&2 echo "PostgreSQL is unavailable - sleeping"
sleep 1 sleep 1
done done
@ -73,8 +91,6 @@ else:
EOF EOF
fi fi
# Sync the countries and world travel regions
# Sync the countries and world travel regions # Sync the countries and world travel regions
python manage.py download-countries python manage.py download-countries
if [ $? -eq 137 ]; then if [ $? -eq 137 ]; then

View file

@ -1,36 +0,0 @@
PGHOST=''
PGDATABASE=''
PGUSER=''
PGPASSWORD=''
SECRET_KEY='pleasechangethisbecauseifyoudontitwillbeverybadandyouwillgethackedinlessthanaminuteguaranteed'
PUBLIC_URL='http://127.0.0.1:8000'
DEBUG=True
FRONTEND_URL='http://localhost:3000'
EMAIL_BACKEND='console'
# EMAIL_BACKEND='email'
# EMAIL_HOST='smtp.gmail.com'
# EMAIL_USE_TLS=False
# EMAIL_PORT=587
# EMAIL_USE_SSL=True
# EMAIL_HOST_USER='user'
# EMAIL_HOST_PASSWORD='password'
# DEFAULT_FROM_EMAIL='user@example.com'
# GOOGLE_MAPS_API_KEY='key'
# ------------------- #
# For Developers to start a Demo Database
# docker run --name adventurelog-development -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=admin -e POSTGRES_DB=adventurelog -p 5432:5432 -d postgis/postgis:15-3.3
# PGHOST='localhost'
# PGDATABASE='adventurelog'
# PGUSER='admin'
# PGPASSWORD='admin'
# ------------------- #

View file

@ -20,12 +20,19 @@ load_dotenv()
BASE_DIR = os.path.dirname(os.path.dirname(__file__)) BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# GDAL library version path
GDAL_LIBRARY_PATH = getenv('GDAL_LIBRARY_PATH', None)
# GEOS library version path
GEOS_LIBRARY_PATH = getenv('GEOS_LIBRARY_PATH', None)
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = getenv('SECRET_KEY') SECRET_KEY = getenv('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = getenv('DEBUG', 'true').lower() == 'true' DEBUG = getenv('DEBUG', 'true').lower() == 'true'

View file

@ -3,12 +3,14 @@ nodaemon=true
[program:nginx] [program:nginx]
command=/usr/sbin/nginx -g "daemon off;" command=/usr/sbin/nginx -g "daemon off;"
user=nginx
autorestart=true autorestart=true
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
[program:gunicorn] [program:gunicorn]
command=/code/entrypoint.sh command=/code/entrypoint.sh
user=adventurelog
autorestart=true autorestart=true
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr

View file

@ -1,7 +1,7 @@
# This script will create a backup of the adventurelog_media volume and store it in the current directory as adventurelog-backup.tar.gz # This script will create a backup of the adventurelog_media volume and store it in the current directory as adventurelog-backup.tar.gz
docker run --rm \ docker run --rm \
-v adventurelog_adventurelog_media:/backup-volume \ -v adventurelog_media:/backup-volume \
-v "$(pwd)":/backup \ -v "$(pwd)":/backup \
busybox \ busybox \
tar -zcvf /backup/adventurelog-backup.tar.gz /backup-volume tar -zcvf /backup/adventurelog-backup.tar.gz /backup-volume

View file

@ -1,36 +1,46 @@
# Use an official Python image as a base # ---------------------
FROM python:3.11-slim # Stage 1: Data builder
# ---------------------
FROM docker.io/python:3.11-slim AS builder
# Set the working directory ARG GIT_SHA=unknown
ARG BUILD_DATE=unknown
# Set workdir and environment
WORKDIR /app WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Install required Python packages # Install required Python packages
RUN pip install --no-cache-dir requests osm2geojson RUN pip install --no-cache-dir requests osm2geojson
# Copy the script into the container # Copy and run data generation script
COPY main.py /app/main.py COPY main.py /app/main.py
# Run the script to generate the data folder and GeoJSON files (this runs inside the container)
RUN python -u /app/main.py RUN python -u /app/main.py
# Install Nginx # ------------------------
RUN apt update && apt install -y nginx && rm -rf /var/lib/apt/lists/* # Stage 2: Final Nginx-only
# ------------------------
FROM docker.io/nginx:alpine
# Copy the entire generated data folder to the Nginx serving directory ARG GIT_SHA=unknown
RUN mkdir -p /var/www/html/data && cp -r /app/data/* /var/www/html/data/ ARG BUILD_DATE=unknown
# Copy Nginx configuration # Optional metadata
LABEL org.opencontainers.image.revision="${GIT_SHA}" \
org.opencontainers.image.created="${BUILD_DATE}"
# Create destination directory
RUN mkdir -p /var/www/html/data
# Copy generated data and static files
COPY --from=builder /app/data /var/www/html/data
COPY index.html /usr/share/nginx/html/index.html
COPY nginx.conf /etc/nginx/nginx.conf COPY nginx.conf /etc/nginx/nginx.conf
# Copy the index.html file to the Nginx serving directory # Add entrypoint
COPY index.html /usr/share/nginx/html/index.html
# Expose port 80 for Nginx
EXPOSE 80
# Copy the entrypoint script into the container
COPY entrypoint.sh /app/entrypoint.sh COPY entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh
# Set the entrypoint script as the default command EXPOSE 80
ENTRYPOINT ["/app/entrypoint.sh"] ENTRYPOINT ["/app/entrypoint.sh"]

View file

@ -5,4 +5,4 @@ docker compose pull
echo "Stating containers" echo "Stating containers"
docker compose up -d docker compose up -d
echo "All set!" echo "All set!"
docker logs adventurelog-backend --follow docker compose logs --follow

View file

@ -1,78 +0,0 @@
version: "3.9"
services:
traefik:
image: traefik:v2.11
command:
- "--api.insecure=true" # Enable Traefik dashboard (remove in production)
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.letsencrypt.acme.email=your-email@example.com" # Replace with your email
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "traefik-letsencrypt:/letsencrypt"
labels:
- "traefik.enable=true"
db:
image: postgis/postgis:15-3.3
restart: unless-stopped
environment:
POSTGRES_DB: database
POSTGRES_USER: adventure
POSTGRES_PASSWORD: your_postgres_password # Replace with the actual password
volumes:
- postgres-data:/var/lib/postgresql/data/
web:
image: ghcr.io/seanmorley15/adventurelog-frontend:latest
restart: unless-stopped
environment:
PUBLIC_SERVER_URL: "http://server:8000"
BODY_SIZE_LIMIT: "100000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.adventurelogweb.entrypoints=websecure"
- "traefik.http.routers.adventurelogweb.rule=Host(`yourdomain.com`) && !(PathPrefix(`/media`) || PathPrefix(`/admin`) || PathPrefix(`/static`) || PathPrefix(`/accounts`))" # Replace with your domain
- "traefik.http.routers.adventurelogweb.tls=true"
- "traefik.http.routers.adventurelogweb.tls.certresolver=letsencrypt"
depends_on:
- server
server:
image: ghcr.io/seanmorley15/adventurelog-backend:latest
restart: unless-stopped
environment:
PGHOST: "db"
PGDATABASE: "database"
PGUSER: "adventure"
PGPASSWORD: your_postgres_password # Replace with the actual password
SECRET_KEY: your_secret_key # Replace with the actual secret key
DJANGO_ADMIN_USERNAME: "admin"
DJANGO_ADMIN_PASSWORD: your_admin_password # Replace with the actual admin password
DJANGO_ADMIN_EMAIL: "adventurelog-admin@yourdomain.com" # Replace with your email
PUBLIC_URL: "https://yourdomain.com" # Replace with your domain
CSRF_TRUSTED_ORIGINS: "https://yourdomain.com" # Replace with your domain
DEBUG: "false"
FRONTEND_URL: "https://yourdomain.com" # Replace with your domain
volumes:
- adventurelog-media:/code/media
labels:
- "traefik.enable=true"
- "traefik.http.routers.adventurelogserver.entrypoints=websecure"
- "traefik.http.routers.adventurelogserver.rule=Host(`yourdomain.com`) && (PathPrefix(`/media`) || PathPrefix(`/admin`) || PathPrefix(`/static`) || PathPrefix(`/accounts`))" # Replace with your domain
- "traefik.http.routers.adventurelogserver.tls=true"
- "traefik.http.routers.adventurelogserver.tls.certresolver=letsencrypt"
depends_on:
- db
volumes:
postgres-data:
adventurelog-media:
traefik-letsencrypt:

View file

@ -1,36 +1,149 @@
name: adventurelog
# Common DB variables used by both backend and db
x-env-common: &env-common
POSTGRES_DB: adventurelog
POSTGRES_USER: adventurelog
POSTGRES_PASSWORD: changeme123
# POSTGRES_PASSWORD_FILE: /run/secrets/postgres-password # Uncomment this block if you'd rather use docker secrets (more-secure)
# Environment variables for the backend service
x-env-backend: &env-backend
# Database Configuration
PGHOST: db # Supposed to match the host of the postgis database
<<: *env-common
# AdventureLog base configuration
SECRET_KEY: changeme123 # Replace with the actual secret key
# SECRET_KEY_FILE: /run/secrets/secret-key # Uncomment this block if you'd rather use docker secrets (more-secure)
DJANGO_ADMIN_USERNAME: admin # Replace with the actual admin username
DJANGO_ADMIN_PASSWORD: admin # Replace with the actual admin password
# DJANGO_ADMIN_PASSWORD_FILE: /run/secrets/django-admin-password # Uncomment this block if you'd rather use docker secrets (more-secure)
DJANGO_ADMIN_EMAIL: admin@example.com # Replace with the actual admin email
BACKEND_PORT: 8016 # Don't forget to update CSRF_TRUSTED_ORIGINS and PUBLIC_URL in backend, and PUBLIC_SERVER_URL in frontend if you make changes to this.
PUBLIC_URL: http://localhost:8016 # Replace with your domain where the backend is accessible publicly, used for the creation of image URLs
CSRF_TRUSTED_ORIGINS: http://localhost:8016,http://localhost:8015 # Replace with your domain, if applicable
FRONTEND_URL: http://localhost:8015 # Replace with your domain where the frontend is accessible, used for email generation.
# Optional integrations (commented out by default)
# DISABLE_REGISTRATION: False
# DISABLE_REGISTRATION_MESSAGE: Registration is disabled for this instance of AdventureLog.
# EMAIL_BACKEND: email
# EMAIL_HOST: smtp.mail.com
# EMAIL_USE_TLS: False
# EMAIL_PORT: 587
# EMAIL_USE_SSL: True
# EMAIL_HOST_USER: user
# EMAIL_HOST_PASSWORD: password
# # EMAIL_HOST_PASSWORD_FILE: /run/secrets/email-host-password # Uncomment this block if you'd rather use docker secrets (more-secure)
# DEFAULT_FROM_EMAIL: adventurelog@example.com
# GOOGLE_MAPS_API_KEY: your_google_maps_api_key
# PUBLIC_UMAMI_SRC: https://cloud.umami.is/script.js # If you are using the hosted version of Umami
# PUBLIC_UMAMI_WEBSITE_ID:
# Extra configuration
DEBUG: false # Use to enable debugging
# Environment variables for the frontend service
x-env-frontend: &env-frontend
FRONTEND_PORT: 8015 # Don't forget to update CSRF_TRUSTED_ORIGINS in backend and FRONTEND_URL in backend and ORIGIN in frontend if you make changes to this.
PUBLIC_SERVER_URL: http://backend: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
BODY_SIZE_LIMIT: Infinity
services: services:
web:
#build: ./frontend/
image: ghcr.io/seanmorley15/adventurelog-frontend:latest
container_name: adventurelog-frontend
restart: unless-stopped
env_file: .env
ports:
- "${FRONTEND_PORT:-8015}:3000"
depends_on:
- server
db: db:
image: postgis/postgis:16-3.5 image: docker.io/postgis/postgis:16-3.5
container_name: adventurelog-db
restart: unless-stopped restart: unless-stopped
env_file: .env #env_file: .env # Disabled for security reasons, as all containers have access to these env vars.
environment: # Anything defined here (including the env-backend) overrides what's in the env_file.
<<: *env-common
volumes: volumes:
- postgres_data:/var/lib/postgresql/data/ - data:/var/lib/postgresql/data/
# secrets: # Uncomment this block if you'd rather use docker secrets (more-secure)
# - postgres-password
networks:
- default
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
interval: 20s
timeout: 10s
retries: 5
start_period: 10s
server: frontend:
#build: ./backend/ #build: ./frontend/
image: ghcr.io/seanmorley15/adventurelog-backend:latest image: localhost/adventurelog-frontend:testing
container_name: adventurelog-backend
restart: unless-stopped restart: unless-stopped
env_file: .env # env_file: .env # Disabled for security reasons, as all containers have access to these env vars.
environment: # Anything defined here (including the env-backend) overrides what's in the env_file.
<<: *env-frontend
ports: ports:
- "${BACKEND_PORT:-8016}:80" - "8015:3000"
networks:
- default
depends_on: depends_on:
- db backend:
condition: service_healthy
healthcheck:
test: ["CMD", "/nodejs/bin/node", "-e", "require('net').connect(3000).on('connect', () => process.exit(0)).on('error', () => process.exit(1))"]
interval: 10s
timeout: 3s
retries: 3
start_period: 10s
# labels:
# Traefik example: Refer to https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/ for help on deploying Traefik.
# - "traefik.enable=true"
# - "traefik.http.routers.adventurelogweb.entrypoints=websecure"
# - "traefik.http.routers.adventurelogweb.rule=Host(`yourdomain.com`) && !(PathPrefix(`/media`) || PathPrefix(`/admin`) || PathPrefix(`/static`) || PathPrefix(`/accounts`))" # Replace with your domain
# - "traefik.http.routers.adventurelogweb.tls=true"
# - "traefik.http.routers.adventurelogweb.tls.certresolver=letsencrypt"
backend:
#build: ./backend/
image: localhost/adventurelog-backend:testing
restart: unless-stopped
# env_file: .env # Disabled for security reasons, as all containers have access to these env vars.
environment: # Anything defined here (including the env-backend) overrides what's in the env_file.
<<: *env-backend
networks:
- default
ports:
- "8016:80"
depends_on:
db:
condition: service_healthy
volumes: volumes:
- adventurelog_media:/code/media/ - media:/code/media/
# secrets: # Uncomment this block if you'd rather use docker secrets (more-secure)
# - postgres-password
# - secret-key
# # - email-host-password
# - django-admin-password
healthcheck:
test: ["CMD", "curl", "--fail", "--silent", "--show-error", "http://localhost:80/"]
interval: 30s
timeout: 10s
start_period: 20s
retries: 5
# labels:
# Traefik example: Refer to https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/ for help on deploying Traefik.
# - "traefik.enable=true"
# - "traefik.http.routers.adventurelogserver.entrypoints=websecure"
# - "traefik.http.routers.adventurelogserver.rule=Host(`yourdomain.com`) && (PathPrefix(`/media`) || PathPrefix(`/admin`) || PathPrefix(`/static`) || PathPrefix(`/accounts`))" # Replace with your domain
# - "traefik.http.routers.adventurelogserver.tls=true"
# - "traefik.http.routers.adventurelogserver.tls.certresolver=letsencrypt"
volumes: volumes:
postgres_data: data:
adventurelog_media: media:
# secrets: # Uncomment this block if you'd rather use docker secrets (more-secure)
# postgres-password:
# file: .secrets/postgres-password.secret
# secret-key:
# file: .secrets/secret-key.secret
# # email-host-password: # Uncomment this if you want to use secrets with the email host password
# # file: .secrets/email-host-password.secret
# django-admin-password:
# file: .secrets/django-admin-password.secret

View file

@ -2,7 +2,7 @@
Docker is the preferred way to run AdventureLog on your local machine. It is a lightweight containerization technology that allows you to run applications in isolated environments called containers. Docker is the preferred way to run AdventureLog on your local machine. It is a lightweight containerization technology that allows you to run applications in isolated environments called containers.
> **Note**: This guide mainly focuses on installation with a Linux-based host machine, but the steps are similar for other operating systems. > **Note**: This guide mainly focuses on installation with a Linux-based host machine, but the steps are similar for other operating systems or when using Podman.
## Prerequisites ## Prerequisites
@ -29,30 +29,22 @@ If running on an ARM based machine, you will need to use a different PostGIS Ima
## Configuration ## Configuration
The `.env` file contains all the configuration settings for your AdventureLog instance. Heres a breakdown of each section: The `docker-compose.yml` file contains all the configuration settings for your AdventureLog instance. Heres a breakdown of each environment variable (at the top of the file):
### 🌐 Frontend (web)
| 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` |
| `BODY_SIZE_LIMIT` | Yes | Maximum upload size in bytes. | `Infinity` |
| `FRONTEND_PORT` | Yes | Port that the frontend will run on inside Docker. | `8015` |
### 🐘 PostgreSQL Database ### 🐘 PostgreSQL Database
| Name | Required | Description | Default Value | | Name | Required | Description | Default Value |
| ------------------- | -------- | --------------------- | ------------- | | ------------------- | -------- | --------------------- | ------------- |
| `PGHOST` | Yes | Internal DB hostname. | `db` | | `PGHOST` | Yes | Internal DB hostname. | `db` |
| `POSTGRES_DB` | Yes | DB name. | `database` | | `POSTGRES_DB` | Yes | DB name. | `adventurelog` |
| `POSTGRES_USER` | Yes | DB user. | `adventure` | | `POSTGRES_USER` | Yes | DB user. | `adventurelog` |
| `POSTGRES_PASSWORD` | Yes | DB password. | `changeme123` | | `POSTGRES_PASSWORD` | Yes | DB password. | `changeme123` |
### 🔒 Backend (server) ### 🔒 Backend (server)
| Name | Required | Description | Default Value | | Name | Required | Description | Default Value |
| ----------------------- | -------- | ---------------------------------------------------------------------------------- | --------------------------------------------- | | ----------------------- | -------- | ---------------------------------------------------------------------------------- | --------------------------------------------- |
| `PHHOST` | Yes | The hostname of the postgres container. | `pg` |
| `SECRET_KEY` | Yes | Django secret key. Change this in production! | `changeme123` | | `SECRET_KEY` | Yes | Django secret key. Change this in production! | `changeme123` |
| `DJANGO_ADMIN_USERNAME` | Yes | Default Django admin username. | `admin` | | `DJANGO_ADMIN_USERNAME` | Yes | Default Django admin username. | `admin` |
| `DJANGO_ADMIN_PASSWORD` | Yes | Default Django admin password. | `admin` | | `DJANGO_ADMIN_PASSWORD` | Yes | Default Django admin password. | `admin` |
@ -63,6 +55,15 @@ The `.env` file contains all the configuration settings for your AdventureLog in
| `BACKEND_PORT` | Yes | Port that the backend will run on inside Docker. | `8016` | | `BACKEND_PORT` | Yes | Port that the backend will run on inside Docker. | `8016` |
| `DEBUG` | No | Should be `False` in production. | `False` | | `DEBUG` | No | Should be `False` in production. | `False` |
### 🌐 Frontend (web)
| 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://backend: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` |
| `BODY_SIZE_LIMIT` | Yes | Maximum upload size in bytes. | `Infinity` |
| `FRONTEND_PORT` | Yes | Port that the frontend will run on inside Docker. | `8015` |
## Optional Configuration ## Optional Configuration
- [Disable Registration](../configuration/disable_registration.md) - [Disable Registration](../configuration/disable_registration.md)
@ -71,9 +72,50 @@ The `.env` file contains all the configuration settings for your AdventureLog in
- [Immich Integration](../configuration/immich_integration.md) - [Immich Integration](../configuration/immich_integration.md)
- [Umami Analytics](../configuration/analytics.md) - [Umami Analytics](../configuration/analytics.md)
## Additional Configuration Methods
### Secret Files
If you're not comfortable storing sensitive values like `SECRET_KEY` or any `PASSWORD` directly in the environment file, you can either use Docker secrets or bind-mount a text file containing the secret value. In this case, append `_FILE` to the environment variable name and set its value to the file path.
For example, instead of:
```yml
SECRET_KEY: your_secret_value
```
You can use:
```yml
SECRET_KEY_FILE: /run/secrets/secret_key # For a docker secret
SECRET_KEY_FILE: /some/directory/secret_key # For a volume bind mount
```
Make sure the any secret files are **not** committed to version control to keep your secrets safe.
### .env File
If you prefer not to hardcode sensitive values like `SECRET_KEY` or any `PASSWORD` directly in your `docker-compose.yml` file, you can reference them from a `.env` file. Docker Compose will automatically read this file and substitute the values into your configuration. An example .env file is found [on GitHub](https://github.com/seanmorley15/AdventureLog/blob/main/.env.example).
For example, in your `.env` file:
```
SECRET\_KEY=your\_secret\_value
````
And in your `docker-compose.yml`:
```yaml
environment:
- SECRET_KEY=${SECRET_KEY}
````
Make sure the `.env` file is **not** committed to version control to keep your secrets safe.
## Running the Containers ## Running the Containers
Once you've configured `.env`, you can start AdventureLog with: Once you've configured `docker-compose.yml`, you can start AdventureLog with:
```bash ```bash
docker compose up -d docker compose up -d

View file

@ -5,7 +5,7 @@ Install **AdventureLog** in seconds using our automated script.
## 🧪 One-Liner Install ## 🧪 One-Liner Install
```bash ```bash
curl -sSL https://get.adventurelog.app | bash bash -c "$(curl -sSL https://get.adventurelog.app)"
``` ```
This will: This will:
@ -27,7 +27,7 @@ This will:
The script automatically: The script automatically:
1. Verifies Docker is installed and running 1. Verifies Docker is installed and running
2. Downloads `docker-compose.yml` and `.env` 2. Downloads `docker-compose.yml`
3. Prompts you for domain and port settings 3. Prompts you for domain and port settings
4. Waits for services to start 4. Waits for services to start
5. Prints success info with next steps 5. Prints success info with next steps

View file

@ -4,4 +4,4 @@ Traefik is a modern HTTP reverse proxy and load balancer that makes deploying mi
AdventureLog has a built-in Traefik configuration that makes it easy to deploy and manage your AdventureLog instance. AdventureLog has a built-in Traefik configuration that makes it easy to deploy and manage your AdventureLog instance.
The most recent version of the Traefik `docker-compose.yml` file can be found in the [AdventureLog GitHub repository](https://github.com/seanmorley15/AdventureLog/blob/main/docker-compose-traefik.yaml). The most recent version of [docker-compose.yml](https://github.com/seanmorley15/AdventureLog/blob/main/docker-compose.yml) file includes example Traefik container labels. To deploy Traefik itself, consult the [Traefik v3.x documentation](https://doc.traefik.io/traefik/).

6
frontend/.dockerignore Normal file
View file

@ -0,0 +1,6 @@
.env.example
.prettierignore
.prettierrc
.gitignore
Dockerfile
.dockerignore

View file

@ -1,7 +0,0 @@
PUBLIC_SERVER_URL=http://127.0.0.1:8000
BODY_SIZE_LIMIT=Infinity
# OPTIONAL VARIABLES FOR UMAMI ANALYTICS
PUBLIC_UMAMI_SRC=
PUBLIC_UMAMI_WEBSITE_ID=

View file

@ -1,49 +1,65 @@
# Use this image as the platform to build the app # ----------------------
FROM node:22-alpine AS external-website # Stage 1: Build the app
# ----------------------
FROM docker.io/node:22-alpine AS builder
ARG GIT_SHA=unknown
ARG GIT_TAG=latest
ARG BUILD_DATE=unknown
# Set working directory
WORKDIR /app
COPY . ./
# Install pnpm globally
RUN npm install -g pnpm && \
pnpm install --frozen-lockfile && \
rm -f .env && \
pnpm run build && \
mv /app/package.json /app/build/package.json;\
ls -lah .; \
ls -lah ./build
# ----------------------------
# Stage 2: Install Production Dependencies
# ----------------------------
FROM docker.io/node:22-alpine AS deps
WORKDIR /app
COPY --from=builder /app/build/package.json ./
RUN npm install --omit=dev && \
addgroup -g 349 adventurelog && \
adduser -D -u 349 -G adventurelog adventurelog && \
chown -R 349:349 /app
# ----------------------------
# Stage 3: Distroless Runtime
# ----------------------------
FROM gcr.io/distroless/nodejs20
# Metadata labels for the AdventureLog image
LABEL maintainer="Sean Morley" \ LABEL maintainer="Sean Morley" \
version="v0.10.0" \
description="AdventureLog — the ultimate self-hosted travel companion." \
org.opencontainers.image.title="AdventureLog" \ org.opencontainers.image.title="AdventureLog" \
org.opencontainers.image.description="AdventureLog is a self-hosted travel companion that helps you plan, track, and share your adventures." \ org.opencontainers.image.description="AdventureLog is a self-hosted travel companion that helps you plan, track, and share your adventures." \
org.opencontainers.image.version="v0.10.0" \
org.opencontainers.image.authors="Sean Morley" \ org.opencontainers.image.authors="Sean Morley" \
org.opencontainers.image.url="https://raw.githubusercontent.com/seanmorley15/AdventureLog/refs/heads/main/brand/banner.png" \ org.opencontainers.image.url="https://raw.githubusercontent.com/seanmorley15/AdventureLog/refs/heads/main/brand/banner.png" \
org.opencontainers.image.source="https://github.com/seanmorley15/AdventureLog" \ org.opencontainers.image.source="https://github.com/seanmorley15/AdventureLog" \
org.opencontainers.image.vendor="Sean Morley" \ org.opencontainers.image.vendor="Sean Morley" \
org.opencontainers.image.created="$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \ org.opencontainers.image.version="${GIT_TAG}" \
org.opencontainers.image.revision="${GIT_SHA}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.licenses="GPL-3.0" org.opencontainers.image.licenses="GPL-3.0"
# The WORKDIR instruction sets the working directory for everything that will happen next USER 349:349
WORKDIR /app WORKDIR /app
# Install pnpm globally first COPY --from=builder /etc/passwd /etc/passwd
RUN npm install -g pnpm COPY --from=builder /etc/group /etc/group
COPY --from=builder /app/build ./
COPY --from=deps /app/node_modules ./node_modules
# Copy package files first for better Docker layer caching CMD ["index.js"]
COPY package.json pnpm-lock.yaml* ./
# Clean install all node modules using pnpm with frozen lockfile
RUN pnpm install --frozen-lockfile
# Copy the rest of the application files
COPY . .
# Remove the development .env file if present
RUN rm -f .env
# Build SvelteKit app
RUN pnpm run build
# Make startup script executable
RUN chmod +x ./startup.sh
# Change to non-root user for security
USER node:node
# Expose the port that the app is listening on
EXPOSE 3000 EXPOSE 3000
# Run startup.sh instead of the default command HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
CMD ["./startup.sh"] CMD /nodejs/bin/node -e "require('net').connect(3000).on('connect', () => process.exit(0)).on('error', () => process.exit(1))"

View file

@ -1,5 +0,0 @@
#!/bin/sh
echo "The origin to be set is: $ORIGIN"
# Start the application
ORIGIN=$ORIGIN exec node build

View file

@ -1,4 +1,4 @@
#!/bin/bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
# ============================================================================= # =============================================================================
@ -20,6 +20,16 @@ declare -g ADMIN_PASSWORD=""
declare -g DB_PASSWORD="" declare -g DB_PASSWORD=""
declare -g FRONTEND_PORT="" declare -g FRONTEND_PORT=""
declare -g BACKEND_PORT="" declare -g BACKEND_PORT=""
declare -g TRAEFIK_ENABLED=""
declare -g USE_EMAIL=""
declare -g USE_DOCKER_SECRETS=""
declare -g EMAIL_HOST=""
declare -g EMAIL_USE_TLS=""
declare -g EMAIL_PORT=""
declare -g EMAIL_USE_SSL=""
declare -g EMAIL_HOST_USER=""
declare -g EMAIL_HOST_PASSWORD=""
declare -g FINISHED_CORRECTLY="true"
# Color codes for beautiful output # Color codes for beautiful output
readonly RED='\033[0;31m' readonly RED='\033[0;31m'
@ -56,6 +66,11 @@ log_header() {
echo -e "${PURPLE}$1${NC}" echo -e "${PURPLE}$1${NC}"
} }
# pause(){
# read -s -n 1 -p "Press any key to continue . . ."
# echo ""
# }
print_banner() { print_banner() {
cat << 'EOF' cat << 'EOF'
╔═════════════════════════════════════════════════════════════════════════╗ ╔═════════════════════════════════════════════════════════════════════════╗
@ -183,18 +198,11 @@ check_dependencies() {
log_info "Checking system dependencies..." log_info "Checking system dependencies..."
local missing_deps=() local missing_deps=()
for bin in curl docker docker-compose tr sed; do
if ! command -v curl &>/dev/null; then if ! command -v "$bin" >/dev/null 2>&1; then
missing_deps+=("curl") missing_deps+=("$bin")
fi fi
done
if ! command -v docker &>/dev/null; then
missing_deps+=("docker")
fi
if ! command -v docker-compose &>/dev/null && ! docker compose version &>/dev/null; then
missing_deps+=("docker-compose")
fi
if [ ${#missing_deps[@]} -ne 0 ]; then if [ ${#missing_deps[@]} -ne 0 ]; then
log_error "Missing dependencies: ${missing_deps[*]}" log_error "Missing dependencies: ${missing_deps[*]}"
@ -205,6 +213,12 @@ check_dependencies() {
"curl") "curl")
echo " • curl: apt-get install curl (Ubuntu/Debian) or brew install curl (macOS)" echo " • curl: apt-get install curl (Ubuntu/Debian) or brew install curl (macOS)"
;; ;;
"tr")
echo " • curl: apt-get install coreutils (Ubuntu/Debian) and should be installed by default on macOS"
;;
"sed")
echo " • curl: apt-get install sed (Ubuntu/Debian) or brew install gnu-sed (macOS)"
;;
"docker") "docker")
echo " • Docker: https://docs.docker.com/get-docker/" echo " • Docker: https://docs.docker.com/get-docker/"
;; ;;
@ -282,12 +296,93 @@ download_files() {
exit 1 exit 1
fi fi
log_success "docker-compose.yml downloaded" log_success "docker-compose.yml downloaded"
}
if ! curl -fsSL --connect-timeout 10 --max-time 30 "$ENV_FILE_URL" -o .env; then
log_error "Failed to download .env template" prompt_email_configuration() {
exit 1 echo ""
fi log_header "📧 SMTP Email Configuration"
log_success ".env template downloaded" echo ""
echo "Please enter the required SMTP settings for sending emails from AdventureLog."
echo ""
# SMTP Host
while true; do
read -r -p "📨 SMTP Host: " EMAIL_HOST
if [[ -n "$EMAIL_HOST" ]]; then
break
else
log_error "SMTP Host cannot be empty."
fi
done
# Use TLS
while true; do
read -r -p "🔐 Use TLS? (y/n): " input_tls
case "${input_tls,,}" in
y | yes)
EMAIL_USE_TLS=true
break
;;
n | no)
EMAIL_USE_TLS=false
break
;;
*)
log_error "Invalid input. Please enter y or n."
;;
esac
done
# Use SSL
while true; do
read -r -p "🔐 Use SSL? (y/n): " input_ssl
case "${input_ssl,,}" in
y | yes)
EMAIL_USE_SSL=true
break
;;
n | no)
EMAIL_USE_SSL=false
break
;;
*)
log_error "Invalid input. Please enter y or n."
;;
esac
done
# SMTP Port
while true; do
read -r -p "🔌 SMTP Port: " EMAIL_PORT
if [[ "$EMAIL_PORT" =~ ^[0-9]+$ ]]; then
break
else
log_error "Please enter a valid numeric port."
fi
done
# SMTP Username
while true; do
read -r -p "👤 SMTP Username: " EMAIL_HOST_USER
if [[ -n "$EMAIL_HOST_USER" ]]; then
break
else
log_error "SMTP Username cannot be empty."
fi
done
# SMTP Password
while true; do
read -r -s -p "🔑 SMTP Password: " EMAIL_HOST_PASSWORD
echo
if [[ -n "$EMAIL_HOST_PASSWORD" ]]; then
break
else
log_error "Passwords do not match or are empty. Please try again."
fi
done
log_success "SMTP configuration completed."
} }
prompt_configuration() { prompt_configuration() {
@ -333,233 +428,330 @@ prompt_configuration() {
# Check port availability # Check port availability
check_port_availability "$FRONTEND_PORT" "frontend" check_port_availability "$FRONTEND_PORT" "frontend"
check_port_availability "$BACKEND_PORT" "backend" check_port_availability "$BACKEND_PORT" "backend"
while true; do
read -r -p "🚦 Use SMTP email with AdventureLog? (Y/n): " input_email
case "${input_email,,}" in
y | yes | "")
USE_EMAIL=true
prompt_email_configuration
break
;;
n | no)
USE_EMAIL=false
break
;;
*)
log_error "Invalid input. Please enter Y or N."
;;
esac
done
log_success "Using SMTP email with AdventureLog?: $USE_EMAIL"
while true; do
read -r -p "🚦 Enable Traefik labels? (Y/n): " input_traefik
case "${input_traefik,,}" in
y | yes | "")
TRAEFIK_ENABLED=true
break
;;
n | no)
TRAEFIK_ENABLED=false
break
;;
*)
log_error "Invalid input. Please enter Y or N."
;;
esac
done
log_success "Traefik enabled?: $TRAEFIK_ENABLED"
while true; do
read -r -p "🚦 Use docker secrets, which is more secure? (Y/n): " input_secrets
case "${input_secrets,,}" in
y | yes | "")
USE_DOCKER_SECRETS=true
break
;;
n | no)
USE_DOCKER_SECRETS=false
break
;;
*)
log_error "Invalid input. Please enter Y or N."
;;
esac
done
log_success "Using Docker Secrets enabled?: $USE_DOCKER_SECRETS"
echo "" echo ""
} }
configure_environment_fallback() {
log_info "Using simple configuration approach..."
# Generate simple passwords using a basic method
DB_PASSWORD="$(date +%s | sha256sum | base64 | head -c 32)"
ADMIN_PASSWORD="$(date +%s | sha256sum | base64 | head -c 24)"
log_info "Generated passwords using fallback method"
# Create backup
cp .env .env.backup
# Use simple string replacement with perl if available
if command -v perl &>/dev/null; then
log_info "Using perl for configuration..."
# Fix: Update BOTH password variables for database consistency
perl -pi -e "s/^POSTGRES_PASSWORD=.*/POSTGRES_PASSWORD=$DB_PASSWORD/" .env
perl -pi -e "s/^DATABASE_PASSWORD=.*/DATABASE_PASSWORD=$DB_PASSWORD/" .env
perl -pi -e "s/^DJANGO_ADMIN_PASSWORD=.*/DJANGO_ADMIN_PASSWORD=$ADMIN_PASSWORD/" .env
perl -pi -e "s|^ORIGIN=.*|ORIGIN=$FRONTEND_ORIGIN|" .env
perl -pi -e "s|^PUBLIC_URL=.*|PUBLIC_URL=$BACKEND_URL|" .env
perl -pi -e "s|^CSRF_TRUSTED_ORIGINS=.*|CSRF_TRUSTED_ORIGINS=$FRONTEND_ORIGIN,$BACKEND_URL|" .env
perl -pi -e "s|^FRONTEND_URL=.*|FRONTEND_URL=$FRONTEND_ORIGIN|" .env
# Add port configuration
perl -pi -e "s/^FRONTEND_PORT=.*/FRONTEND_PORT=$FRONTEND_PORT/" .env
perl -pi -e "s/^BACKEND_PORT=.*/BACKEND_PORT=$BACKEND_PORT/" .env
# Add port variables if they don't exist
if ! grep -q "^FRONTEND_PORT=" .env; then
echo "FRONTEND_PORT=$FRONTEND_PORT" >> .env
fi
if ! grep -q "^BACKEND_PORT=" .env; then
echo "BACKEND_PORT=$BACKEND_PORT" >> .env
fi
if grep -q "POSTGRES_PASSWORD=$DB_PASSWORD" .env; then
log_success "Configuration completed successfully"
return 0
fi
fi
# Manual approach - create .env from scratch with key variables
log_info "Creating minimal .env configuration..."
cat > .env << EOF
# Database Configuration
POSTGRES_DB=adventurelog
POSTGRES_USER=adventurelog
POSTGRES_PASSWORD=$DB_PASSWORD
DATABASE_PASSWORD=$DB_PASSWORD
# Django Configuration
DJANGO_ADMIN_USERNAME=admin
DJANGO_ADMIN_PASSWORD=$ADMIN_PASSWORD
SECRET_KEY=$(openssl rand -base64 32 2>/dev/null || echo "change-this-secret-key-$(date +%s)")
# URL Configuration
ORIGIN=$FRONTEND_ORIGIN
PUBLIC_URL=$BACKEND_URL
FRONTEND_URL=$FRONTEND_ORIGIN
CSRF_TRUSTED_ORIGINS=$FRONTEND_ORIGIN,$BACKEND_URL
# Port Configuration
FRONTEND_PORT=$FRONTEND_PORT
BACKEND_PORT=$BACKEND_PORT
# Additional Settings
DEBUG=False
EOF
log_success "Created minimal .env configuration"
return 0
}
configure_environment() { configure_environment() {
log_info "Generating secure configuration..." log_info "Verifying required tools..."
# Debug: Test password generation first for cmd in tr sed cp grep wc mkdir; do
log_info "Testing password generation..." if ! command -v "$cmd" &>/dev/null; then
if ! command -v tr &>/dev/null; then log_error "$cmd is required but not found."
log_error "tr command not found - required for password generation" exit 1
exit 1 fi
fi done
# Generate secure passwords with error checking log_info "Generating secure secrets..."
log_info "Generating database password..."
DB_PASSWORD=$(generate_secure_password 32) DB_PASSWORD=$(generate_secure_password 32)
if [[ -z "$DB_PASSWORD" ]]; then
log_error "Failed to generate database password"
exit 1
fi
log_success "Database password generated (${#DB_PASSWORD} characters)"
log_info "Generating admin password..."
ADMIN_PASSWORD=$(generate_secure_password 24) ADMIN_PASSWORD=$(generate_secure_password 24)
if [[ -z "$ADMIN_PASSWORD" ]]; then SECRET_KEY=$(generate_secure_password 50)
log_error "Failed to generate admin password"
if [[ -z "$DB_PASSWORD" || -z "$ADMIN_PASSWORD" || -z "$SECRET_KEY" ]]; then
log_error "❌ Failed to generate secure credentials"
exit 1 exit 1
fi fi
log_success "Admin password generated (${#ADMIN_PASSWORD} characters)"
log_success "✅ Secrets generated: DB(${#DB_PASSWORD}), Admin(${#ADMIN_PASSWORD}), Key(${#SECRET_KEY})"
# Debug: Check if .env file exists and is readable
log_info "Checking .env file..." FRONTEND_PORT="${FRONTEND_PORT:-8015}"
if [[ ! -f ".env" ]]; then BACKEND_PORT="${BACKEND_PORT:-8016}"
log_error ".env file not found" FRONTEND_ORIGIN="${FRONTEND_ORIGIN:-"http://localhost:$FRONTEND_PORT"}"
BACKEND_URL="${BACKEND_URL:-"http://localhost:$BACKEND_PORT"}"
CSRF_TRUSTED="$BACKEND_URL,$FRONTEND_ORIGIN"
if [[ ! -f "docker-compose.yml" ]]; then
log_error "docker-compose.yml not found"
exit 1 exit 1
fi fi
if [[ ! -r ".env" ]]; then cp docker-compose.yml docker-compose.yml.bak || {
log_error ".env file is not readable" log_error "Failed to back up docker-compose.yml"
exit 1 exit 1
fi }
log_info "File check passed - .env exists and is readable ($(wc -l < .env) lines)" log_info "Applying configuration to docker-compose.yml..."
# Try fallback method first (simpler and more reliable) # Handle Docker secrets if enabled
log_info "Attempting configuration..." if [[ "$USE_DOCKER_SECRETS" == "true" ]]; then
if configure_environment_fallback; then log_info "Enabling Docker secrets..."
return 0
fi mkdir -p .secrets
log_warning "Fallback method failed, trying advanced processing..." # Save secrets to files
echo "$DB_PASSWORD" > .secrets/postgres-password.secret || FINISHED_CORRECTLY=false
# Fallback to bash processing echo "$SECRET_KEY" > .secrets/secret-key.secret || FINISHED_CORRECTLY=false
# Create backup of original .env echo "$ADMIN_PASSWORD" > .secrets/django-admin-password.secret || FINISHED_CORRECTLY=false
cp .env .env.backup
# Uncomment secret references in docker-compose.yml
# Create a new .env file by processing the original line by line sed -i '' -E \
local temp_file=".env.temp" -e 's/^([[:space:]]*)#[[:space:]]*(secrets:)/\1\2/' \
local processed_lines=0 -e 's/^([[:space:]]*)#[[:space:]]*( - postgres-password)/\1\2/' \
local updated_lines=0 -e 's/^([[:space:]]*)#[[:space:]]*( - secret-key)/\1\2/' \
-e 's/^([[:space:]]*)#[[:space:]]*( - django-admin-password)/\1\2/' \
while IFS= read -r line || [[ -n "$line" ]]; do -e 's/^([[:space:]]*)#[[:space:]]*#( - email-host-password)/\1# \2/' \
((processed_lines++)) -e 's/^([[:space:]]*)#[[:space:]](secrets:[[:space:]]*#.*)/\1\2/' \
case "$line" in -e 's/^([[:space:]]*)#[[:space:]]*(postgres-password:)/\1 \2/' \
POSTGRES_PASSWORD=*) -e 's/^([[:space:]]*)#[[:space:]]*(file: .secrets\/postgres-password\.secret)/\1 \2/' \
echo "POSTGRES_PASSWORD=$DB_PASSWORD" -e 's/^([[:space:]]*)#[[:space:]]*(secret-key:)/\1 \2/' \
((updated_lines++)) -e 's/^([[:space:]]*)#[[:space:]]*(file: .secrets\/secret-key\.secret)/\1 \2/' \
;; -e 's/^([[:space:]]*)#[[:space:]]*#[[:space:]]*(email-host-password:)/\1 # \2/' \
DATABASE_PASSWORD=*) -e 's/^([[:space:]]*)#[[:space:]]*#[[:space:]]*(file: .secrets\/email-host-password\.secret)/\1 # \2/' \
echo "DATABASE_PASSWORD=$DB_PASSWORD" -e 's/^([[:space:]]*)#[[:space:]]*(django-admin-password:)/\1 \2/' \
((updated_lines++)) -e 's/^([[:space:]]*)#[[:space:]]*(file: .secrets\/django-admin-password\.secret)/\1 \2/' \
;; docker-compose.yml || FINISHED_CORRECTLY=false
DJANGO_ADMIN_PASSWORD=*) # for swapping normal variables to secrets
echo "DJANGO_ADMIN_PASSWORD=$ADMIN_PASSWORD" awk '
((updated_lines++)) {
;; lines[NR] = $0
ORIGIN=*)
echo "ORIGIN=$FRONTEND_ORIGIN" # Match lines like: [whitespace]#[whitespace]VARIABLE_FILE:
((updated_lines++)) if ($0 ~ /^[[:space:]]*#[[:space:]]*[A-Z0-9_]+_FILE:/) {
;; line = $0
PUBLIC_URL=*) indent = line
echo "PUBLIC_URL=$BACKEND_URL" sub(/[^[:space:]]+.*/, "", indent) # Get leading whitespace
((updated_lines++))
;; # Remove leading `#` and any spaces after
CSRF_TRUSTED_ORIGINS=*) sub(/^[[:space:]]*#[[:space:]]*/, "", line)
echo "CSRF_TRUSTED_ORIGINS=$FRONTEND_ORIGIN,$BACKEND_URL" split(line, parts, ":")
((updated_lines++)) split(parts[1], name_parts, "_FILE")
;; varname = name_parts[1]
FRONTEND_URL=*)
echo "FRONTEND_URL=$FRONTEND_ORIGIN" uncomment_line[NR] = indent line
((updated_lines++)) comment_var[varname] = 1
;; }
FRONTEND_PORT=*) }
echo "FRONTEND_PORT=$FRONTEND_PORT" END {
((updated_lines++)) for (i = 1; i <= NR; i++) {
;; line = lines[i]
BACKEND_PORT=*)
echo "BACKEND_PORT=$BACKEND_PORT" # Replace commented *_FILE line with uncommented version (with indent)
((updated_lines++)) if (i in uncomment_line) {
;; print uncomment_line[i]
*) continue
echo "$line" }
;;
esac # Comment out original VARIABLE: line if a *_FILE was found
done < .env > "$temp_file" if (line ~ /^[[:space:]]*[A-Z0-9_]+:/) {
indent = line
# Add port variables if they weren't found in the original file sub(/[^[:space:]]+.*/, "", indent)
if ! grep -q "^FRONTEND_PORT=" "$temp_file"; then split(line, parts, ":")
echo "FRONTEND_PORT=$FRONTEND_PORT" >> "$temp_file" var = parts[1]
((updated_lines++)) gsub(/^[[:space:]]*/, "", var)
fi
if ! grep -q "^BACKEND_PORT=" "$temp_file"; then if (var in comment_var) {
echo "BACKEND_PORT=$BACKEND_PORT" >> "$temp_file" print indent "# " substr(line, length(indent)+1)
((updated_lines++)) continue
fi }
}
log_info "Processed $processed_lines lines, updated $updated_lines configuration values"
# Default: print line as-is
# Check if temp file was created successfully print line
if [[ ! -f "$temp_file" ]]; then }
log_error "Failed to create temporary configuration file" }
exit 1 ' docker-compose.yml > docker-compose.yml.tmp && {
fi mv docker-compose.yml.tmp docker-compose.yml
} || FINISHED_CORRECTLY=false
# Replace the original .env with the configured one
if mv "$temp_file" .env; then # Handle email password secret comments
log_success "Environment configured with secure passwords and port settings" awk '
{
lines[NR] = $0
}
END {
for (i = 1; i <= NR; i++) {
line1 = lines[i]
line2 = lines[i + 1]
# Match: line1 = single-commented VAR, line2 = double-commented VAR_FILE
if (line1 ~ /^[[:space:]]*#[[:space:]]*[A-Z0-9_]+:[[:space:]]*/ &&
line2 ~ /^[[:space:]]*#[[:space:]]*#[[:space:]]*[A-Z0-9_]+_FILE:/) {
# Extract indent from line1
indent1 = line1
sub(/[^[:space:]]+.*/, "", indent1)
# Clean VAR line for recommenting
clean1 = line1
gsub(/^[[:space:]]*#[[:space:]]*/, "", clean1)
# Print double-commented VAR line
print indent1 "# # " clean1
# Extract indent from line2
indent2 = line2
sub(/[^[:space:]]+.*/, "", indent2)
# Clean VAR_FILE line to single-comment
clean2 = line2
gsub(/^[[:space:]]*#[[:space:]]*/, "", clean2) # Remove first #
gsub(/^[[:space:]]*#[[:space:]]*/, "", clean2) # Remove second #
# Print single-commented VAR_FILE line
print indent2 "# " clean2
i++ # Skip next line since we just processed it
continue
}
# Default: print original line
print lines[i]
}
}
' docker-compose.yml > docker-compose.yml.tmp && {
mv docker-compose.yml.tmp docker-compose.yml
} || FINISHED_CORRECTLY=false
log_success "Docker secrets configured"
else else
log_error "Failed to replace .env file" # Default env var replacements (no secrets)
log_info "Restoring backup and exiting" sed -i '' -E \
mv .env.backup .env -e "s|^([[:space:]]*POSTGRES_PASSWORD:).*|\1 $DB_PASSWORD|" \
rm -f "$temp_file" -e "s|^([[:space:]]*DJANGO_ADMIN_PASSWORD:).*|\1 $ADMIN_PASSWORD|" \
-e "s|^([[:space:]]*SECRET_KEY:).*|\1 $SECRET_KEY|" \
-e "s|^([[:space:]]*EMAIL_HOST_PASSWORD:).*|\1 $EMAIL_HOST_PASSWORD|" \
docker-compose.yml || FINISHED_CORRECTLY=false
# if [[ "$USE_EMAIL" == "true" ]]; then
# fi
fi
# Handle email config if enabled
if [[ "$USE_EMAIL" == "true" ]]; then
log_info "Enabling email configuration..."
sed -i '' -E \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_BACKEND:).*/\1\2 email/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_HOST:).*/\1\2 $EMAIL_HOST/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_USE_TLS:).*/\1\2 $EMAIL_USE_TLS/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_PORT:).*/\1\2 $EMAIL_PORT/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_USE_SSL:).*/\1\2 $EMAIL_USE_SSL/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_HOST_USER:).*/\1\2 $EMAIL_HOST_USER/" \
docker-compose.yml || FINISHED_CORRECTLY=false
if [[ "$USE_DOCKER_SECRETS" == "true" ]]; then
sed -i '' -E \
-e "s/^([[:space:]]*)#[[:space:]]*(# EMAIL_HOST_PASSWORD:).*/\1\2/" \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_HOST_PASSWORD_FILE:).*/\1\2 \/run\/secrets\/email-host-password/" \
-e "s/^([[:space:]]*)#[[:space:]]*(- email-host-password)/\1 \2/" \
-e "s/^([[:space:]]*)#[[:space:]]*(email-host-password:)/\1\2/" \
-e "s/^([[:space:]]*)#[[:space:]]*(file: .secrets\/email-host-password\.secret)/\1 \2/" \
docker-compose.yml || FINISHED_CORRECTLY=false
else
sed -i '' -E \
-e "s/^([[:space:]]*)#[[:space:]]*(EMAIL_HOST_PASSWORD:).*/\1\2 $EMAIL_HOST_PASSWORD/" \
docker-compose.yml || FINISHED_CORRECTLY=false
fi
log_success "Email configuration applied"
fi
# Replace other standard values
sed -i '' -E \
-e "s|^( *BACKEND_PORT:).*|\1 $BACKEND_PORT|" \
-e "s|^( *FRONTEND_PORT:).*|\1 $FRONTEND_PORT|" \
-e "s|^( *PUBLIC_URL:).*|\1 $BACKEND_URL|" \
-e "s|^( *FRONTEND_URL:).*|\1 $FRONTEND_ORIGIN|" \
-e "s|^( *ORIGIN:).*|\1 $FRONTEND_ORIGIN|" \
-e "s|^( *CSRF_TRUSTED_ORIGINS:).*|\1 $CSRF_TRUSTED|" \
-e "s|([[:space:]]+-[[:space:]]*\")([0-9]+)(:3000\")|\1$FRONTEND_PORT\3|" \
-e "s|([[:space:]]+-[[:space:]]*\")([0-9]+)(:80\")|\1$BACKEND_PORT\3|" \
docker-compose.yml || FINISHED_CORRECTLY=false
if [[ "$TRAEFIK_ENABLED" == "true" ]]; then
sed -i '' -E \
-e 's/^([[:space:]]*)#([[:space:]]*labels:)/\1 \2/' \
-e 's/^([[:space:]]*)#([[:space:]]*-?[[:space:]]*"traefik\..*")/\1 \2/' \
docker-compose.yml || FINISHED_CORRECTLY=false
fi
if [[ "$FINISHED_CORRECTLY" == "false" ]]; then
log_error "configuration failed"
log_info "Restoring backup..."
mv docker-compose.yml.bak docker-compose.yml
exit 1 exit 1
fi fi
# Verify critical configuration was applied log_success "docker-compose.yml updated"
if grep -q "POSTGRES_PASSWORD=$DB_PASSWORD" .env && (grep -q "DATABASE_PASSWORD=$DB_PASSWORD" .env || grep -q "POSTGRES_PASSWORD=$DB_PASSWORD" .env); then
log_success "Configuration verification passed - database password variables set" log_info "🔍 Verifying updated values in docker-compose.yml:"
diff -y docker-compose.yml.bak docker-compose.yml || :
# Basic verification of values present
if [[ "$USE_DOCKER_SECRETS" == "false" ]]; then
if grep -q "$DB_PASSWORD" docker-compose.yml && grep -q "$FRONTEND_PORT" docker-compose.yml && grep -q "$BACKEND_PORT" docker-compose.yml; then
log_success "✅ Configuration verification passed"
else
log_warning "⚠️ Some configuration values may not have applied properly"
log_info "Restoring backup for safety... (renaming auto-configured docker-compose.yml to docker-compose.yml.install)"
mv docker-compose.yml docker-compose.yml.install
mv docker-compose.yml.bak docker-compose.yml
exit 1
fi
else else
log_error "Configuration verification failed - database passwords not properly configured" if grep -q "postgres-password" docker-compose.yml && grep -q "$FRONTEND_PORT" docker-compose.yml && grep -q "$BACKEND_PORT" docker-compose.yml; then
log_info "Showing database-related lines in .env for debugging:" log_success "✅ Configuration verification passed"
grep -E "(POSTGRES_PASSWORD|DATABASE_PASSWORD)" .env | while read -r line; do else
echo " $line" log_warning "⚠️ Some configuration values may not have applied properly"
done log_info "Restoring backup for safety... (renaming auto-configured docker-compose.yml to docker-compose.yml.install)"
mv .env.backup .env mv docker-compose.yml docker-compose.yml.install
exit 1 mv docker-compose.yml.bak docker-compose.yml
fi exit 1
fi
# Verify port configuration
if grep -q "FRONTEND_PORT=$FRONTEND_PORT" .env && grep -q "BACKEND_PORT=$BACKEND_PORT" .env; then
log_success "Port configuration verified - frontend: $FRONTEND_PORT, backend: $BACKEND_PORT"
else
log_warning "Port configuration may not be complete - check .env file manually"
fi fi
} }

View file

@ -1,78 +1,63 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: example-name name: adventurelog
labels: labels:
app: adventure app: adventurelog
spec: spec:
replicas: 1 replicas: 1
selector: selector:
matchLabels: matchLabels:
app: adventure app: adventurelog
template: template:
metadata: metadata:
name: adventure
labels: labels:
app: adventure app: adventurelog
spec: spec:
volumes: volumes:
- name: adventure-journal - name: media
persistentVolumeClaim: persistentVolumeClaim:
claimName: adventure-journal-pvc claimName: media-pvc
- name: adventure-journal-db - name: data
persistentVolumeClaim: persistentVolumeClaim:
claimName: adventure-journal-db-pvc claimName: data-pvc
containers: containers:
- name: adventure-frontend - name: frontend
image: ghcr.io/seanmorley15/adventurelog-frontend:latest image: ghcr.io/seanmorley15/adventurelog-frontend:latest
imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 3000 - containerPort: 3000
env: env:
- name: FRONTEND_PORT
value: "8015"
- name: PUBLIC_SERVER_URL - name: PUBLIC_SERVER_URL
value: "http://internally-and-externally.reachable.io:80" value: "http://backend:8000"
- name: ORIGIN - name: ORIGIN
value: "http://url-typed-into-browser.io:80" value: "http://localhost:8015"
- name: BODY_SIZE_LIMIT - name: BODY_SIZE_LIMIT
value: "Infinity" value: "Infinity"
readinessProbe:
exec:
command: ["/nodejs/bin/node", "-e", "require('net').connect(3000).on('connect', () => process.exit(0)).on('error', () => process.exit(1))"]
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
- name: adventure-db - name: backend
image: postgis/postgis:15-3.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
volumeMounts:
- name: adventure-journal-db
mountPath: /var/lib/postgresql/data
env:
- name: POSTGRES_DB
value: database
- name: PGDATA
value: /var/lib/postgresql/data/pgdata/subdir
- name: POSTGRES_USER
value: adventure
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: adventurelog-secret
key: adventure-postgres-password
- name: adventure-backend
image: ghcr.io/seanmorley15/adventurelog-backend:latest image: ghcr.io/seanmorley15/adventurelog-backend:latest
imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 80 - containerPort: 80
- containerPort: 8000 - containerPort: 8000
volumeMounts: volumeMounts:
- name: adventure-journal - name: media
mountPath: /code/media mountPath: /code/media
env: env:
- name: PGHOST - name: PGHOST
value: "adventure-db-svc" value: "db"
- name: PGDATABASE - name: POSTGRES_DB
value: "database" value: "adventurelog"
- name: PGUSER - name: POSTGRES_USER
value: "adventure" value: "adventurelog"
- name: PGPASSWORD - name: PGPASSWORD
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
@ -82,58 +67,101 @@ spec:
valueFrom: valueFrom:
secretKeyRef: secretKeyRef:
name: adventurelog-secret name: adventurelog-secret
key: adventure-postgres-password key: secret-key
- name: PUBLIC_URL
value: "http://internally-and-externally.reachable.io:80" # Match the outward port, used for the creation of image urls
- name: FRONTEND_URL
value: "http://url-typed-into-browser.io:80"
- name: CSRF_TRUSTED_ORIGINS
value: "http://url-typed-into-browser.io:80, http://internally-and-externally.reachable.io:80"
- name: DJANGO_ADMIN_USERNAME - name: DJANGO_ADMIN_USERNAME
value: "admin" value: "admin"
- name: DJANGO_ADMIN_PASSWORD - name: DJANGO_ADMIN_PASSWORD
value: "admin" value: "admin"
- name: DJANGO_ADMIN_EMAIL - name: DJANGO_ADMIN_EMAIL
value: "admin@example.com" value: "admin@example.com"
- name: BACKEND_PORT
value: "8016"
- name: PUBLIC_URL
value: "http://localhost:8016"
- name: FRONTEND_URL
value: "http://localhost:8015"
- name: CSRF_TRUSTED_ORIGINS
value: "http://localhost:8016,http://localhost:8015"
- name: DEBUG - name: DEBUG
value: "True" value: "false"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 20
periodSeconds: 30
timeoutSeconds: 10
failureThreshold: 5
- name: db
image: postgis/postgis:16-3.5
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
env:
- name: POSTGRES_DB
value: "adventurelog"
- name: POSTGRES_USER
value: "adventurelog"
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: adventurelog-secret
key: adventure-postgres-password
readinessProbe:
exec:
command: ["pg_isready", "-U", "adventurelog"]
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 10
failureThreshold: 5
restartPolicy: Always restartPolicy: Always
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: adventure-db-svc name: backend
spec: spec:
selector: selector:
app: adventure app: adventurelog
ports: ports:
- name: db - name: http
protocol: TCP port: 80
port: 5432 targetPort: 80
targetPort: 5432 - name: backend
port: 8000
targetPort: 8000
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
name: server name: frontend
spec: spec:
selector: selector:
app: adventure app: adventurelog
ports: ports:
- name: http - name: http
protocol: TCP port: 3000
port: 80 targetPort: 3000
targetPort: 80 ---
- name: base apiVersion: v1
protocol: TCP kind: Service
port: 8000 metadata:
targetPort: 8000 name: db
spec:
selector:
app: adventurelog
ports:
- name: postgres
port: 5432
targetPort: 5432
--- ---
# If you aren't automatically provisioning PVCs (i.e. with Longhorn, you'll need to also create the PV's)
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: adventure-journal-pvc name: media-pvc
spec: spec:
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
@ -144,10 +172,19 @@ spec:
apiVersion: v1 apiVersion: v1
kind: PersistentVolumeClaim kind: PersistentVolumeClaim
metadata: metadata:
name: adventure-journal-db-pvc name: data-pvc
spec: spec:
accessModes: accessModes:
- ReadWriteOnce - ReadWriteOnce
resources: resources:
requests: requests:
storage: 10Gi storage: 10Gi
---
apiVersion: v1
kind: Secret
metadata:
name: adventurelog-secret
type: Opaque
stringData:
adventure-postgres-password: changeme123
secret-key: changeme123