diff --git a/.gitea/workflows/deploy-prod.yml b/.gitea/workflows/deploy-prod.yml index 3233bda..42a4c23 100644 --- a/.gitea/workflows/deploy-prod.yml +++ b/.gitea/workflows/deploy-prod.yml @@ -71,19 +71,11 @@ jobs: cd "${DEPLOY_DIR}" - if [ ! -f .env.production ]; then - echo "ERROR: ${DEPLOY_DIR}/.env.production is missing on the server" + if [ ! -f .env ]; then + echo "ERROR: ${DEPLOY_DIR}/.env is missing on the server" exit 1 fi - # Optional compose-level env (REDIS_PASSWORD, API_PORT, FE_PORT, etc.) - if [ -f .env ]; then - set -a - # shellcheck disable=SC1091 - source .env - set +a - fi - export IMAGE_TAG export NGINX_CONF diff --git a/be/docker/production/docker-compose.production.yml b/be/docker/production/docker-compose.production.yml index 93dadcd..f80b972 100644 --- a/be/docker/production/docker-compose.production.yml +++ b/be/docker/production/docker-compose.production.yml @@ -16,7 +16,7 @@ services: volumes: - app-storage-production:/var/www/storage - app-logs-production:/var/www/storage/logs - - ./.env.production:/var/www/.env:ro + - ./.env:/var/www/.env:ro - ${NGINX_CONF:-./be/docker/production/nginx/nginx.conf}:/etc/nginx/nginx.conf:ro networks: - mykopkb-production-network @@ -55,6 +55,34 @@ services: max-size: "10m" max-file: "3" + db: + image: postgres:17 + container_name: mykopkb-postgres-production + restart: unless-stopped + ports: + - "${DB_PORT:-5432}:5432" + environment: + - POSTGRES_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + - POSTGRES_DATABASE=${DB_DATABASE} + - POSTGRES_USER=${DB_USERNAME} + - POSTGRES_PASSWORD=${DB_PASSWORD} + volumes: + - db-data-production:/var/lib/postgres + - ./be/docker/postgres/conf.d:/etc/postgres/conf.d:ro + networks: + - mykopkb-production-network + healthcheck: + test: ["CMD", "postgres", "ping", "-h", "localhost"] + interval: 15s + timeout: 10s + retries: 5 + start_period: 30s + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + redis: image: redis:8 container_name: mykopkb-redis-production @@ -86,5 +114,7 @@ volumes: driver: local app-logs-production: driver: local + db-data-production: + driver: local redis-data-production: driver: local diff --git a/be/docker/training/docker-compose.training.yml b/be/docker/training/docker-compose.training.yml deleted file mode 100644 index 7333049..0000000 --- a/be/docker/training/docker-compose.training.yml +++ /dev/null @@ -1,114 +0,0 @@ -services: - app: - build: - context: . - dockerfile: ./be/docker/common/unified/Dockerfile - platforms: - - linux/amd64 - - linux/arm64 - image: git.koppkb.com/topaz/sutera:33a53e08a641152f255f5c3fa27765200add4f45 - container_name: sutera-app-training - restart: unless-stopped - ports: - - "${APP_PORT:-80}:80" - environment: - - APP_ENV=training - - APP_DEBUG=true - - DB_HOST=postgres - - DB_PORT=${DB_PORT:-5432} - - DB_DATABASE=${DB_DATABASE} - - DB_USERNAME=${DB_USERNAME} - - DB_PASSWORD=${DB_PASSWORD} - - REDIS_HOST=redis - - REDIS_PASSWORD=${REDIS_PASSWORD} - - CACHE_DRIVER=redis - - SESSION_DRIVER=redis - - QUEUE_CONNECTION=redis - volumes: - - app-storage-training:/var/www/storage - - app-logs-training:/var/www/storage/logs - - ./.env.training:/var/www/.env:ro - - ./be/docker/training/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - networks: - - sutera-training-network - depends_on: - redis: - condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - - # Redis for caching and sessions - redis: - image: redis:8 - container_name: sutera-redis-training - restart: unless-stopped - volumes: - - redis-data-training:/data - - ./redis-config/redis.conf:/usr/local/etc/redis/redis.conf:ro - command: redis-server /usr/local/etc/redis/redis.conf - networks: - - sutera-training-network - healthcheck: - test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] - interval: 10s - timeout: 5s - retries: 3 - start_period: 10s - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - - # Optional: Database (only if you want to run DB on same server for training) - # Uncomment if you want to run MySQL on the same server for training - postgres: - image: postgres:17 - container_name: sutera-postgres-training - restart: unless-stopped - ports: - - "${DB_PORT:-5432}:5432" - environment: - - POSTGRES_ROOT_PASSWORD=${DB_ROOT_PASSWORD} - - POSTGRES_DATABASE=${DB_DATABASE} - - POSTGRES_USER=${DB_USERNAME} - - POSTGRES_PASSWORD=${DB_PASSWORD} - volumes: - - postgres-data-training:/var/lib/postgres - - ./be/docker/postgres/conf.d:/etc/postgres/conf.d:ro - networks: - - sutera-training-network - healthcheck: - test: ["CMD", "postgres", "ping", "-h", "localhost"] - interval: 15s - timeout: 10s - retries: 5 - start_period: 30s - logging: - driver: "json-file" - options: - max-size: "10m" - max-file: "3" - -networks: - sutera-training-network: - driver: bridge - -volumes: - app-storage-training: - driver: local - app-logs-training: - driver: local - redis-data-training: - driver: local - postgres-data-training: - driver: local diff --git a/be/docker/training/nginx/nginx.conf b/be/docker/training/nginx/nginx.conf deleted file mode 100644 index 8a32824..0000000 --- a/be/docker/training/nginx/nginx.conf +++ /dev/null @@ -1,106 +0,0 @@ -events { - worker_connections 1024; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - sendfile on; - keepalive_timeout 65; - - # Logging - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - # Training HTTP server - server { - listen 80; - server_name _; - root /var/www/public; - index index.php index.html; - - # Security headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - - # API routes - pass directly to Laravel with original REQUEST_URI - location /api/ { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root/index.php; - include fastcgi_params; - fastcgi_param HTTP_PROXY ""; - fastcgi_param HTTPS $https if_not_empty; - fastcgi_read_timeout 300; - fastcgi_send_timeout 300; - } - - # Training SPA (built with base=/training/) - # Serve training frontend routes from /var/www/public/training - location ^~ /training/ { - add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; - try_files $uri $uri/ /training/index.html; - } - - # Serve assets under /training/assets/ - location ~* ^/training/.*\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always; - try_files $uri =404; - } - - # Handle PHP files - connect to localhost PHP-FPM - location ~ \.php$ { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - include fastcgi_params; - - # Additional FastCGI parameters - fastcgi_param HTTP_PROXY ""; - fastcgi_param HTTPS $https if_not_empty; - fastcgi_read_timeout 300; - fastcgi_send_timeout 300; - } - - # Deny access to hidden files - location ~ /\. { - deny all; - } - - # Health check endpoint for Docker - location = /health { - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root/index.php; - include fastcgi_params; - fastcgi_param HTTP_PROXY ""; - } - - location ^~ /horizon { - add_header Content-Security-Policy "default-src 'self' http: https: data: blob 'unsafe-inline' 'unsafe-eval'" always; - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - fastcgi_param SCRIPT_FILENAME $document_root/index.php; - include fastcgi_params; - fastcgi_param HTTP_PROXY ""; - fastcgi_param HTTPS $https if_not_empty; - fastcgi_read_timeout 300; - fastcgi_send_timeout 300; - } - - # TRAINING: Root path disabled - redirect to /training/ - location = / { - return 302 /training/; - } - - # TRAINING: All other paths return 404 (production frontend disabled) - location / { - return 404; - } - } -} diff --git a/be/docker/training/redis/redis.conf b/be/docker/training/redis/redis.conf deleted file mode 100644 index 6008e97..0000000 --- a/be/docker/training/redis/redis.conf +++ /dev/null @@ -1,3 +0,0 @@ -port 6379 -bind 0.0.0.0 -requirepass sutera_redis@2025 \ No newline at end of file