diff --git a/.gitignore b/.gitignore index c82285b78..f65e77037 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ static/ TODO.txt resources/images/.DS_Store resources/.DS_Store -.env +.env* .DS_Store \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 369c7b508..2b8ba2862 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,11 +1,8 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" -# Run tests first -npm run test || { - echo "Tests failed - commit aborted" - exit 1 -} +# Add PATH setup to ensure npx is found +export PATH="/usr/local/bin:$HOME/.npm-global/bin:$HOME/.nvm/versions/node/$(node -v)/bin:$PATH" # Then run lint-staged if tests pass npx lint-staged \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index bc4043754..b9c991dec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,28 @@ # Use an official Node runtime as the base image FROM node:18 - ARG GIT_COMMIT=unknown ENV GIT_COMMIT=$GIT_COMMIT -# Install Nginx, Supervisor and Git (for Husky) -RUN apt-get update && apt-get install -y nginx supervisor git && \ - rm -rf /var/lib/apt/lists/* +# Install Nginx, Supervisor, Git, jq, curl, and Node Exporter dependencies +RUN apt-get update && apt-get install -y \ + nginx \ + supervisor \ + git \ + curl \ + jq \ + wget \ + && rm -rf /var/lib/apt/lists/* + +# Install Node Exporter +RUN mkdir -p /opt/node_exporter && \ + wget -qO- https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz | \ + tar xvz --strip-components=1 -C /opt/node_exporter && \ + ln -s /opt/node_exporter/node_exporter /usr/local/bin/ + +# Install cloudflared +RUN curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb > cloudflared.deb \ + && dpkg -i cloudflared.deb \ + && rm cloudflared.deb # Set the working directory in the container WORKDIR /usr/src/app @@ -33,8 +49,9 @@ RUN rm -f /etc/nginx/sites-enabled/default RUN mkdir -p /var/log/supervisor COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf -# Expose only the Nginx port -EXPOSE 80 443 +# Copy and make executable the startup script +COPY startup.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/startup.sh -# Start Supervisor to manage both Node.js and Nginx -CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"] \ No newline at end of file +# Use the startup script as the entrypoint +ENTRYPOINT ["/usr/local/bin/startup.sh"] \ No newline at end of file diff --git a/deploy.sh b/deploy.sh index cb7bcc741..630afc288 100755 --- a/deploy.sh +++ b/deploy.sh @@ -7,6 +7,27 @@ set -e # Exit immediately if a command exits with a non-zero status +# Check command line arguments +if [ $# -lt 2 ] || [ $# -gt 3 ]; then + echo "Error: Please specify environment and host, with optional subdomain" + echo "Usage: $0 [prod|staging] [eu|us|staging] [subdomain]" + exit 1 +fi + +# Validate first argument (environment) +if [ "$1" != "prod" ] && [ "$1" != "staging" ]; then + echo "Error: First argument must be either 'prod' or 'staging'" + echo "Usage: $0 [prod|staging] [eu|us|staging] [subdomain]" + exit 1 +fi + +# Validate second argument (host) +if [ "$2" != "eu" ] && [ "$2" != "us" ] && [ "$2" != "staging" ]; then + echo "Error: Second argument must be either 'eu', 'us', or 'staging'" + echo "Usage: $0 [prod|staging] [eu|us|staging] [subdomain]" + exit 1 +fi + # Function to print section headers print_header() { echo "======================================================" @@ -14,59 +35,59 @@ print_header() { echo "======================================================" } -# Load environment variables +ENV=$1 +HOST=$2 +SUBDOMAIN=$3 # Optional third argument for custom subdomain + +# Set subdomain - use the custom subdomain if provided, otherwise use REGION +if [ -n "$SUBDOMAIN" ]; then + echo "Using custom subdomain: $SUBDOMAIN" +else + SUBDOMAIN=$HOST + echo "Using host as subdomain: $SUBDOMAIN" +fi + +# Load common environment variables first if [ -f .env ]; then - echo "Loading configuration from .env file..." + echo "Loading common configuration from .env file..." export $(grep -v '^#' .env | xargs) fi -# Check command line argument -if [ $# -ne 1 ] || ([ "$1" != "staging" ] && [ "$1" != "eu" ] && [ "$1" != "us" ]); then - echo "Error: Please specify environment (staging, eu, or us)" - echo "Usage: $0 [staging|eu|us]" +# Load environment-specific variables +if [ -f .env.$ENV ]; then + echo "Loading $ENV-specific configuration from .env.$ENV file..." + export $(grep -v '^#' .env.$ENV | xargs) +else + echo "Error: Environment file .env.$ENV not found" exit 1 fi -REGION=$1 -VERSION_TAG="latest" -DOCKER_REPO="" -ENV="" -SSH_KEY="" - -# Set environment-specific variables -if [ "$REGION" == "staging" ]; then - print_header "DEPLOYING TO STAGING ENVIRONMENT" +if [ "$HOST" == "staging" ]; then + print_header "DEPLOYING TO STAGING HOST" SERVER_HOST=$SERVER_HOST_STAGING - DOCKER_REPO=$DOCKER_REPO_STAGING - ENV="staging" - SSH_KEY=$SSH_KEY_STAGING -elif [ "$REGION" == "us" ]; then - print_header "DEPLOYING TO US ENVIRONMENT" +elif [ "$HOST" == "us" ]; then + print_header "DEPLOYING TO US HOST" SERVER_HOST=$SERVER_HOST_US - DOCKER_REPO=$DOCKER_REPO_PROD # Uses prod Docker repo for alt environment - SSH_KEY=$SSH_KEY_PROD - ENV="prod" else - print_header "DEPLOYING TO EU ENVIRONMENT" + print_header "DEPLOYING TO EU HOST" SERVER_HOST=$SERVER_HOST_EU - DOCKER_REPO=$DOCKER_REPO_PROD - SSH_KEY=$SSH_KEY_PROD - ENV="prod" fi # Check required environment variables if [ -z "$SERVER_HOST" ]; then - echo "Error: SERVER_HOST_${REGION^^} not defined in .env file or environment" + echo "Error: ${HOST} not defined in .env file or environment" exit 1 fi # Configuration -DOCKER_USERNAME=${DOCKER_USERNAME} # Docker Hub username UPDATE_SCRIPT="./update.sh" # Path to your update script REMOTE_USER="openfront" REMOTE_UPDATE_PATH="/home/$REMOTE_USER" REMOTE_UPDATE_SCRIPT="$REMOTE_UPDATE_PATH/update-openfront.sh" # Where to place the script on server +IMAGE_NAME="${DOCKER_USERNAME}/${DOCKER_REPO}" +DOCKER_IMAGE="${IMAGE_NAME}:${VERSION_TAG}" + # Check if update script exists if [ ! -f "$UPDATE_SCRIPT" ]; then echo "Error: Update script $UPDATE_SCRIPT not found!" @@ -75,7 +96,9 @@ fi # Step 1: Build and upload Docker image to Docker Hub print_header "STEP 1: Building and uploading Docker image to Docker Hub" -echo "Region: ${REGION}" +echo "Environment: ${ENV}" +echo "Host: ${HOST}" +echo "Subdomain: ${SUBDOMAIN}" echo "Using version tag: $VERSION_TAG" echo "Docker repository: $DOCKER_REPO" @@ -107,25 +130,32 @@ chmod +x $UPDATE_SCRIPT # Copy the update script to the server scp -i $SSH_KEY $UPDATE_SCRIPT $REMOTE_USER@$SERVER_HOST:$REMOTE_UPDATE_SCRIPT -# Copy environment variables if needed -if [ -f .env ]; then - scp -i $SSH_KEY .env $REMOTE_USER@$SERVER_HOST:$REMOTE_UPDATE_PATH/.env - # Secure the .env file - ssh -i $SSH_KEY $REMOTE_USER@$SERVER_HOST "chmod 600 $REMOTE_UPDATE_PATH/.env" -fi - if [ $? -ne 0 ]; then echo "❌ Failed to copy update script to server. Stopping deployment." exit 1 fi -echo "✅ Update script successfully copied to server." - -# Step 3: Execute the update script on the server -print_header "STEP 3: Executing update script on server" - -# Make the script executable on the remote server and execute it with the environment parameter -ssh -i $SSH_KEY $REMOTE_USER@$SERVER_HOST "chmod +x $REMOTE_UPDATE_SCRIPT && $REMOTE_UPDATE_SCRIPT $REGION $DOCKER_USERNAME $DOCKER_REPO" +ssh -i $SSH_KEY $REMOTE_USER@$SERVER_HOST "chmod +x $REMOTE_UPDATE_SCRIPT && \ +cat > $REMOTE_UPDATE_PATH/.env << 'EOL' +GAME_ENV=$ENV +ENV=$ENV +HOST=$HOST +SUBDOMAIN=$SUBDOMAIN +DOCKER_IMAGE=$DOCKER_IMAGE +DOCKER_TOKEN=$DOCKER_TOKEN +ADMIN_TOKEN=$ADMIN_TOKEN +CF_ACCOUNT_ID=$CF_ACCOUNT_ID +R2_ACCESS_KEY=$R2_ACCESS_KEY +R2_SECRET_KEY=$R2_SECRET_KEY +R2_BUCKET=$R2_BUCKET +CF_API_TOKEN=$CF_API_TOKEN +DOMAIN=$DOMAIN +SUBDOMAIN=$SUBDOMAIN +MON_USERNAME=$MON_USERNAME +MON_PASSWORD=$MON_PASSWORD +EOL +chmod 600 $REMOTE_UPDATE_PATH/.env && \ +$REMOTE_UPDATE_SCRIPT" if [ $? -ne 0 ]; then echo "❌ Failed to execute update script on server." @@ -133,6 +163,6 @@ if [ $? -ne 0 ]; then fi print_header "DEPLOYMENT COMPLETED SUCCESSFULLY" -echo "✅ New version deployed to ${REGION} environment!" -echo "🌐 Check your ${REGION} server to verify the deployment." +echo "✅ New version deployed to ${ENV} environment in ${HOST} with subdomain ${SUBDOMAIN}!" +echo "🌐 Check your server to verify the deployment." echo "=======================================================" \ No newline at end of file diff --git a/example.env b/example.env index 1be8f5410..14430d50d 100644 --- a/example.env +++ b/example.env @@ -1,20 +1,32 @@ -# Server Configuration -SERVER_HOST_STAGING=xxx.xxx.xx.xxx -SERVER_HOST_EU=xxx.xxx.xxx.xxx -SERVER_HOST_US=x.xxx.xxx.xxx -SSH_KEY_STAGING=~/.ssh/your-staging-key -SSH_KEY_PROD=~/.ssh/your-prod-key +# SSH Configuration +SSH_KEY=~/.ssh/your-ssh-key # Docker Configuration DOCKER_USERNAME=username -DOCKER_REPO_PROD=your-prod-repo -DOCKER_REPO_STAGING=your-staging-repo -DOCKER_TOKEN=your_docker_token +DOCKER_REPO=your-repo-name +DOCKER_TOKEN=your_docker_token_here # Admin credentials -ADMIN_TOKEN=your_admin_token +ADMIN_TOKEN=your_admin_token_here + +# Cloudflare Configuration +CF_ACCOUNT_ID=your_cloudflare_account_id +CF_API_TOKEN=your_cloudflare_api_token +DOMAIN=your-domain.com + +# R2 Configuration R2_ACCESS_KEY=your_r2_access_key R2_SECRET_KEY=your_r2_secret_key -R2_ACCOUNT_ID=your_r2_account_id -R2_PROD_BUCKET=your-prod-bucket -R2_STAGING_BUCKET=your-staging-bucket \ No newline at end of file +R2_BUCKET=your-bucket-name + +# Server Hosts +SERVER_HOST_STAGING=123.456.78.90 +SERVER_HOST_EU=123.456.78.91 +SERVER_HOST_US=123.456.78.92 + +# Monitoring Credentials +MON_USERNAME=monitor_username +MON_PASSWORD=monitor_password + +# Version +VERSION_TAG="latest" \ No newline at end of file diff --git a/metric-exporter.sh b/metric-exporter.sh new file mode 100755 index 000000000..e3ac7370e --- /dev/null +++ b/metric-exporter.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Metric Collector for Prometheus Pushgateway +# This script collects metrics from Node Exporter and application sources +# and pushes them to a Prometheus Pushgateway with custom labels. + +# Configuration +NODE_EXPORTER_URL="http://localhost:9100/metrics" +APP_METRICS_URL="http://localhost:9090/metrics" +PUSHGATEWAY_BASE_URL="https://mon.openfront.io/pushgateway/metrics" +AUTH=$MON_USERNAME:$MON_PASSWORD +INTERVAL=15 # seconds + +# Function to fetch metrics from Node Exporter +fetch_node_exporter_metrics() { + curl -s --connect-timeout 5 --max-time 10 "$NODE_EXPORTER_URL" || + echo "# Error fetching Node Exporter metrics" +} + +# Function to fetch metrics from your application +fetch_app_metrics() { + curl -s --connect-timeout 5 --max-time 10 "$APP_METRICS_URL" || + echo "# Error fetching application metrics" +} + +# Function to push metrics to Pushgateway +push_metrics() { + local metrics=$1 + local job_name=$2 + + echo "Pushing $job_name metrics to Pushgateway..." + + # Create a temporary file for the metrics + TEMP_FILE=$(mktemp) + echo "$metrics" > "$TEMP_FILE" + + # Push to Pushgateway with instance label + curl -s -u "$AUTH" --data-binary @"$TEMP_FILE" \ + "$PUSHGATEWAY_BASE_URL/job/$job_name/instance/$HOST" + + # Check if push was successful + if [ $? -eq 0 ]; then + echo "$job_name metrics pushed successfully" + else + echo "Error pushing $job_name metrics" + fi + + # Remove temporary file + rm "$TEMP_FILE" +} + +# Function to add labels to metrics +add_labels() { + local metrics=$1 + + # First, handle metrics with existing labels + metrics=$(echo "$metrics" | sed -E 's/(\{[^}]*)\}/\1,env="'$ENV'",host="'$HOST'",subdomain="'$SUBDOMAIN'"}/g') + + # Then, handle metrics with no existing labels + metrics=$(echo "$metrics" | sed -E 's/^([a-zA-Z0-9_:]+)[ \t]+([0-9.e+-]+)$/\1{env="'$ENV'",host="'$HOST'",subdomain="'$SUBDOMAIN'"} \2/g') + + echo "$metrics" +} + +# Main function to collect and push metrics +collect_and_push_metrics() { + echo "Starting metrics collection cycle at $(date)" + + # Get metrics from both sources + NODE_METRICS=$(fetch_node_exporter_metrics) + APP_METRICS=$(fetch_app_metrics) + + # Clean up metrics (remove headers etc.) + NODE_METRICS=$(echo "$NODE_METRICS" | grep -v "^Fetching") + APP_METRICS=$(echo "$APP_METRICS" | grep -v "^Fetching") + + # Add labels to metrics + NODE_METRICS=$(add_labels "$NODE_METRICS") + APP_METRICS=$(add_labels "$APP_METRICS") + + # Push to Pushgateway separately + push_metrics "$NODE_METRICS" "node_exporter" + push_metrics "$APP_METRICS" "app_metrics" + + echo "Metrics collection cycle completed at $(date)" +} + +# Main execution +echo "===== Starting metrics collector =====" +echo "Environment: $ENV, HOST: $HOST, Subdomain: $SUBDOMAIN" +echo "Collecting and pushing metrics every $INTERVAL seconds" +echo "Node Exporter URL: $NODE_EXPORTER_URL" +echo "App Metrics URL: $APP_METRICS_URL" +echo "Pushgateway URL: $PUSHGATEWAY_BASE_URL" + +# Wait for app to be ready. +sleep 30 + +# Then set up interval loop +while true; do + sleep $INTERVAL + collect_and_push_metrics +done \ No newline at end of file diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 95487a5cd..afaee99a6 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -34,7 +34,7 @@ export abstract class DefaultServerConfig implements ServerConfig { return process.env.GIT_COMMIT; } r2Endpoint(): string { - return `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`; + return `https://${process.env.CF_ACCOUNT_ID}.r2.cloudflarestorage.com`; } r2AccessKey(): string { return process.env.R2_ACCESS_KEY; diff --git a/src/server/WorkerMetrics.ts b/src/server/WorkerMetrics.ts index 08c4d2e19..5f209e87b 100644 --- a/src/server/WorkerMetrics.ts +++ b/src/server/WorkerMetrics.ts @@ -1,10 +1,6 @@ import promClient from "prom-client"; -import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { GameManager } from "./GameManager"; -const config = getServerConfigFromServer(); -const region = config.region(); - // Initialize the Prometheus registry const register = new promClient.Registry(); @@ -15,21 +11,18 @@ promClient.collectDefaultMetrics({ register }); const activeGamesGauge = new promClient.Gauge({ name: "openfront_active_games_count", help: "Number of active games on this worker", - labelNames: ["region"], registers: [register], }); const connectedClientsGauge = new promClient.Gauge({ name: "openfront_connected_clients_count", help: "Number of connected clients on this worker", - labelNames: ["region"], registers: [register], }); const memoryUsageGauge = new promClient.Gauge({ name: "openfront_memory_usage_bytes", help: "Current memory usage of the worker process in bytes", - labelNames: ["region"], registers: [register], }); @@ -42,11 +35,11 @@ export const metrics = { // Function to update game-related metrics updateGameMetrics: (gameManager: GameManager) => { - activeGamesGauge.set({ region: region }, gameManager.activeGames()); - connectedClientsGauge.set({ region: region }, gameManager.activeClients()); + activeGamesGauge.set(gameManager.activeGames()); + connectedClientsGauge.set(gameManager.activeClients()); // Update memory usage metrics const memoryUsage = process.memoryUsage(); - memoryUsageGauge.set({ region: region }, memoryUsage.heapUsed); + memoryUsageGauge.set(memoryUsage.heapUsed); }, }; diff --git a/startup.sh b/startup.sh new file mode 100644 index 000000000..58e768d61 --- /dev/null +++ b/startup.sh @@ -0,0 +1,90 @@ +#!/bin/bash +set -e + +# Check if required environment variables are set +if [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ACCOUNT_ID" ] || [ -z "$SUBDOMAIN" ] || [ -z "$DOMAIN" ]; then + echo "Error: Required environment variables not set" + echo "Please set CF_API_TOKEN, CF_ACCOUNT_ID, SUBDOMAIN, and DOMAIN" + exit 1 +fi + +# Generate a unique tunnel name using timestamp +TIMESTAMP=$(date +%Y%m%d%H%M%S) +TUNNEL_NAME="${SUBDOMAIN}-tunnel-${TIMESTAMP}" +echo "Using unique tunnel name: ${TUNNEL_NAME}" + +# Create a new tunnel +echo "Creating Cloudflare tunnel for subdomain ${SUBDOMAIN}..." +TUNNEL_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + --data "{\"name\":\"${TUNNEL_NAME}\"}") + +# Extract tunnel ID and token +TUNNEL_ID=$(echo $TUNNEL_RESPONSE | jq -r '.result.id') +TUNNEL_TOKEN=$(echo $TUNNEL_RESPONSE | jq -r '.result.token') + +if [ -z "$TUNNEL_ID" ] || [ "$TUNNEL_ID" == "null" ]; then + echo "Failed to create tunnel" + echo $TUNNEL_RESPONSE + exit 1 +fi + +echo "Tunnel created with ID: ${TUNNEL_ID}" + +# Configure the tunnel with hostname +echo "Configuring tunnel to point to ${SUBDOMAIN}.${DOMAIN}..." +curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/configurations" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + --data "{\"config\":{\"ingress\":[{\"hostname\":\"${SUBDOMAIN}.${DOMAIN}\",\"service\":\"http://localhost:80\"},{\"service\":\"http_status:404\"}]}}" + +# Update DNS record to point to the new tunnel +echo "Updating DNS record to point to the new tunnel..." + +# First check if DNS record exists +DNS_RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${DOMAIN}" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json") + +ZONE_ID=$(echo $DNS_RECORDS | jq -r '.result[0].id') + +if [ -z "$ZONE_ID" ] || [ "$ZONE_ID" == "null" ]; then + echo "Could not find zone ID for domain ${DOMAIN}" + exit 1 +fi + +# Check for existing record +EXISTING_RECORDS=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${SUBDOMAIN}.${DOMAIN}" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json") + +RECORD_ID=$(echo $EXISTING_RECORDS | jq -r '.result[0].id') + +# Create or update the DNS record +if [ -z "$RECORD_ID" ] || [ "$RECORD_ID" == "null" ]; then + # Create new record + echo "Creating new DNS record..." + DNS_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + --data "{\"type\":\"CNAME\",\"name\":\"${SUBDOMAIN}\",\"content\":\"${TUNNEL_ID}.cfargotunnel.com\",\"ttl\":1,\"proxied\":true}") +else + # Update existing record + echo "Updating existing DNS record..." + DNS_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \ + -H "Authorization: Bearer ${CF_API_TOKEN}" \ + -H "Content-Type: application/json" \ + --data "{\"type\":\"CNAME\",\"name\":\"${SUBDOMAIN}\",\"content\":\"${TUNNEL_ID}.cfargotunnel.com\",\"ttl\":1,\"proxied\":true}") +fi + + +# Log the tunnel information +echo "Tunnel is set up! Site will be available at: https://${SUBDOMAIN}.${DOMAIN}" + + +# Export the tunnel token for supervisord +export CLOUDFLARE_TUNNEL_TOKEN=${TUNNEL_TOKEN} + +# Start supervisord +exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf \ No newline at end of file diff --git a/supervisord.conf b/supervisord.conf index c31d0429c..16c3eb212 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -22,4 +22,26 @@ user=node stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 \ No newline at end of file +stderr_logfile_maxbytes=0 + +[program:cloudflared] +command=cloudflared tunnel run --token %(ENV_CLOUDFLARE_TUNNEL_TOKEN)s +autostart=true +autorestart=true +stdout_logfile=/var/log/cloudflared.log +stderr_logfile=/var/log/cloudflared-err.log + +[program:node_exporter] +command=/usr/local/bin/node_exporter +autostart=true +autorestart=true +stdout_logfile=/var/log/node_exporter.log +stderr_logfile=/var/log/node_exporter-err.log + + +[program:metrics_exporter] +command=/usr/src/app/metric-exporter.sh +autostart=true +autorestart=true +stdout_logfile=/var/log/metrics-exporter.log +stderr_logfile=/var/log/metrics-exporter-err.log diff --git a/update.sh b/update.sh index 8aea4b024..86319d255 100755 --- a/update.sh +++ b/update.sh @@ -2,35 +2,20 @@ # update.sh - Script to update Docker container on Hetzner server # Called by deploy.sh after uploading Docker image to Docker Hub -# Check if environment parameter is provided -if [ $# -lt 3 ]; then - echo "Error: Required parameters missing" - echo "Usage: $0 " - exit 1 -fi - -# Set parameters -REGION=$1 -DOCKER_USERNAME=$2 -DOCKER_REPO=$3 - -# Container and image configuration -CONTAINER_NAME="openfront-${REGION}" -IMAGE_NAME="${DOCKER_USERNAME}/${DOCKER_REPO}" -FULL_IMAGE_NAME="${IMAGE_NAME}:latest" - -echo "======================================================" -echo "🔄 UPDATING SERVER: ${REGION} ENVIRONMENT" -echo "======================================================" -echo "Container name: ${CONTAINER_NAME}" -echo "Docker image: ${FULL_IMAGE_NAME}" - # Load environment variables if .env exists if [ -f /home/openfront/.env ]; then echo "Loading environment variables from .env file..." export $(grep -v '^#' /home/openfront/.env | xargs) fi +echo "======================================================" +echo "🔄 UPDATING SERVER: ${HOST} ENVIRONMENT" +echo "======================================================" + + +# Container and image configuration +CONTAINER_NAME="openfront-${ENV}-${SUBDOMAIN}" + docker login -u $DOCKER_USERNAME -p $DOCKER_TOKEN # Install Loki Docker plugin if not already installed @@ -46,8 +31,8 @@ else echo "Loki Docker plugin already installed." fi -echo "Pulling latest image from Docker Hub..." -docker pull $FULL_IMAGE_NAME +echo "Pulling ${DOCKER_IMAGE} from Docker Hub..." +docker pull $DOCKER_IMAGE echo "Checking for existing container..." # Check for running container @@ -86,27 +71,20 @@ if [ -n "$PORT_CHECK" ]; then echo "Attempting to proceed anyway..." fi -ENV="prod" -if [ "$REGION" == "staging" ]; then - ENV="staging" -fi - -echo "Starting new container for ${REGION} environment..." -docker run -d -p 80:80 -p 127.0.0.1:9090:9090 \ +echo "Starting new container for ${HOST} environment..." +docker run -d \ --restart=always \ $VOLUME_MOUNTS \ --log-driver=loki \ - --log-opt loki-url="http://localhost:3100/loki/api/v1/push" \ + --log-opt loki-url="https://${MON_USERNAME}:${MON_PASSWORD}@mon.openfront.io/loki/loki/api/v1/push" \ --log-opt loki-batch-size="400" \ - --log-opt loki-external-labels="job=docker,environment=${ENV},host=${REGION},region=${REGION}" \ - --env GAME_ENV=${ENV} \ - --env REGION=${REGION} \ + --log-opt loki-external-labels="job=docker,environment=${ENV},host=${HOST},subdomain=${SUBDOMAIN}" \ --env-file /home/openfront/.env \ --name ${CONTAINER_NAME} \ - $FULL_IMAGE_NAME + $DOCKER_IMAGE if [ $? -eq 0 ]; then - echo "Update complete! New ${REGION} container is running." + echo "Update complete! New ${CONTAINER_NAME} container is running." # Final cleanup after successful deployment echo "Performing final cleanup of unused Docker resources..."