mirror of
https://github.com/freedbygrace/ActiveDirectoryManager.git
synced 2026-08-09 18:32:21 +00:00
Reorganize infrastructure as code and implement versioning schema
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Environment Variables for Docker Deployment
|
||||
# Copy from .env.example and customize as needed
|
||||
|
||||
# Database Configuration
|
||||
POSTGRES_USER=admanagement
|
||||
POSTGRES_PASSWORD=change_this_to_a_secure_password
|
||||
POSTGRES_DB=admanagement
|
||||
|
||||
# Application Configuration
|
||||
NODE_ENV=production
|
||||
PORT=5000
|
||||
BASE_URL=http://localhost:5000
|
||||
SESSION_SECRET=change_this_to_a_random_string
|
||||
JWT_SECRET=change_this_to_a_different_random_string
|
||||
|
||||
# Default Admin User Configuration
|
||||
DEFAULT_ADMIN_USERNAME=admin
|
||||
DEFAULT_ADMIN_PASSWORD=change_this_to_a_secure_password
|
||||
DEFAULT_ADMIN_EMAIL=admin@example.com
|
||||
DEFAULT_ADMIN_FULLNAME=System Administrator
|
||||
DISABLE_REGISTRATION=false
|
||||
@@ -0,0 +1,56 @@
|
||||
# Database Configuration
|
||||
POSTGRES_USER=admanagement
|
||||
POSTGRES_PASSWORD=strong_password_here
|
||||
POSTGRES_DB=admanagement
|
||||
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_URL=redis://redis:6379
|
||||
|
||||
# Application Configuration
|
||||
NODE_ENV=production
|
||||
PORT=5000
|
||||
BASE_URL=http://localhost:5000
|
||||
SESSION_SECRET=change_this_to_a_random_string
|
||||
DEBUG=api:*
|
||||
|
||||
# JWT Secret for API tokens
|
||||
JWT_SECRET=change_this_to_a_different_random_string
|
||||
JWT_EXPIRY=24h
|
||||
|
||||
# LDAP Connection Default Settings
|
||||
LDAP_CONNECT_TIMEOUT=10000
|
||||
LDAP_IDLE_TIMEOUT=60000
|
||||
LDAP_RECONNECT_TIMEOUT=10000
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_WINDOW_MS=900000
|
||||
RATE_LIMIT_MAX_REQUESTS=1000
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
|
||||
# Default Admin User Configuration
|
||||
DEFAULT_ADMIN_USERNAME=admin
|
||||
DEFAULT_ADMIN_PASSWORD=password
|
||||
DEFAULT_ADMIN_EMAIL=admin@example.com
|
||||
DEFAULT_ADMIN_FULLNAME=System Administrator
|
||||
DISABLE_REGISTRATION=false
|
||||
|
||||
# LDAP Authentication Configuration (Optional)
|
||||
# LDAP_SERVER=ldap.example.com
|
||||
# LDAP_PORT=389
|
||||
# LDAP_USE_TLS=true
|
||||
# LDAP_BIND_DN=cn=admin,dc=example,dc=com
|
||||
# LDAP_BIND_PASSWORD=admin_password
|
||||
# LDAP_SEARCH_BASE=dc=example,dc=com
|
||||
# LDAP_SEARCH_FILTER=(uid={{username}})
|
||||
|
||||
# OpenID Connect Authentication Configuration (Optional)
|
||||
# OIDC_ISSUER=https://accounts.google.com
|
||||
# OIDC_AUTHORIZATION_URL=https://accounts.google.com/o/oauth2/v2/auth
|
||||
# OIDC_TOKEN_URL=https://oauth2.googleapis.com/token
|
||||
# OIDC_USERINFO_URL=https://openidconnect.googleapis.com/v1/userinfo
|
||||
# OIDC_CLIENT_ID=your_client_id
|
||||
# OIDC_CLIENT_SECRET=your_client_secret
|
||||
# OIDC_CALLBACK_URL=http://localhost:5000/api/auth/oidc/callback
|
||||
@@ -0,0 +1,25 @@
|
||||
# Production Environment Settings
|
||||
|
||||
# Node Environment
|
||||
NODE_ENV=production
|
||||
|
||||
# Server Configuration
|
||||
PORT=5000
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=info
|
||||
DEBUG=api:error,api:cache
|
||||
|
||||
# Performance Tuning
|
||||
COMPRESSION_LEVEL=6
|
||||
BODY_PARSER_LIMIT=10mb
|
||||
|
||||
# Security Settings
|
||||
RATE_LIMIT_WINDOW_MS=900000
|
||||
RATE_LIMIT_MAX_REQUESTS=500
|
||||
SESSION_COOKIE_SECURE=true
|
||||
SESSION_COOKIE_HTTPONLY=true
|
||||
|
||||
# API Settings
|
||||
SWAGGER_ENABLED=true
|
||||
@@ -0,0 +1,3 @@
|
||||
# This file is used to set the VERSION environment variable for docker-compose
|
||||
# It reads the version from the version.txt file
|
||||
VERSION=$(cat ../version.txt)
|
||||
@@ -0,0 +1,65 @@
|
||||
FROM node:20-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package.json and package-lock.json
|
||||
COPY package*.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy project files
|
||||
COPY . .
|
||||
|
||||
# Build the application
|
||||
RUN npm run build
|
||||
|
||||
# Production image
|
||||
FROM node:20-alpine AS production
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Set environment variables
|
||||
ENV NODE_ENV=production
|
||||
ENV PORT=5000
|
||||
ENV BASE_URL=http://localhost:5000
|
||||
|
||||
# Authentication environment variables
|
||||
ENV JWT_SECRET=change-this-in-production
|
||||
ENV SESSION_SECRET=change-this-in-production
|
||||
ENV DEFAULT_ADMIN_USERNAME=admin
|
||||
ENV DEFAULT_ADMIN_PASSWORD=password
|
||||
ENV DEFAULT_ADMIN_EMAIL=
|
||||
ENV DEFAULT_ADMIN_FULLNAME="System Administrator"
|
||||
ENV DISABLE_REGISTRATION=false
|
||||
|
||||
# Database configuration
|
||||
ENV DATABASE_URL=postgres://postgres:postgres@postgres:5432/admgr
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# Install production dependencies only
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Copy built application from builder stage
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
|
||||
|
||||
# Copy migration files
|
||||
COPY --from=builder /app/migrations ./migrations
|
||||
|
||||
# Create a non-root user and set ownership
|
||||
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
||||
RUN chown -R appuser:appgroup /app
|
||||
|
||||
# Switch to non-root user
|
||||
USER appuser
|
||||
|
||||
# Expose the port the app runs on
|
||||
EXPOSE 5000
|
||||
|
||||
# Start the application
|
||||
CMD ["node", "dist/server/index.js"]
|
||||
@@ -0,0 +1,74 @@
|
||||
# PowerShell script for building Docker images (Windows)
|
||||
param (
|
||||
[string]$tag = "",
|
||||
[string]$registry = "",
|
||||
[switch]$push = $false,
|
||||
[string]$imageName = "ActiveDirectoryManager"
|
||||
)
|
||||
|
||||
# If no tag is provided, use the version from version.txt
|
||||
if (-not $tag) {
|
||||
$versionFile = Join-Path (Split-Path $PSScriptRoot) "version.txt"
|
||||
if (Test-Path $versionFile) {
|
||||
$tag = Get-Content $versionFile -Raw
|
||||
$tag = $tag.Trim()
|
||||
} else {
|
||||
# If version.txt doesn't exist, use current date/time in yyyy.MM.dd.HHmm format
|
||||
$tag = Get-Date -Format "yyyy.MM.dd.HHmm"
|
||||
}
|
||||
}
|
||||
|
||||
# Set error action preference to stop on any error
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Display build information
|
||||
Write-Host "Building Docker image: $imageName" -ForegroundColor Green
|
||||
Write-Host "Tag: $tag" -ForegroundColor Green
|
||||
if ($registry) {
|
||||
Write-Host "Registry: $registry" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Determine the full image name
|
||||
$fullImageName = if ($registry) { "$registry/$imageName" } else { $imageName }
|
||||
|
||||
# Check if Docker is available
|
||||
try {
|
||||
docker --version
|
||||
}
|
||||
catch {
|
||||
Write-Host "Docker is not available. Please install Docker and try again." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build the Docker image
|
||||
try {
|
||||
Write-Host "Building image: $fullImageName`:$tag" -ForegroundColor Cyan
|
||||
|
||||
# Navigate to the root directory (two levels up from the script location)
|
||||
$rootDir = (Get-Item $PSScriptRoot).Parent.Parent.FullName
|
||||
|
||||
# Build the Docker image
|
||||
docker build -t "$fullImageName`:$tag" -f "$PSScriptRoot/Dockerfile" $rootDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Docker build failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Write-Host "Successfully built image: $fullImageName`:$tag" -ForegroundColor Green
|
||||
|
||||
# Push the image if requested
|
||||
if ($push) {
|
||||
Write-Host "Pushing image to registry: $fullImageName`:$tag" -ForegroundColor Cyan
|
||||
docker push "$fullImageName`:$tag"
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Docker push failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Write-Host "Successfully pushed image: $fullImageName`:$tag" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "Error: $_" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# Bash script for building Docker images (Linux/macOS)
|
||||
|
||||
# Default values
|
||||
TAG=""
|
||||
REGISTRY=""
|
||||
PUSH=false
|
||||
IMAGE_NAME="ActiveDirectoryManager"
|
||||
|
||||
# If no tag is provided, use the version from version.txt
|
||||
if [ -z "$TAG" ]; then
|
||||
VERSION_FILE="$(dirname "$(dirname "$0")")/version.txt"
|
||||
if [ -f "$VERSION_FILE" ]; then
|
||||
TAG=$(cat "$VERSION_FILE" | tr -d '[:space:]')
|
||||
else
|
||||
# If version.txt doesn't exist, use current date/time in yyyy.MM.dd.HHmm format
|
||||
TAG=$(date +"%Y.%m.%d.%H%M")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--tag)
|
||||
TAG="$2"
|
||||
shift 2
|
||||
;;
|
||||
--registry)
|
||||
REGISTRY="$2"
|
||||
shift 2
|
||||
;;
|
||||
--push)
|
||||
PUSH=true
|
||||
shift
|
||||
;;
|
||||
--image-name)
|
||||
IMAGE_NAME="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Determine the full image name
|
||||
if [ -n "$REGISTRY" ]; then
|
||||
FULL_IMAGE_NAME="$REGISTRY/$IMAGE_NAME"
|
||||
else
|
||||
FULL_IMAGE_NAME="$IMAGE_NAME"
|
||||
fi
|
||||
|
||||
# Display build information
|
||||
echo -e "\e[32mBuilding Docker image: $IMAGE_NAME\e[0m"
|
||||
echo -e "\e[32mTag: $TAG\e[0m"
|
||||
if [ -n "$REGISTRY" ]; then
|
||||
echo -e "\e[32mRegistry: $REGISTRY\e[0m"
|
||||
fi
|
||||
|
||||
# Check if Docker is available
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo -e "\e[31mDocker is not available. Please install Docker and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Build the Docker image
|
||||
echo -e "\e[36mBuilding image: $FULL_IMAGE_NAME:$TAG\e[0m"
|
||||
|
||||
# Navigate to the root directory (two levels up from the script location)
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
|
||||
# Build the Docker image
|
||||
if ! docker build -t "$FULL_IMAGE_NAME:$TAG" -f "$(dirname "${BASH_SOURCE[0]}")/Dockerfile" "$ROOT_DIR"; then
|
||||
echo -e "\e[31mDocker build failed\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\e[32mSuccessfully built image: $FULL_IMAGE_NAME:$TAG\e[0m"
|
||||
|
||||
# Push the image if requested
|
||||
if [ "$PUSH" = true ]; then
|
||||
echo -e "\e[36mPushing image to registry: $FULL_IMAGE_NAME:$TAG\e[0m"
|
||||
|
||||
if ! docker push "$FULL_IMAGE_NAME:$TAG"; then
|
||||
echo -e "\e[31mDocker push failed\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\e[32mSuccessfully pushed image: $FULL_IMAGE_NAME:$TAG\e[0m"
|
||||
fi
|
||||
@@ -0,0 +1,80 @@
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
context: ../../
|
||||
dockerfile: iac/docker/Dockerfile
|
||||
image: ActiveDirectoryManager:${VERSION:-latest}
|
||||
container_name: ActiveDirectoryManager-api
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "5000:5000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=5000
|
||||
- BASE_URL=${BASE_URL:-http://localhost:5000}
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- SESSION_SECRET=${SESSION_SECRET}
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- DEFAULT_ADMIN_USERNAME=${DEFAULT_ADMIN_USERNAME:-admin}
|
||||
- DEFAULT_ADMIN_PASSWORD=${DEFAULT_ADMIN_PASSWORD:-password}
|
||||
- DEFAULT_ADMIN_EMAIL=${DEFAULT_ADMIN_EMAIL}
|
||||
- DEFAULT_ADMIN_FULLNAME=${DEFAULT_ADMIN_FULLNAME:-System Administrator}
|
||||
- DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false}
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
networks:
|
||||
- app-network
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: ActiveDirectoryManager-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
networks:
|
||||
- app-network
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: ActiveDirectoryManager-redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
networks:
|
||||
- app-network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
networks:
|
||||
app-network:
|
||||
driver: bridge
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
Reference in New Issue
Block a user