2025-12-02 14:01:34 +03:00
#!/bin/bash
2025-12-02 15:19:14 +03:00
# New Setuper script for A/D Infrastructure
# Downloads Packmate, moded_distructive_farm, Firegex OUTSIDE SERVICES_DIR, starts them, then starts all game services from SERVICES_DIR, and registers only Packmate and Firegex with controller.
2025-12-02 14:01:34 +03:00
2025-12-02 14:08:59 +03:00
set +e
2025-12-02 14:01:34 +03:00
2025-12-02 18:00:12 +03:00
SCRIPT_DIR = " $( cd " $( dirname " $0 " ) " && pwd ) "
2025-12-02 15:19:14 +03:00
ROOT_DIR = " $SCRIPT_DIR /.. "
# Read .env for SERVICES_DIR, CONTROLLER_API, SECRET_TOKEN
ENV_FILE = " $ROOT_DIR /.env "
if [ ! -f " $ENV_FILE " ] ; then
echo " .env file not found in $ROOT_DIR . Exiting. "
exit 1
fi
2025-12-02 17:52:40 +03:00
SERVICES_DIR = $( grep '^SERVICES_DIR=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
CONTROLLER_API = $( grep '^CONTROLLER_API=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
SECRET_TOKEN = $( grep '^SECRET_TOKEN=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
2025-12-02 15:19:14 +03:00
# Defaults
2025-12-02 17:52:40 +03:00
if [ -z " $CONTROLLER_API " ] ; then
CONTROLLER_API = "http://localhost:8001"
fi
if [ -z " $SECRET_TOKEN " ] ; then
SECRET_TOKEN = "change-me-in-production"
fi
2025-12-02 14:01:34 +03:00
2025-12-02 15:19:14 +03:00
echo "=== A/D Infrastructure Setuper (NEW) ==="
echo " Game services directory: $SERVICES_DIR "
2025-12-02 14:01:34 +03:00
echo ""
# Function to call controller API
call_api( ) {
local endpoint = " $1 "
local method = " ${ 2 :- GET } "
local data = " ${ 3 :- } "
if [ " $method " = "POST" ] ; then
curl -s -X POST " $CONTROLLER_API $endpoint " \
-H " Authorization: Bearer $SECRET_TOKEN " \
-H "Content-Type: application/json" \
-d " $data "
else
curl -s " $CONTROLLER_API $endpoint " \
-H " Authorization: Bearer $SECRET_TOKEN "
fi
}
2025-12-02 15:19:14 +03:00
# Function to setup and start Packmate
2025-12-02 14:01:34 +03:00
setup_packmate( ) {
echo "=== Setting up Packmate ==="
2025-12-02 15:19:14 +03:00
local packmate_dir = " $ROOT_DIR /packmate "
2025-12-02 14:01:34 +03:00
if [ -d " $packmate_dir " ] ; then
echo "Packmate directory already exists, updating..."
cd " $packmate_dir "
git pull
git submodule update --init --recursive
else
echo "Cloning Packmate with submodules..."
git clone --recursive https://gitlab.com/packmate/Packmate.git " $packmate_dir "
cd " $packmate_dir "
fi
mkdir -p pcaps rsa_keys Packmate_stuff
2025-12-02 18:33:05 +03:00
# Read config from parent .env
BOARD_URL = $( grep '^BOARD_URL=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
PACKMATE_LOCAL_IP = $( grep '^PACKMATE_LOCAL_IP=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
NET_INTERFACE = $( grep '^NET_INTERFACE=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
2025-12-02 18:59:22 +03:00
PACKMATE_WEB_LOGIN = $( grep '^PACKMATE_WEB_LOGIN=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
PACKMATE_WEB_PASSWORD = $( grep '^PACKMATE_WEB_PASSWORD=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
2025-12-02 18:33:05 +03:00
# Defaults if not set
if [ -z " $PACKMATE_LOCAL_IP " ] ; then
PACKMATE_LOCAL_IP = "10.60.1.2"
fi
if [ -z " $NET_INTERFACE " ] ; then
NET_INTERFACE = "eth0"
fi
2025-12-02 18:59:22 +03:00
if [ -z " $PACKMATE_WEB_LOGIN " ] ; then
PACKMATE_WEB_LOGIN = "admin"
fi
if [ -z " $PACKMATE_WEB_PASSWORD " ] ; then
PACKMATE_WEB_PASSWORD = "admin123"
fi
2025-12-02 15:19:14 +03:00
# .env and config generation (minimal)
2025-12-02 18:33:05 +03:00
cat > .env <<ENVE OF
2025-12-02 14:01:34 +03:00
BUILD_TAG = latest
2025-12-02 15:19:14 +03:00
PACKMATE_DB_PASSWORD = K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
2025-12-02 18:33:05 +03:00
NET_INTERFACE = $NET_INTERFACE
PACKMATE_LOCAL_IP = $PACKMATE_LOCAL_IP
2025-12-02 18:59:22 +03:00
WEB_LOGIN = $PACKMATE_WEB_LOGIN
WEB_PASSWORD = $PACKMATE_WEB_PASSWORD
2025-12-02 18:00:12 +03:00
POSTGRES_USER = packmate
POSTGRES_PASSWORD = K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
POSTGRES_DB = packmate
DB_PASSWORD = K604YnL3G1hp2RDkCZNjGpxbyNpNHTRb
2025-12-02 18:33:05 +03:00
INTERFACE = $NET_INTERFACE
LOCAL_IP = $PACKMATE_LOCAL_IP
2025-12-02 18:00:12 +03:00
MODE = LIVE
OLD_STREAMS_CLEANUP_ENABLED = true
OLD_STREAMS_CLEANUP_INTERVAL = 5
OLD_STREAMS_CLEANUP_THRESHOLD = 240
2025-12-02 14:13:03 +03:00
ENVEOF
cat > Packmate_stuff/postgresql.conf <<'PGEOF'
2025-12-02 14:01:34 +03:00
port = 65001
max_connections = 100
shared_buffers = 128MB
2025-12-02 14:13:03 +03:00
PGEOF
cat > Packmate_stuff/update_db_config.sh <<'SHEOF'
2025-12-02 14:01:34 +03:00
#!/bin/bash
cp /tmp/postgresql.conf /var/lib/postgresql/data/postgresql.conf
2025-12-02 14:13:03 +03:00
SHEOF
2025-12-02 14:01:34 +03:00
chmod +x Packmate_stuff/update_db_config.sh
2025-12-02 15:19:14 +03:00
# docker-compose.yml (minimal)
2025-12-02 14:13:03 +03:00
cat > docker-compose.yml <<'DCEOF'
2025-12-02 14:01:34 +03:00
services:
packmate:
env_file:
- .env
container_name: packmate-app
network_mode: "host"
2025-12-02 18:00:12 +03:00
image: registry.gitlab.com/packmate/packmate:latest
2025-12-02 14:01:34 +03:00
volumes:
- "./pcaps/:/app/pcaps/:ro"
- "./rsa_keys/:/app/rsa_keys/:ro"
depends_on:
db:
condition: service_healthy
db:
container_name: packmate-db
2025-12-02 18:00:12 +03:00
env_file:
- .env
2025-12-02 14:01:34 +03:00
network_mode: "host"
image: postgres:15.2
volumes:
- "./Packmate_stuff/postgresql.conf:/tmp/postgresql.conf:ro"
- "./Packmate_stuff/update_db_config.sh:/docker-entrypoint-initdb.d/_update_db_config.sh:ro"
healthcheck:
test: [ "CMD-SHELL" , "pg_isready -U packmate -p 65001" ]
interval: 2s
timeout: 5s
retries: 15
2025-12-02 14:13:03 +03:00
DCEOF
2025-12-02 15:19:14 +03:00
echo "Starting Packmate containers..."
2025-12-02 18:36:00 +03:00
docker compose up -d --no-build
2025-12-02 18:59:22 +03:00
echo "Waiting for Packmate to be ready..."
sleep 5
2025-12-02 14:01:34 +03:00
cd " $SCRIPT_DIR "
}
2025-12-02 15:19:14 +03:00
# Function to setup and start moded_distructive_farm
2025-12-02 14:01:34 +03:00
setup_farm( ) {
echo "=== Setting up moded_distructive_farm ==="
2025-12-02 15:19:14 +03:00
local farm_dir = " $ROOT_DIR /moded_distructive_farm "
2025-12-02 14:01:34 +03:00
if [ -d " $farm_dir " ] ; then
echo "Farm directory already exists, updating..."
cd " $farm_dir "
git pull
else
echo "Cloning moded_distructive_farm..."
git clone https://github.com/ilyastar9999/moded_distructive_farm.git " $farm_dir "
cd " $farm_dir "
fi
2025-12-02 18:33:05 +03:00
# Read config from parent .env
BOARD_URL = $( grep '^BOARD_URL=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
TEAM_TOKEN = $( grep '^TEAM_TOKEN=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
NUM_TEAMS = $( grep '^NUM_TEAMS=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
IP_TEAM_BASE = $( grep '^IP_TEAM_BASE=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
cat > .env <<ENVE OF
2025-12-02 14:01:34 +03:00
DB_PORT = 5432
DB_HOST = postgres
DB_USER = farm
2025-12-02 15:19:14 +03:00
DB_PASS = farmpassword123
2025-12-02 14:01:34 +03:00
DB_NAME = farm
2025-12-02 18:33:05 +03:00
BOARD_URL = $BOARD_URL
TEAM_TOKEN = $TEAM_TOKEN
2025-12-02 15:19:14 +03:00
WEB_PASSWORD = farmadmin
2025-12-02 18:33:05 +03:00
NUM_TEAMS = $NUM_TEAMS
IP_TEAM_BASE = $IP_TEAM_BASE
2025-12-02 15:19:14 +03:00
API_TOKEN = farm-api-token-123
2025-12-02 18:00:12 +03:00
POSTGRES_USER = farm
POSTGRES_PASSWORD = farmpassword123
POSTGRES_DB = farm
2025-12-02 14:13:03 +03:00
ENVEOF
2025-12-02 15:19:14 +03:00
echo "Starting moded_distructive_farm containers..."
2025-12-02 18:36:00 +03:00
docker compose up -d --no-build
2025-12-02 14:01:34 +03:00
cd " $SCRIPT_DIR "
}
2025-12-02 15:19:14 +03:00
# Function to setup and start Firegex
2025-12-02 14:01:34 +03:00
setup_firegex( ) {
echo "=== Setting up Firegex ==="
2025-12-02 15:19:14 +03:00
local firegex_dir = " $ROOT_DIR /firegex "
2025-12-02 18:59:22 +03:00
2025-12-02 18:33:05 +03:00
# Read config from parent .env
BOARD_URL = $( grep '^BOARD_URL=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
TEAM_TOKEN = $( grep '^TEAM_TOKEN=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
2025-12-02 18:59:22 +03:00
# Export environment variables for installer
export SCOREBOARD_URL = " $BOARD_URL "
export TEAM_TOKEN = " $TEAM_TOKEN "
export FIREGEX_PORT = "5000"
export DOCKER_MODE = "true"
echo "Installing Firegex using official installer..."
sh -c " $( curl -sLf https://pwnzer0tt1.it/firegex.sh) "
2025-12-02 15:19:14 +03:00
cd " $SCRIPT_DIR "
}
# Start all game services from SERVICES_DIR
start_game_services( ) {
echo " === Starting all game services from $SERVICES_DIR === "
2025-12-02 18:59:22 +03:00
# Read Packmate config from .env
PACKMATE_LOCAL_IP = $( grep '^PACKMATE_LOCAL_IP=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
PACKMATE_WEB_LOGIN = $( grep '^PACKMATE_WEB_LOGIN=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
PACKMATE_WEB_PASSWORD = $( grep '^PACKMATE_WEB_PASSWORD=' " $ENV_FILE " | cut -d'=' -f2- | tr -d '"' | xargs)
if [ -z " $PACKMATE_LOCAL_IP " ] ; then
PACKMATE_LOCAL_IP = "10.60.1.2"
2025-12-02 14:08:59 +03:00
fi
2025-12-02 18:59:22 +03:00
if [ -z " $PACKMATE_WEB_LOGIN " ] ; then
PACKMATE_WEB_LOGIN = "admin"
fi
if [ -z " $PACKMATE_WEB_PASSWORD " ] ; then
PACKMATE_WEB_PASSWORD = "admin123"
fi
2025-12-02 20:13:15 +03:00
echo "Preparing to start game services..."
2025-12-02 18:59:22 +03:00
# Create base64 auth string
PACKMATE_AUTH = $( echo -n " $PACKMATE_WEB_LOGIN : $PACKMATE_WEB_PASSWORD " | base64)
2025-12-02 19:54:03 +03:00
PACKMATE_URL = " http:// ${ PACKMATE_LOCAL_IP } :65000 "
# Try to obtain Packmate session cookie (JSESSIONID) using Basic auth
PACKMATE_COOKIE = $( curl -s -k -D - " $PACKMATE_URL / " \
-H " Authorization: Basic $PACKMATE_AUTH " \
-H "Accept: application/json" | grep -i 'Set-Cookie' | grep -i 'JSESSIONID' | head -n1 | sed 's/.*JSESSIONID=\([^;]*\).*/\1/' )
if [ -n " $PACKMATE_COOKIE " ] ; then
PACKMATE_COOKIE_HEADER = " Cookie: JSESSIONID= $PACKMATE_COOKIE "
else
PACKMATE_COOKIE_HEADER = ""
fi
2025-12-02 18:59:22 +03:00
# Resolve SERVICES_DIR to absolute path
2025-12-02 19:09:27 +03:00
case " $SERVICES_DIR " in
/*)
# Already absolute path
; ;
*)
# Relative path, make it absolute
SERVICES_DIR = " $ROOT_DIR / $SERVICES_DIR "
; ;
esac
2025-12-02 18:59:22 +03:00
if [ ! -d " $SERVICES_DIR " ] ; then
echo " Services directory $SERVICES_DIR does not exist, skipping game services startup. "
return
fi
# Find all subdirectories with docker-compose.yml
echo " Scanning for services in $SERVICES_DIR ... "
local service_count = 0
for service_dir in " $SERVICES_DIR " /*/ ; do
2025-12-02 19:13:53 +03:00
# Skip if wildcard didn't match anything
if [ ! -d " $service_dir " ] ; then
continue
fi
if [ -f " $service_dir /docker-compose.yml " ] || [ -f " $service_dir /docker-compose.yaml " ] ; then
2025-12-02 18:59:22 +03:00
service_name = $( basename " $service_dir " )
echo " Starting service: $service_name "
2025-12-02 19:37:24 +03:00
2025-12-02 19:38:54 +03:00
# Get relative path from SERVICES_DIR
service_rel_path = $( basename " $service_dir " )
2025-12-02 19:37:24 +03:00
2025-12-02 18:59:22 +03:00
cd " $service_dir "
2025-12-02 19:25:30 +03:00
docker compose up -d
2025-12-02 18:59:22 +03:00
2025-12-02 19:31:02 +03:00
# Determine which compose file exists
compose_file = "docker-compose.yml"
if [ ! -f " $compose_file " ] && [ -f "docker-compose.yaml" ] ; then
compose_file = "docker-compose.yaml"
fi
if [ ! -f " $compose_file " ] && [ -f "compose.yml" ] ; then
compose_file = "compose.yml"
fi
2025-12-02 20:37:52 +03:00
# Get actual exposed ports from docker ps, excluding 3333, 4444, 65000, 65001, 5432, and remove duplicates
2025-12-02 20:33:44 +03:00
container_name = " ${ service_name } -app "
2025-12-02 20:37:52 +03:00
service_ports = $( docker ps --filter " name= $container_name " --format "{{.Ports}}" | grep -oE '[0-9]+->' | sed 's/->//' | grep -Ev '^(3333|4444|65000|65001|5432)$' | sort -u | tr '\n' ',' | sed 's/,$//' )
2025-12-02 20:08:08 +03:00
echo " Exposed ports for $service_name : $service_ports "
2025-12-02 20:13:15 +03:00
2025-12-02 20:24:10 +03:00
# Register service with controller and send ports, except for Firegex, farm, and packmate
2025-12-02 20:28:53 +03:00
if [ " $service_name " != "firegex" ] && [ " $service_name " != "farm" ] && [ " $service_name " != "packmate" ] ; then
2025-12-02 20:24:10 +03:00
echo " Registering $service_name with controller... "
2025-12-02 20:28:53 +03:00
ports_json = " [ $service_ports ] "
2025-12-02 20:24:10 +03:00
ports_json = $( echo " $ports_json " | sed 's/,/,/g' )
call_api "/services" "POST" " {\"name\": \" $service_name \", \"path\": \" $service_rel_path \", \"ports\": $ports_json } "
else
echo " Skipping controller registration for $service_name . "
fi
2025-12-02 18:59:22 +03:00
# Add service to Packmate if Packmate is running
if [ -n " $service_ports " ] ; then
echo " Adding $service_name to Packmate... "
2025-12-02 19:54:03 +03:00
# Try to add each exposed host port to Packmate
2025-12-02 19:01:25 +03:00
echo " $service_ports " | tr ',' '\n' | while read port; do
if [ -n " $port " ] ; then
2025-12-02 19:54:03 +03:00
# Primary attempt (with trailing slash)
status = $( curl -s -k -o /dev/null -w "%{http_code}" -X POST " ${ PACKMATE_URL } /api/service/ " \
2025-12-02 19:01:25 +03:00
-H "Accept: application/json" \
-H " Authorization: Basic $PACKMATE_AUTH " \
-H "Content-Type: application/json" \
2025-12-02 19:54:03 +03:00
${ PACKMATE_COOKIE_HEADER : +-H " $PACKMATE_COOKIE_HEADER " } \
-d " {\"name\": \" $service_name \", \"port\": $port } " )
if [ " $status " -ge 200 ] && [ " $status " -lt 300 ] ; then
echo " Packmate: registered $service_name port $port (status $status ) "
else
# Fallback attempt without trailing slash
status2 = $( curl -s -k -o /dev/null -w "%{http_code}" -X POST " ${ PACKMATE_URL } /api/service " \
-H "Accept: application/json" \
-H " Authorization: Basic $PACKMATE_AUTH " \
-H "Content-Type: application/json" \
${ PACKMATE_COOKIE_HEADER : +-H " $PACKMATE_COOKIE_HEADER " } \
-d " {\"name\": \" $service_name \", \"port\": $port } " )
echo " Packmate: register $service_name port $port -> status $status (fallback $status2 ) "
fi
2025-12-02 19:01:25 +03:00
fi
2025-12-02 18:59:22 +03:00
done
fi
service_count = $(( service_count + 1 ))
fi
done
echo " Started and registered $service_count game service(s) "
cd " $SCRIPT_DIR "
2025-12-02 14:01:34 +03:00
}
2025-12-02 19:34:54 +03:00
# Start infrastructure services (controller, web, telegram bot, scoreboard injector)
start_infrastructure_services( ) {
echo "Starting infrastructure services..."
docker compose -f " $ROOT_DIR /docker-compose.yaml " up -d --build
echo "Infrastructure services started."
}
2025-12-02 14:01:34 +03:00
# Main setup flow
main( ) {
echo "Starting setup process..."
echo ""
read -p "Setup Packmate? (y/n): " setup_pm
read -p "Setup moded_distructive_farm? (y/n): " setup_fm
read -p "Setup Firegex? (y/n): " setup_fg
echo ""
2025-12-02 18:59:22 +03:00
if [ " $setup_pm " != "n" ] ; then
2025-12-02 14:01:34 +03:00
setup_packmate
2025-12-02 14:13:03 +03:00
fi
2025-12-02 18:59:22 +03:00
if [ " $setup_fm " != "n" ] ; then
2025-12-02 14:13:03 +03:00
setup_farm
fi
2025-12-02 18:59:22 +03:00
if [ " $setup_fg " != "n" ] ; then
2025-12-02 14:13:03 +03:00
setup_firegex
fi
2025-12-02 19:34:54 +03:00
start_infrastructure_services
2025-12-02 15:19:14 +03:00
start_game_services
2025-12-02 14:08:59 +03:00
echo ""
echo "=== Setup Complete! ==="
2025-12-02 15:19:14 +03:00
echo " Game services have been started from: $SERVICES_DIR "
2025-12-02 14:08:59 +03:00
echo ""
echo "Next steps:"
2025-12-02 15:19:14 +03:00
echo " 1. Access web dashboard: http://localhost:8000"
echo " 2. Register services via the dashboard if auto-registration failed"
2025-12-02 14:08:59 +03:00
echo ""
2025-12-02 14:01:34 +03:00
}
2025-12-02 18:00:12 +03:00
main