maybe good
This commit is contained in:
44
scripts/backup.sh
Executable file
44
scripts/backup.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# Backup script for Delphi Database System
|
||||
|
||||
set -e
|
||||
|
||||
BACKUP_DIR="/app/backups"
|
||||
DB_FILE="/app/data/delphi_database.db"
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
BACKUP_FILE="${BACKUP_DIR}/delphi_backup_${TIMESTAMP}.db"
|
||||
|
||||
echo "🔄 Starting database backup..."
|
||||
|
||||
# Create backup directory if it doesn't exist
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Check if database exists
|
||||
if [ ! -f "$DB_FILE" ]; then
|
||||
echo "❌ Database file not found: $DB_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create backup
|
||||
echo "📦 Creating backup: $BACKUP_FILE"
|
||||
cp "$DB_FILE" "$BACKUP_FILE"
|
||||
|
||||
# Verify backup
|
||||
if [ -f "$BACKUP_FILE" ]; then
|
||||
BACKUP_SIZE=$(stat -f%z "$BACKUP_FILE" 2>/dev/null || stat -c%s "$BACKUP_FILE" 2>/dev/null)
|
||||
echo "✅ Backup created successfully"
|
||||
echo " File: $BACKUP_FILE"
|
||||
echo " Size: $BACKUP_SIZE bytes"
|
||||
else
|
||||
echo "❌ Backup failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up old backups (keep last 10)
|
||||
echo "🧹 Cleaning up old backups..."
|
||||
find "$BACKUP_DIR" -name "delphi_backup_*.db" -type f | sort -r | tail -n +11 | xargs -r rm -f
|
||||
|
||||
REMAINING_BACKUPS=$(find "$BACKUP_DIR" -name "delphi_backup_*.db" -type f | wc -l)
|
||||
echo "📊 Remaining backups: $REMAINING_BACKUPS"
|
||||
|
||||
echo "🎉 Backup process completed!"
|
||||
116
scripts/git-pre-commit-hook
Executable file
116
scripts/git-pre-commit-hook
Executable file
@@ -0,0 +1,116 @@
|
||||
#!/bin/bash
|
||||
# Pre-commit hook for Delphi Consulting Group Database System
|
||||
# Prevents committing sensitive files and data
|
||||
#
|
||||
# To install: ln -s ../../scripts/git-pre-commit-hook .git/hooks/pre-commit
|
||||
|
||||
set -e
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[0;32m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${GREEN}🔍 Running security pre-commit checks...${NC}"
|
||||
|
||||
# Flag to track if any issues found
|
||||
ISSUES_FOUND=0
|
||||
|
||||
# Function to report security issue
|
||||
report_issue() {
|
||||
echo -e "${RED}❌ SECURITY ISSUE: $1${NC}"
|
||||
ISSUES_FOUND=1
|
||||
}
|
||||
|
||||
# Function to report warning
|
||||
report_warning() {
|
||||
echo -e "${YELLOW}⚠️ WARNING: $1${NC}"
|
||||
}
|
||||
|
||||
# Check for .env files
|
||||
if git diff --cached --name-only | grep -E "\.env$|\.env\." > /dev/null; then
|
||||
report_issue "Environment files (.env) contain secrets and should not be committed!"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "\.env$|\.env\.")"
|
||||
fi
|
||||
|
||||
# Check for database files
|
||||
if git diff --cached --name-only | grep -E "\.(db|sqlite|sqlite3)$" > /dev/null; then
|
||||
report_issue "Database files contain sensitive data and should not be committed!"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "\.(db|sqlite|sqlite3)$")"
|
||||
fi
|
||||
|
||||
# Check for backup files
|
||||
if git diff --cached --name-only | grep -E "\.(backup|bak|dump)$|backups/" > /dev/null; then
|
||||
report_issue "Backup files may contain sensitive data and should not be committed!"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "\.(backup|bak|dump)$|backups/")"
|
||||
fi
|
||||
|
||||
# Check for SSL certificates and keys
|
||||
if git diff --cached --name-only | grep -E "\.(pem|key|crt|cert|p12|pfx)$" > /dev/null; then
|
||||
report_issue "SSL certificates and private keys should not be committed!"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "\.(pem|key|crt|cert|p12|pfx)$")"
|
||||
fi
|
||||
|
||||
# Check for upload directories
|
||||
if git diff --cached --name-only | grep -E "uploads/|user-uploads/" > /dev/null; then
|
||||
report_issue "Upload directories may contain sensitive user documents!"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "uploads/|user-uploads/")"
|
||||
fi
|
||||
|
||||
# Check for local configuration files
|
||||
if git diff --cached --name-only | grep -E "\-local\.|config\.local|settings\.local" > /dev/null; then
|
||||
report_warning "Local configuration files detected - ensure they don't contain secrets"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "\-local\.|config\.local|settings\.local")"
|
||||
fi
|
||||
|
||||
# Check for common secret patterns in staged files
|
||||
SECRET_PATTERNS=(
|
||||
"password\s*=\s*['\"][^'\"]+['\"]"
|
||||
"api_key\s*=\s*['\"][^'\"]+['\"]"
|
||||
"secret_key\s*=\s*['\"][^'\"]+['\"]"
|
||||
"token\s*=\s*['\"][^'\"]+['\"]"
|
||||
"-----BEGIN (RSA )?PRIVATE KEY-----"
|
||||
"-----BEGIN CERTIFICATE-----"
|
||||
)
|
||||
|
||||
for pattern in "${SECRET_PATTERNS[@]}"; do
|
||||
if git diff --cached | grep -qiE "$pattern"; then
|
||||
report_warning "Potential secret detected in staged changes"
|
||||
echo " Pattern: $pattern"
|
||||
echo " Review your changes carefully!"
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for large files (may be database dumps or uploads)
|
||||
LARGE_FILES=$(git diff --cached --name-only | xargs -I {} stat -f%z {} 2>/dev/null | awk '$1 > 1048576 {count++} END {print count+0}')
|
||||
if [ "$LARGE_FILES" -gt 0 ]; then
|
||||
report_warning "$LARGE_FILES large files detected (>1MB) - ensure they're not sensitive data"
|
||||
fi
|
||||
|
||||
# Check for Python cache files (should be in .gitignore but double-check)
|
||||
if git diff --cached --name-only | grep -E "__pycache__|\.pyc$" > /dev/null; then
|
||||
report_warning "Python cache files detected - these should be in .gitignore"
|
||||
echo " Files: $(git diff --cached --name-only | grep -E "__pycache__|\.pyc$")"
|
||||
fi
|
||||
|
||||
# If any security issues found, prevent commit
|
||||
if [ $ISSUES_FOUND -eq 1 ]; then
|
||||
echo -e "${RED}🚫 COMMIT BLOCKED: Security issues detected!${NC}"
|
||||
echo ""
|
||||
echo "To fix:"
|
||||
echo "1. Remove sensitive files from staging: git reset HEAD <filename>"
|
||||
echo "2. Add files to .gitignore if needed"
|
||||
echo "3. Use environment variables for secrets"
|
||||
echo "4. Run: python scripts/setup-security.py for proper configuration"
|
||||
echo ""
|
||||
echo "To bypass this check (NOT RECOMMENDED): git commit --no-verify"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Show summary
|
||||
echo -e "${GREEN}✅ Pre-commit security checks passed!${NC}"
|
||||
echo "📝 Staged files: $(git diff --cached --name-only | wc -l)"
|
||||
|
||||
# Success - allow commit to proceed
|
||||
exit 0
|
||||
76
scripts/init-container.sh
Executable file
76
scripts/init-container.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash
|
||||
# Initialization script for Delphi Database System Docker container
|
||||
|
||||
set -e
|
||||
|
||||
echo "🚀 Initializing Delphi Consulting Group Database System..."
|
||||
|
||||
# Create necessary directories
|
||||
mkdir -p /app/data /app/uploads /app/backups /app/exports /app/logs
|
||||
|
||||
# Set permissions
|
||||
chmod 755 /app/data /app/uploads /app/backups /app/exports
|
||||
chmod 750 /app/logs
|
||||
|
||||
# Check if database exists
|
||||
if [ ! -f "/app/data/delphi_database.db" ]; then
|
||||
echo "📊 Database not found. Creating new database..."
|
||||
|
||||
# Initialize database tables
|
||||
python -c "
|
||||
from app.database.base import engine
|
||||
from app.models import BaseModel
|
||||
BaseModel.metadata.create_all(bind=engine)
|
||||
print('✅ Database tables created successfully')
|
||||
"
|
||||
|
||||
# Check if we should create admin user
|
||||
if [ "${CREATE_ADMIN_USER}" = "true" ]; then
|
||||
echo "👤 Creating default admin user..."
|
||||
python -c "
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from app.database.base import engine
|
||||
from app.models.user import User
|
||||
from app.auth.security import get_password_hash
|
||||
import os
|
||||
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
db = SessionLocal()
|
||||
|
||||
try:
|
||||
# Check if admin already exists
|
||||
existing_admin = db.query(User).filter(User.username == 'admin').first()
|
||||
if not existing_admin:
|
||||
admin_user = User(
|
||||
username=os.getenv('ADMIN_USERNAME', 'admin'),
|
||||
email=os.getenv('ADMIN_EMAIL', 'admin@delphicg.local'),
|
||||
full_name=os.getenv('ADMIN_FULLNAME', 'System Administrator'),
|
||||
hashed_password=get_password_hash(os.getenv('ADMIN_PASSWORD', 'admin123')),
|
||||
is_active=True,
|
||||
is_admin=True
|
||||
)
|
||||
db.add(admin_user)
|
||||
db.commit()
|
||||
print('✅ Default admin user created')
|
||||
print(f' Username: {admin_user.username}')
|
||||
print(f' Email: {admin_user.email}')
|
||||
print(' Password: See ADMIN_PASSWORD environment variable')
|
||||
else:
|
||||
print('ℹ️ Admin user already exists, skipping creation')
|
||||
finally:
|
||||
db.close()
|
||||
"
|
||||
fi
|
||||
else
|
||||
echo "✅ Database found, skipping initialization"
|
||||
fi
|
||||
|
||||
# Run database migrations if needed (future feature)
|
||||
# echo "🔄 Running database migrations..."
|
||||
# python -m alembic upgrade head
|
||||
|
||||
echo "🎉 Initialization complete!"
|
||||
|
||||
# Start the application
|
||||
echo "🌟 Starting Delphi Database System..."
|
||||
exec "$@"
|
||||
47
scripts/install-git-hooks.sh
Executable file
47
scripts/install-git-hooks.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
# Install Git hooks for Delphi Consulting Group Database System
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔧 Installing Git hooks for enhanced security..."
|
||||
|
||||
# Check if we're in a git repository
|
||||
if [ ! -d ".git" ]; then
|
||||
echo "❌ Error: Not in a Git repository root directory"
|
||||
echo " Please run this script from the project root where .git directory exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create hooks directory if it doesn't exist
|
||||
mkdir -p .git/hooks
|
||||
|
||||
# Install pre-commit hook
|
||||
if [ -f ".git/hooks/pre-commit" ]; then
|
||||
echo "⚠️ Pre-commit hook already exists. Creating backup..."
|
||||
mv .git/hooks/pre-commit .git/hooks/pre-commit.backup
|
||||
fi
|
||||
|
||||
# Create symlink to our pre-commit hook
|
||||
ln -sf ../../scripts/git-pre-commit-hook .git/hooks/pre-commit
|
||||
|
||||
# Make sure it's executable
|
||||
chmod +x .git/hooks/pre-commit
|
||||
|
||||
echo "✅ Pre-commit hook installed successfully!"
|
||||
echo ""
|
||||
echo "🛡️ Security features enabled:"
|
||||
echo " • Prevents committing .env files"
|
||||
echo " • Blocks database files and backups"
|
||||
echo " • Detects SSL certificates and keys"
|
||||
echo " • Warns about potential secrets in code"
|
||||
echo " • Checks for large files (potential data dumps)"
|
||||
echo ""
|
||||
echo "💡 The hook will run automatically before each commit."
|
||||
echo " To bypass (NOT recommended): git commit --no-verify"
|
||||
echo ""
|
||||
echo "🧪 Test the hook:"
|
||||
echo " 1. Try staging a .env file: touch .env && git add .env"
|
||||
echo " 2. Run: git commit -m 'test'"
|
||||
echo " 3. The commit should be blocked with a security warning"
|
||||
echo ""
|
||||
echo "✨ Your repository is now protected against accidental secret commits!"
|
||||
56
scripts/restore.sh
Executable file
56
scripts/restore.sh
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
# Restore script for Delphi Database System
|
||||
|
||||
set -e
|
||||
|
||||
BACKUP_DIR="/app/backups"
|
||||
DB_FILE="/app/data/delphi_database.db"
|
||||
|
||||
echo "🔄 Starting database restore..."
|
||||
|
||||
# Check if backup file is provided
|
||||
if [ -z "$1" ]; then
|
||||
echo "📋 Available backups:"
|
||||
ls -la "$BACKUP_DIR"/delphi_backup_*.db 2>/dev/null || echo " No backups found"
|
||||
echo ""
|
||||
echo "Usage: $0 <backup_file>"
|
||||
echo "Example: $0 delphi_backup_20241207_143000.db"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_FILE="$BACKUP_DIR/$1"
|
||||
|
||||
# Check if backup file exists
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
echo "❌ Backup file not found: $BACKUP_FILE"
|
||||
echo "📋 Available backups:"
|
||||
ls -la "$BACKUP_DIR"/delphi_backup_*.db 2>/dev/null || echo " No backups found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create backup of current database before restore
|
||||
if [ -f "$DB_FILE" ]; then
|
||||
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
||||
CURRENT_BACKUP="${BACKUP_DIR}/delphi_backup_before_restore_${TIMESTAMP}.db"
|
||||
echo "💾 Creating backup of current database..."
|
||||
cp "$DB_FILE" "$CURRENT_BACKUP"
|
||||
echo "✅ Current database backed up to: $CURRENT_BACKUP"
|
||||
fi
|
||||
|
||||
# Restore database
|
||||
echo "🔄 Restoring database from: $BACKUP_FILE"
|
||||
cp "$BACKUP_FILE" "$DB_FILE"
|
||||
|
||||
# Verify restore
|
||||
if [ -f "$DB_FILE" ]; then
|
||||
DB_SIZE=$(stat -f%z "$DB_FILE" 2>/dev/null || stat -c%s "$DB_FILE" 2>/dev/null)
|
||||
echo "✅ Database restored successfully"
|
||||
echo " File: $DB_FILE"
|
||||
echo " Size: $DB_SIZE bytes"
|
||||
else
|
||||
echo "❌ Restore failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🎉 Restore process completed!"
|
||||
echo "⚠️ Please restart the application to ensure proper database connection."
|
||||
195
scripts/setup-security.py
Executable file
195
scripts/setup-security.py
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Security setup script for Delphi Consulting Group Database System
|
||||
Generates secure keys and helps configure environment variables
|
||||
"""
|
||||
|
||||
import secrets
|
||||
import string
|
||||
import os
|
||||
import sys
|
||||
|
||||
def generate_secret_key(length=32):
|
||||
"""Generate a secure secret key"""
|
||||
return secrets.token_urlsafe(length)
|
||||
|
||||
def generate_secure_password(length=16):
|
||||
"""Generate a secure password with mixed characters"""
|
||||
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
|
||||
password = ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||
return password
|
||||
|
||||
def create_env_file():
|
||||
"""Create a .env file with secure defaults"""
|
||||
env_path = ".env"
|
||||
|
||||
if os.path.exists(env_path):
|
||||
response = input(f"{env_path} already exists. Overwrite? (y/N): ").strip().lower()
|
||||
if response != 'y':
|
||||
print("Keeping existing .env file.")
|
||||
return False
|
||||
|
||||
print("🔐 Generating secure configuration...")
|
||||
|
||||
# Generate secure values
|
||||
secret_key = generate_secret_key(32)
|
||||
admin_password = generate_secure_password(16)
|
||||
|
||||
# Get user inputs
|
||||
print("\n📝 Please provide the following information:")
|
||||
admin_username = input("Admin username [admin]: ").strip() or "admin"
|
||||
admin_email = input("Admin email [admin@delphicg.local]: ").strip() or "admin@delphicg.local"
|
||||
admin_fullname = input("Admin full name [System Administrator]: ").strip() or "System Administrator"
|
||||
external_port = input("External port [6920]: ").strip() or "6920"
|
||||
|
||||
# Ask about password
|
||||
use_generated = input(f"Use generated password '{admin_password}'? (Y/n): ").strip().lower()
|
||||
if use_generated == 'n':
|
||||
admin_password = input("Enter custom admin password: ").strip()
|
||||
while len(admin_password) < 8:
|
||||
print("Password must be at least 8 characters long!")
|
||||
admin_password = input("Enter custom admin password: ").strip()
|
||||
|
||||
# Create .env content
|
||||
env_content = f"""# Delphi Consulting Group Database System - Environment Variables
|
||||
# Generated by setup-security.py on {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
||||
|
||||
# ===== APPLICATION SETTINGS =====
|
||||
APP_NAME=Delphi Consulting Group Database System
|
||||
DEBUG=False
|
||||
|
||||
# ===== DATABASE CONFIGURATION =====
|
||||
DATABASE_URL=sqlite:///data/delphi_database.db
|
||||
|
||||
# ===== SECURITY SETTINGS - GENERATED =====
|
||||
SECRET_KEY={secret_key}
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=30
|
||||
ALGORITHM=HS256
|
||||
|
||||
# ===== ADMIN USER CREATION =====
|
||||
CREATE_ADMIN_USER=true
|
||||
ADMIN_USERNAME={admin_username}
|
||||
ADMIN_EMAIL={admin_email}
|
||||
ADMIN_PASSWORD={admin_password}
|
||||
ADMIN_FULLNAME={admin_fullname}
|
||||
|
||||
# ===== SERVER SETTINGS =====
|
||||
HOST=0.0.0.0
|
||||
PORT=8000
|
||||
EXTERNAL_PORT={external_port}
|
||||
|
||||
# ===== FILE STORAGE =====
|
||||
UPLOAD_DIR=./uploads
|
||||
BACKUP_DIR=./backups
|
||||
|
||||
# ===== PAGINATION =====
|
||||
DEFAULT_PAGE_SIZE=50
|
||||
MAX_PAGE_SIZE=200
|
||||
|
||||
# ===== LOGGING =====
|
||||
LOG_LEVEL=INFO
|
||||
|
||||
# ===== PRODUCTION SECURITY =====
|
||||
SECURE_COOKIES=False
|
||||
SECURE_SSL_REDIRECT=False
|
||||
|
||||
# ===== CORS SETTINGS =====
|
||||
CORS_ORIGINS=["http://localhost:{external_port}"]
|
||||
|
||||
# ===== RATE LIMITING =====
|
||||
RATE_LIMIT_PER_MINUTE=100
|
||||
LOGIN_RATE_LIMIT_PER_MINUTE=10
|
||||
|
||||
# ===== DOCKER SETTINGS =====
|
||||
WORKERS=4
|
||||
WORKER_TIMEOUT=120
|
||||
|
||||
# ===== BACKUP SETTINGS =====
|
||||
BACKUP_RETENTION_COUNT=10
|
||||
|
||||
# ===== MONITORING & HEALTH CHECKS =====
|
||||
HEALTH_CHECK_INTERVAL=30
|
||||
HEALTH_CHECK_TIMEOUT=10
|
||||
"""
|
||||
|
||||
# Write .env file
|
||||
try:
|
||||
with open(env_path, 'w') as f:
|
||||
f.write(env_content)
|
||||
|
||||
# Set restrictive permissions
|
||||
os.chmod(env_path, 0o600)
|
||||
|
||||
print(f"\n✅ Created {env_path} with secure configuration!")
|
||||
print(f"📁 File permissions set to 600 (owner read/write only)")
|
||||
print(f"\n🔐 Generated credentials:")
|
||||
print(f" Secret Key: {secret_key[:10]}... (truncated)")
|
||||
print(f" Admin Username: {admin_username}")
|
||||
print(f" Admin Email: {admin_email}")
|
||||
print(f" Admin Password: {admin_password}")
|
||||
print(f" External Port: {external_port}")
|
||||
|
||||
print(f"\n⚠️ IMPORTANT SECURITY NOTES:")
|
||||
print(f" • Keep the .env file secure and never commit it to version control")
|
||||
print(f" • Change the admin password after first login")
|
||||
print(f" • The secret key is used for JWT token signing")
|
||||
print(f" • For production, consider using stronger passwords and key rotation")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error creating .env file: {e}")
|
||||
return False
|
||||
|
||||
def show_security_checklist():
|
||||
"""Display security checklist"""
|
||||
print("\n📋 PRODUCTION SECURITY CHECKLIST:")
|
||||
checklist = [
|
||||
"✓ Generated secure SECRET_KEY",
|
||||
"✓ Set strong admin password",
|
||||
"✓ Configured proper CORS origins",
|
||||
"□ Set up SSL/HTTPS in production",
|
||||
"□ Configure firewall rules",
|
||||
"□ Set up regular backups",
|
||||
"□ Enable monitoring/logging",
|
||||
"□ Review user access permissions",
|
||||
"□ Update Docker images regularly",
|
||||
"□ Set up intrusion detection"
|
||||
]
|
||||
|
||||
for item in checklist:
|
||||
print(f" {item}")
|
||||
|
||||
def main():
|
||||
print("🛡️ Delphi Database Security Setup")
|
||||
print("=" * 40)
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "--key-only":
|
||||
print("🔑 Generating secure secret key:")
|
||||
print(generate_secret_key(32))
|
||||
return
|
||||
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "--password-only":
|
||||
print("🔒 Generating secure password:")
|
||||
print(generate_secure_password(16))
|
||||
return
|
||||
|
||||
print("This script will help you set up secure configuration for the")
|
||||
print("Delphi Consulting Group Database System.\n")
|
||||
|
||||
# Create .env file
|
||||
if create_env_file():
|
||||
show_security_checklist()
|
||||
|
||||
print(f"\n🚀 Next steps:")
|
||||
print(f" 1. Review the generated .env file")
|
||||
print(f" 2. Start the application: docker-compose up -d")
|
||||
print(f" 3. Access: http://localhost:{os.getenv('EXTERNAL_PORT', '6920')}")
|
||||
print(f" 4. Login with the generated admin credentials")
|
||||
print(f" 5. Change the admin password after first login")
|
||||
else:
|
||||
print("\n❌ Setup failed or cancelled.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user