mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-05 05:05:17 +02:00
feat(devsecops): updated installer to utilize new docker-compose format
This commit is contained in:
parent
2ee4b2a4d4
commit
bc9a9a631d
5 changed files with 467 additions and 236 deletions
|
@ -6,14 +6,17 @@ BODY_SIZE_LIMIT=Infinity
|
||||||
|
|
||||||
# 🐘 PostgreSQL Database
|
# 🐘 PostgreSQL Database
|
||||||
PGHOST=db # Supposed to match the host of the postgis database
|
PGHOST=db # Supposed to match the host of the postgis database
|
||||||
POSTGRES_DB=adventureloga
|
POSTGRES_DB=adventurelog
|
||||||
POSTGRES_USER=adventurelog
|
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 # Replace with the actual secret key
|
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_USERNAME=admin # Replace with the actual admin username
|
||||||
DJANGO_ADMIN_PASSWORD=admin # Replace with the actual admin password
|
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
|
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.
|
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
|
PUBLIC_URL=http://localhost:8016 # Replace with your domain where the backend is accessible publicly, used for the creation of image urls
|
||||||
|
@ -33,6 +36,7 @@ FRONTEND_URL=http://localhost:8015 # Replace with your domain where the frontend
|
||||||
# EMAIL_USE_SSL=True
|
# EMAIL_USE_SSL=True
|
||||||
# EMAIL_HOST_USER=user
|
# EMAIL_HOST_USER=user
|
||||||
# EMAIL_HOST_PASSWORD=password
|
# 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
|
# DEFAULT_FROM_EMAIL=adventurelog@example.com
|
||||||
|
|
||||||
## Google Maps: https://adventurelog.app/docs/configuration/google_maps_integration.html
|
## Google Maps: https://adventurelog.app/docs/configuration/google_maps_integration.html
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
.pnpm-store/
|
.pnpm-store/
|
||||||
.env
|
.env
|
||||||
|
.secrets
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
#!/usr/bin/env 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
|
||||||
get_env() {
|
get_env() {
|
||||||
|
|
|
@ -2,9 +2,10 @@ name: adventurelog
|
||||||
|
|
||||||
# Common DB variables used by both backend and db
|
# Common DB variables used by both backend and db
|
||||||
x-env-common: &env-common
|
x-env-common: &env-common
|
||||||
POSTGRES_DB: adventurelog # If you change this, it needs to also be changed in the backend
|
POSTGRES_DB: adventurelog
|
||||||
POSTGRES_USER: adventurelog # If you change this, it needs to also be changed in the backend
|
POSTGRES_USER: adventurelog
|
||||||
POSTGRES_PASSWORD: changeme123 # If you change this, it needs to also be changed in the backend
|
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
|
# Environment variables for the backend service
|
||||||
x-env-backend: &env-backend
|
x-env-backend: &env-backend
|
||||||
|
@ -13,8 +14,10 @@ x-env-backend: &env-backend
|
||||||
<<: *env-common
|
<<: *env-common
|
||||||
# AdventureLog base configuration
|
# AdventureLog base configuration
|
||||||
SECRET_KEY: changeme123 # Replace with the actual secret key
|
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_USERNAME: admin # Replace with the actual admin username
|
||||||
DJANGO_ADMIN_PASSWORD: admin # Replace with the actual admin password
|
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
|
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.
|
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
|
PUBLIC_URL: http://localhost:8016 # Replace with your domain where the backend is accessible publicly, used for the creation of image URLs
|
||||||
|
@ -31,7 +34,8 @@ x-env-backend: &env-backend
|
||||||
# EMAIL_USE_SSL: True
|
# EMAIL_USE_SSL: True
|
||||||
# EMAIL_HOST_USER: user
|
# EMAIL_HOST_USER: user
|
||||||
# EMAIL_HOST_PASSWORD: password
|
# EMAIL_HOST_PASSWORD: password
|
||||||
# DEFAULT_FROM_EMAIL: ${COMPOSE_PROJECT_NAME@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
|
||||||
# GOOGLE_MAPS_API_KEY: your_google_maps_api_key
|
# 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_SRC: https://cloud.umami.is/script.js # If you are using the hosted version of Umami
|
||||||
# PUBLIC_UMAMI_WEBSITE_ID:
|
# PUBLIC_UMAMI_WEBSITE_ID:
|
||||||
|
@ -55,6 +59,8 @@ services:
|
||||||
<<: *env-common
|
<<: *env-common
|
||||||
volumes:
|
volumes:
|
||||||
- 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:
|
networks:
|
||||||
- default
|
- default
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
@ -109,6 +115,11 @@ services:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
volumes:
|
volumes:
|
||||||
- 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:
|
healthcheck:
|
||||||
test: ["CMD", "curl", "--fail", "--silent", "--show-error", "http://localhost:80/"]
|
test: ["CMD", "curl", "--fail", "--silent", "--show-error", "http://localhost:80/"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
|
@ -126,3 +137,13 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue