diff --git a/.forgejo/workflows/build-on-commit.yml b/.forgejo/workflows/build-on-commit.yml new file mode 100644 index 0000000..fba6d8f --- /dev/null +++ b/.forgejo/workflows/build-on-commit.yml @@ -0,0 +1,47 @@ +name: Build Docker Image on Commit + +on: + push: + branches: + - main + tags: + - '!' # Exclude tags + +jobs: + build-and-publish: + runs-on: docker-builder + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set REPO_VARS + id: repo-url + run: | + echo "REPO_HOST=$(echo "${{ github.server_url }}" | sed 's~http[s]*://~~g')" >> $GITHUB_ENV + echo "REPO_PATH=${{ github.repository }}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: docker-container + driver-opts: | + network=host + + - name: Login to OCI registry + run: | + echo "${{ secrets.OCI_TOKEN }}" | docker login $REPO_HOST -u "${{ secrets.OCI_USER }}" --password-stdin + + - name: Build and push multi-arch Docker images + run: | + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --tag $REPO_HOST/$REPO_PATH:${{ github.sha }} \ + --tag $REPO_HOST/$REPO_PATH:nightly \ + --push \ + . + + - name: Cleanup + run: | + docker buildx prune -f + docker logout $REPO_HOST \ No newline at end of file diff --git a/.forgejo/workflows/build-on-tag.yml b/.forgejo/workflows/build-on-tag.yml new file mode 100644 index 0000000..012b946 --- /dev/null +++ b/.forgejo/workflows/build-on-tag.yml @@ -0,0 +1,46 @@ +name: Build and Publish Docker Image on Tag + +on: + push: + tags: + - '*' + +jobs: + build-and-publish: + runs-on: docker-builder + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set REPO_VARS + id: repo-url + run: | + echo "REPO_HOST=$(echo "${{ github.server_url }}" | sed 's~http[s]*://~~g')" >> $GITHUB_ENV + echo "REPO_PATH=${{ github.repository }}" >> $GITHUB_ENV + echo "TAG=${{ github.ref_name }}" >> $GITHUB_ENV + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver: docker-container + driver-opts: | + network=host + + - name: Login to OCI registry + run: | + echo "${{ secrets.OCI_TOKEN }}" | docker login $REPO_HOST -u "${{ secrets.OCI_USER }}" --password-stdin + + - name: Build and push Docker images + run: | + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --tag $REPO_HOST/$REPO_PATH:$TAG \ + --tag $REPO_HOST/$REPO_PATH:latest \ + --push \ + . + + - name: Cleanup + run: | + docker buildx prune -f + docker logout $REPO_HOST \ No newline at end of file diff --git a/.gitignore b/.gitignore index 933a105..91fcd16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,3 @@ -# Environment files -.env -.env.local -.env.*.local - -# TAK Server release files -takserver-release/*.zip -takserver-release/*.tar.gz - -# Data directories -*/data/ - - -# Local overrides -docker-compose.override.yml -docker-compose.local.yml - -# Original files and releases (legacy) /original-files /takserver-release -/data +/data \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index eee87b6..b64b9c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,46 @@ FROM eclipse-temurin:17-jammy -RUN apt update && apt-get install -y emacs-nox net-tools netcat vim nmon python3-lxml unzip curl -# Copy the TAK Server release file -COPY takserver-release/ /takserver-release/ -COPY scripts/ /opt/scripts/ +# Install all required packages +RUN apt-get update && apt-get install -y \ + postgresql-common \ + emacs-nox \ + net-tools \ + netcat \ + vim \ + unzip \ + curl \ + sudo \ + gosu -# Create necessary directories -RUN mkdir -p /opt/tak/data/logs /opt/tak/data/certs +RUN yes | /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh +RUN apt-get update && apt-get install -y \ + postgresql-15 \ + postgresql-15-postgis-3 \ + postgresql-client-15 \ + postgresql-contrib-15 -ENTRYPOINT ["/bin/bash", "/opt/scripts/docker_entrypoint.sh"] +RUN apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Create tak user and directories +RUN useradd -m -s /bin/bash tak && \ + mkdir -p /opt/tak /opt/tak/logs /takserver-zip && \ + chown -R tak:tak /opt/tak + +# Configure PostgreSQL data directory (initialization will be done at runtime) +RUN mkdir -p /var/lib/postgresql/15/main && \ + chown -R postgres:postgres /var/lib/postgresql + +# Copy all scripts into the container +COPY entrypoint.sh /entrypoint.sh +COPY scripts/ /scripts/ + +# Make all scripts executable +RUN chmod +x /entrypoint.sh && \ + chmod +x /scripts/*.sh + +# Expose common TAK server ports +EXPOSE 5432 8080 8443 8444 8446 + +# Set the entrypoint +ENTRYPOINT ["/entrypoint.sh"] diff --git a/EDIT_ME.env b/EDIT_ME.env deleted file mode 100644 index d23efce..0000000 --- a/EDIT_ME.env +++ /dev/null @@ -1,28 +0,0 @@ -# The database password -POSTGRES_PASSWORD='' - -# Certificate Authority configuration details -CA_NAME='' -CA_PASS='' -STATE='' -CITY='' -ORGANIZATION='' -ORGANIZATIONAL_UNIT='' - -# The password for the takserver instance's certificate -TAKSERVER_CERT_PASS='' - -# The username and password for the takserver administrator -ADMIN_CERT_NAME='' -ADMIN_CERT_PASS='' - -# Values that should not require modification with standard usage -POSTGRES_DB=cot -POSTGRES_USER=martiuser -POSTGRES_URL=jdbc:postgresql://takdb:5432/cot - -# Heap size configuration (in MB) -CONFIG_MAX_HEAP=512 -MESSAGING_MAX_HEAP=2048 -API_MAX_HEAP=1024 -PLUGIN_MANAGER_MAX_HEAP=512 diff --git a/README.md b/README.md index 2ac7168..d04c177 100644 --- a/README.md +++ b/README.md @@ -1,108 +1,224 @@ -# TAK Server Docker Setup +# TAK Server Hybrid Docker Container -A self-contained Docker setup for TAK Server that automatically extracts and configures from the release files. +This Docker container combines both the TAK server and PostgreSQL database functionality into a single container. It automatically detects and uses the latest TAK server release from the mounted volume. -## Quick Start +## ⚠️ IMPORTANT: TAK Server Files Required -1. **Build the Docker image:** - ```bash - ./build.sh - ``` +**This container does NOT include TAK server files due to licensing restrictions.** You must provide your own TAK server release files obtained through proper channels: -2. **Configure environment variables:** - Edit `EDIT_ME.env` and fill in the required values: - ```bash - # Required fields to fill in: - POSTGRES_PASSWORD='your_db_password' - CA_NAME='your_ca_name' - CA_PASS='your_ca_password' - STATE='your_state' - CITY='your_city' - ORGANIZATION='your_organization' - ORGANIZATIONAL_UNIT='your_org_unit' - TAKSERVER_CERT_PASS='your_takserver_cert_password' - ADMIN_CERT_NAME='admin_username' - ADMIN_CERT_PASS='admin_password' - ``` +1. Download TAK server files from the official TAK.gov website +2. Obtain through proper military/government channels +3. Purchase through authorized distributors -3. **Start the services:** - ```bash - docker-compose up - ``` +**You must have a valid license to use TAK server software.** + +## Prerequisites + +1. **Valid TAK Server License**: You must have proper licensing/authorization to use TAK server +2. **TAK Server Files**: Download `takserver-docker-X.Y-RELEASE-Z.zip` from official sources +3. **Docker & Docker Compose**: Installed on your system + +## Setup Instructions + +### Step 1: Obtain TAK Server Files +- Download the TAK server Docker release from official channels +- Place the `takserver-docker-X.Y-RELEASE-Z.zip` file in the `takserver-release/` directory +- The container will automatically detect and use the latest version + +### Step 2: File Structure +``` +/docker/services/tak/ +├── Dockerfile # Hybrid container +├── entrypoint.sh # Main container entrypoint +├── scripts/ # Helper scripts +│ ├── tak-version.sh # TAK version detection +│ ├── db-setup.sh # Database setup +│ └── healthcheck.sh # Health monitoring +├── docker-compose.yml # Docker Compose configuration +├── README.md # This documentation +├── build.sh # Build script +├── validate.sh # Setup validation script +├── original-files/ # Original Dockerfile templates +└── takserver-release/ # Place your TAK server files here + └── takserver-docker-X.Y-RELEASE-Z.zip # Your TAK server files +``` ## Features -- **Self-contained**: Automatically extracts TAK Server from release files -- **Single image**: Everything built into one Docker image (plus database) -- **Environment driven**: All configuration through environment variables -- **Automatic setup**: Certificates, database schema, and admin user created automatically -- **Persistent data**: Docker volumes for data persistence -- **Simple deployment**: Just build and run +- **Hybrid Architecture**: Combines TAK server and PostgreSQL database in one container +- **Automatic Version Detection**: Finds the latest `takserver-docker-X.Y-RELEASE-Z.zip` file +- **Semantic Versioning**: Uses semantic version sorting to determine the latest release +- **Complete Setup**: Includes PostGIS extension for spatial data support +- **Runtime TAK Setup**: TAK server files are processed at container startup (licensing compliant) +- **User-Provided Files**: No TAK server files included in the image -## Structure +## Usage -- `Dockerfile` - Self-contained TAK Server image -- `docker-compose.yml` - Orchestration with PostgreSQL database -- `EDIT_ME.env` - Environment variables configuration -- `build.sh` - Build script -- `scripts/docker_entrypoint.sh` - Main entrypoint with extraction and startup logic -- `scripts/coreConfigEnvHelper.py` - Configuration helper +### Option 1: Using Docker Compose (Recommended) -## Environment Variables +**First, ensure you have TAK server files in the correct directory:** +```bash +# Verify your TAK server files +ls -la takserver-release/ +# Should show: takserver-docker-X.Y-RELEASE-Z.zip -### Required -- `POSTGRES_PASSWORD` - Database password -- `CA_NAME` - Certificate Authority name -- `CA_PASS` - Certificate Authority password -- `STATE` - State for certificate generation -- `CITY` - City for certificate generation -- `ORGANIZATION` - Organization for certificate generation -- `ORGANIZATIONAL_UNIT` - Organizational unit for certificate generation -- `TAKSERVER_CERT_PASS` - TAK Server certificate password -- `ADMIN_CERT_NAME` - Admin username -- `ADMIN_CERT_PASS` - Admin password +# Build and start the hybrid container +docker-compose up -d -### Optional (with defaults) -- `CONFIG_MAX_HEAP=512` - Config service heap size (MB) -- `MESSAGING_MAX_HEAP=2048` - Messaging service heap size (MB) -- `API_MAX_HEAP=1024` - API service heap size (MB) -- `PLUGIN_MANAGER_MAX_HEAP=512` - Plugin Manager heap size (MB) -- `POSTGRES_DB=cot` - Database name -- `POSTGRES_USER=martiuser` - Database user -- `POSTGRES_URL=jdbc:postgresql://takdb:5432/cot` - Database URL +# View logs to monitor startup +docker-compose logs -f tak-hybrid + +# Stop the container +docker-compose down +``` + +### Option 2: Using Docker directly + +```bash +# Build the image +docker build -t tak-hybrid . + +# Run the container (replace /path/to/tak/files with your actual path) +docker run -d \ + --name tak-hybrid \ + -p 5432:5432 \ + -p 8080:8080 \ + -p 8443:8443 \ + -p 8444:8444 \ + -v /path/to/tak/files:/takserver-zip:ro \ + -v tak-data:/opt/tak/data \ + -v tak-logs:/opt/tak/logs \ + tak-hybrid +``` + +## TAK Server Release Files + +Place your TAK server release files in the `takserver-release/` directory. The container will automatically detect and use the latest version based on semantic versioning. + +**Supported filename format**: `takserver-docker-X.Y-RELEASE-Z.zip` + +Examples: +- `takserver-docker-5.4-RELEASE-19.zip` +- `takserver-docker-5.5-RELEASE-1.zip` +- `takserver-docker-6.0-RELEASE-5.zip` ## Ports -- `8443` - HTTPS API -- `8444` - Certificate enrollment -- `8446` - Federation -- `8089` - Web interface -- `9000` - Messaging -- `9001` - Streaming +- **5432**: PostgreSQL database +- **8080**: TAK server web interface (HTTP) +- **8443**: TAK server web interface (HTTPS) +- **8444**: TAK server certificate enrollment +- **8446**: TAK server API -## Volumes +## Database Configuration -- `takserver_data` - TAK Server data (logs, certs, config) -- `takdb_data` - PostgreSQL data +The container automatically sets up PostgreSQL with: +- Database: `cot` +- User: `martiuser` +- Password: `password` +- PostGIS extension enabled -## What the entrypoint does +## Environment Variables -1. **Extract TAK Server** - Automatically extracts from `/takserver-release/` if not already done -2. **Validate environment** - Checks all required environment variables -3. **Initialize directories** - Creates necessary data directories -4. **Generate certificates** - Creates CA, server, and admin certificates if needed -5. **Configure TAK Server** - Updates CoreConfig.xml with environment variables -6. **Initialize database** - Waits for database and runs schema setup -7. **Start services** - Launches all TAK Server services in correct order -8. **Create admin user** - Adds the admin user after services are ready +The following environment variables can be customized in the docker-compose.yml: -## Manual file editing +- `POSTGRES_DB`: Database name (default: cot) +- `POSTGRES_USER`: Database user (default: martiuser) +- `POSTGRES_PASSWORD`: Database password (default: password) -If you need to customize CoreConfig.xml or other configuration files beyond what environment variables provide, you can: +## Helper Scripts -1. Start the container once to generate initial files -2. Stop the container -3. Edit files in the `takserver_data` volume -4. Restart the container +The container includes several helper scripts for management and troubleshooting: -The entrypoint will preserve existing configuration files and only regenerate what's missing. +### TAK Version Detection (`/scripts/tak-version.sh`) +```bash +# Find latest TAK release +docker exec tak-hybrid /scripts/tak-version.sh /takserver-zip latest + +# List all available releases +docker exec tak-hybrid /scripts/tak-version.sh /takserver-zip list + +# Get version from specific file +docker exec tak-hybrid /scripts/tak-version.sh /takserver-zip version /takserver-zip/takserver-docker-5.4-RELEASE-19.zip +``` + +### Database Setup (`/scripts/db-setup.sh`) +```bash +# Full database setup +docker exec tak-hybrid /scripts/db-setup.sh setup + +# Test database connection +docker exec tak-hybrid /scripts/db-setup.sh test + +# Print database configuration +docker exec tak-hybrid /scripts/db-setup.sh config +``` + +### Health Monitoring (`/scripts/healthcheck.sh`) +```bash +# Run all health checks +docker exec tak-hybrid /scripts/healthcheck.sh all + +# Check specific components +docker exec tak-hybrid /scripts/healthcheck.sh postgres +docker exec tak-hybrid /scripts/healthcheck.sh database +docker exec tak-hybrid /scripts/healthcheck.sh tak-process +``` + +## Troubleshooting + +### Check container logs +```bash +docker-compose logs tak-hybrid +``` + +### Access the container shell +```bash +docker-compose exec tak-hybrid /bin/bash +``` + +### Verify PostgreSQL is running +```bash +docker-compose exec tak-hybrid pg_isready -U martiuser -d cot +``` + +### Check TAK server status +```bash +docker-compose exec tak-hybrid ps aux | grep tak +``` + +## Error Handling + +The container includes comprehensive error checking: + +### Missing TAK Server Files +``` +ERROR: No TAK server files found! +Please mount a directory containing takserver-docker-X.Y-RELEASE-Z.zip files to /takserver-zip +``` +**Solution**: Ensure you have properly mounted the directory containing your TAK server files. + +### Invalid File Format +``` +ERROR: No takserver-docker-X.Y-RELEASE-Z.zip file found in /takserver-zip/ +Please ensure you have a file matching the pattern: takserver-docker-X.Y-RELEASE-Z.zip +``` +**Solution**: Verify your TAK server file follows the correct naming convention. + +### Licensing Compliance + +This container design ensures license compliance by: +- **Not redistributing TAK server files** +- **Requiring users to provide their own licensed files** +- **Processing files only at runtime** +- **Clear documentation of licensing requirements** + +## Legal Notice + +TAK server software is subject to export control regulations and licensing requirements. Users are responsible for: +- Obtaining proper licenses/authorization +- Compliance with export control laws +- Following all applicable regulations +- Ensuring authorized use only + +This container does not include or redistribute any TAK server software files. diff --git a/build.sh b/build.sh deleted file mode 100755 index 349f11a..0000000 --- a/build.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Simple build script -set -e - -echo "Building TAK Server Docker image..." - -# Check if takserver-release directory exists -if [[ ! -d "takserver-release" ]]; then - echo "Creating symlink to takserver-release..." - ln -sf ../../takserver-release takserver-release -fi - -# Build the Docker image -docker build -t takserver:latest . - -echo "Build complete!" -echo "Edit EDIT_ME.env with your configuration, then run:" -echo "docker-compose up" diff --git a/docker-compose.yml b/docker-compose.yml index 0500553..b986496 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,41 +1,29 @@ -version: '3.4' +networks: + webserver: + external: true + + +volumes: + takserver: + postgres-data: services: - takserver: - image: takserver:latest + tak-hybrid: build: . - env_file: - - 'EDIT_ME.env' - volumes: - - 'takserver_data:/opt/tak/data' - depends_on: - - takdb - networks: - - taknet + # image: git.merith.xyz/oci/takserver:nightly + restart: no ports: - - '8089:8089' - - '8443:8443' - - '8444:8444' - - '8446:8446' - - '9000:9000' - - '9001:9001' - - takdb: - image: postgis/postgis:15-3.3 + - "5432:5432" # PostgreSQL + - "8080:8080" # TAK server web UI (typical port) + - "8443:8443" # TAK server HTTPS (typical port) + - "8444:8444" # TAK server cert enrollment (typical port) networks: - - taknet - environment: - - POSTGRES_DB=cot - - POSTGRES_USER=martiuser - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - webserver volumes: - - 'takdb_data:/var/lib/postgresql/data' - -networks: - taknet: - -volumes: - takserver_data: - driver: local - takdb_data: - driver: local + - ./takserver-release:/takserver-zip:ro + - ./data/takserver:/opt/tak + - ./data/postgres-data:/var/lib/postgresql/15/main + environment: + POSTGRES_DB: default_db + POSTGRES_USER: default_user + POSTGRES_PASSWORD: default_password \ No newline at end of file diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..4c0be63 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,354 @@ +#!/bin/bash +set -e + +# Colors for logging +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_debug() { + echo -e "${BLUE}[DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_info "Starting TAK Server Hybrid Container..." + +# Ensure proper ownership of key directories +log_debug "Enforcing ownership permissions..." +chown -R tak:tak /opt/tak 2>/dev/null || true +chown -R postgres:postgres /var/lib/postgresql 2>/dev/null || true +log_debug "Ownership permissions enforced" + +# Source helper scripts +log_debug "Sourcing helper scripts..." +source /scripts/tak-version.sh +log_debug "Helper scripts loaded successfully" + +# Check if TAK server files are provided +log_info "Checking for TAK server files..." +log_debug "Looking for files in /takserver-zip directory..." + +if [ ! -d "/takserver-zip" ]; then + log_error "Mount point /takserver-zip does not exist!" + log_error "Please ensure you mount a directory containing TAK server files" + log_error "Example: docker run -v /path/to/tak/files:/takserver-zip:ro ..." + exit 1 +fi + +# Check if directory is empty +if [ ! "$(ls -A /takserver-zip 2>/dev/null)" ]; then + log_error "Directory /takserver-zip is empty!" + log_error "Please place takserver-docker-X.Y-RELEASE-Z.zip files in the mounted directory" + log_debug "Directory contents:" + ls -l /takserver-zip/ || log_debug "Cannot list directory contents" + exit 1 +fi + +# List all files in the directory for debugging +log_debug "Contents of /takserver-zip:" +ls -l /takserver-zip/ | while read line; do + log_debug " $line" +done + +# Check for zip files specifically +ZIP_COUNT=$(find /takserver-zip -name "*.zip" -type f | wc -l) +log_debug "Found $ZIP_COUNT zip files in /takserver-zip" + +if [ $ZIP_COUNT -eq 0 ]; then + log_error "No zip files found in /takserver-zip!" + log_error "Please ensure you have takserver-docker-X.Y-RELEASE-Z.zip files" + log_debug "Available files:" + find /takserver-zip -type f | while read file; do + log_debug " $(basename $file)" + done + while true; do sleep 3600; done +fi + +# Check for TAK server specific zip files +TAK_ZIP_COUNT=$(find /takserver-zip -name "takserver-docker-*-RELEASE-*.zip" -type f | wc -l) +log_debug "Found $TAK_ZIP_COUNT TAK server zip files" + +if [ $TAK_ZIP_COUNT -eq 0 ]; then + log_error "No TAK server zip files found matching pattern 'takserver-docker-*-RELEASE-*.zip'!" + log_error "Available zip files:" + find /takserver-zip -name "*.zip" -type f | while read file; do + log_error " $(basename $file)" + done + log_error "Required format: takserver-docker-X.Y-RELEASE-Z.zip" + log_error "Example: takserver-docker-5.4-RELEASE-19.zip" + exit 1 +fi + +# Use the helper script to find the latest TAK release +log_info "Finding latest TAK server release..." +LATEST_ZIP=$(find_latest_tak_release /takserver-zip) +if [ $? -ne 0 ]; then + log_error "Failed to find latest TAK release: $LATEST_ZIP" + log_info "Available TAK releases:" + list_tak_releases /takserver-zip + exit 1 +fi + +log_info "Found latest TAK server release: $(basename $LATEST_ZIP)" +log_info "Version: $(get_tak_version $LATEST_ZIP)" +log_debug "Full path: $LATEST_ZIP" + +# Extract the zip file if not already extracted +if [ ! -f /opt/tak/configureInDocker.sh ]; then + log_info "TAK server files not found - extracting from ZIP..." + log_debug "Using extraction script: /scripts/tak-extract.sh" + + # Use the extraction script + if /scripts/tak-extract.sh extract "$LATEST_ZIP" /opt/tak; then + log_info "TAK server extraction completed successfully" + + # Set proper permissions + /scripts/tak-extract.sh permissions /opt/tak tak:tak + + # Verify installation + if /scripts/tak-extract.sh verify /opt/tak; then + log_info "TAK server installation verified" + else + log_error "TAK server installation verification failed!" + exit 1 + fi + else + log_error "Failed to extract TAK server files!" + exit 1 + fi +else + log_info "TAK server files already exist - skipping extraction" + log_debug "Found existing configureInDocker.sh at /opt/tak/configureInDocker.sh" + + # Ensure permissions are correct on existing files + log_debug "Ensuring correct permissions on existing TAK files..." + /scripts/tak-extract.sh permissions /opt/tak tak:tak + + # Also enforce ownership at the directory level + log_debug "Enforcing TAK directory ownership..." + chown -R tak:tak /opt/tak +fi + +# Start PostgreSQL +log_info "Starting PostgreSQL..." + +# Ensure PostgreSQL directories have correct ownership +log_debug "Enforcing PostgreSQL directory ownership..." +chown -R postgres:postgres /var/lib/postgresql +chown -R postgres:postgres /var/run/postgresql 2>/dev/null || true + +# Initialize PostgreSQL if not already done +if [ ! -f /var/lib/postgresql/15/main/PG_VERSION ]; then + log_info "Initializing PostgreSQL database cluster..." + if sudo -u postgres /usr/lib/postgresql/15/bin/initdb -D /var/lib/postgresql/15/main; then + log_info "PostgreSQL initialized successfully" + + # Configure PostgreSQL + log_info "Configuring PostgreSQL..." + + # Create postgresql.conf + log_debug "Creating postgresql.conf..." + cat > /tmp/postgresql.conf < /tmp/pg_hba.conf < /tmp/postgresql.conf < /tmp/pg_hba.conf </dev/null; then + log_debug "PostgreSQL process is still running" +else + log_error "PostgreSQL process died immediately!" + log_error "Checking system logs for errors..." + # Try to get any error output + journalctl -u postgresql --no-pager --lines=10 2>/dev/null || log_debug "No journalctl available" + exit 1 +fi + +# Wait for PostgreSQL to start and setup database +log_info "Waiting for PostgreSQL to be ready..." +POSTGRES_READY=0 +for i in {1..30}; do + if pg_isready -h localhost -p 5432 >/dev/null 2>&1; then + POSTGRES_READY=1 + log_info "PostgreSQL is ready after ${i} seconds" + break + fi + log_debug "PostgreSQL not ready yet, waiting... (attempt $i/30)" + sleep 1 +done + +if [ $POSTGRES_READY -eq 0 ]; then + log_error "PostgreSQL failed to become ready after 30 seconds!" + log_error "Checking PostgreSQL process status..." + if kill -0 $POSTGRES_PID 2>/dev/null; then + log_error "PostgreSQL process is running but not accepting connections" + else + log_error "PostgreSQL process has died" + fi + exit 1 +fi + +# Use the database setup script +log_info "Setting up database..." +if /scripts/db-setup.sh setup; then + log_info "Database setup completed successfully" +else + log_error "Database setup failed!" + exit 1 +fi + +# Run database configuration if it exists +if [ -f "/opt/tak/db-utils/configureInDocker.sh" ]; then + log_info "Configuring TAK database..." + /opt/tak/db-utils/configureInDocker.sh & + DB_CONFIG_PID=$! + log_debug "TAK database configuration started with PID: $DB_CONFIG_PID" + sleep 10 +else + log_warn "TAK database configuration script not found, skipping..." +fi + +# Start TAK server +if [ -f "/opt/tak/configureInDocker.sh" ]; then + log_info "Starting TAK server..." + log_debug "Executing: /opt/tak/configureInDocker.sh init" + exec /opt/tak/configureInDocker.sh init +else + log_error "TAK server configuration script not found!" + log_error "Expected file: /opt/tak/configureInDocker.sh" + log_error "The extracted TAK server files may be incomplete or corrupted." + log_debug "Contents of /opt/tak:" + ls -la /opt/tak/ | while read line; do + log_debug " $line" + done + exit 1 +fi \ No newline at end of file diff --git a/manage.sh b/manage.sh new file mode 100755 index 0000000..6c3be70 --- /dev/null +++ b/manage.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# TAK Server Management Script +# This script provides easy access to container management functions + +CONTAINER_NAME="tak-hybrid" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if container is running +check_container() { + if ! docker ps | grep -q "$CONTAINER_NAME"; then + log_error "Container '$CONTAINER_NAME' is not running" + log_info "Start the container with: docker-compose up -d" + exit 1 + fi +} + +# Execute script in container +exec_script() { + check_container + docker exec "$CONTAINER_NAME" "$@" +} + +# Show usage +show_usage() { + echo "TAK Server Management Script" + echo "Usage: $0 [options]" + echo "" + echo "Commands:" + echo " health [component] - Run health checks" + echo " db - Database operations" + echo " version [action] - TAK version operations" + echo " logs - Show container logs" + echo " shell - Open shell in container" + echo " status - Show container status" + echo " restart - Restart container" + echo "" + echo "Examples:" + echo " $0 health all - Run all health checks" + echo " $0 db test - Test database connection" + echo " $0 version list - List available TAK versions" + echo " $0 logs - Show recent logs" +} + +case "$1" in + "health") + shift + exec_script /scripts/healthcheck.sh "$@" + ;; + "db") + shift + exec_script /scripts/db-setup.sh "$@" + ;; + "version") + shift + exec_script /scripts/tak-version.sh /takserver-zip "$@" + ;; + "logs") + docker-compose logs -f tak-hybrid + ;; + "shell") + check_container + docker exec -it "$CONTAINER_NAME" /bin/bash + ;; + "status") + if docker ps | grep -q "$CONTAINER_NAME"; then + log_info "Container is running" + docker ps | grep "$CONTAINER_NAME" + else + log_warn "Container is not running" + fi + ;; + "restart") + log_info "Restarting container..." + docker-compose restart tak-hybrid + ;; + *) + show_usage + exit 1 + ;; +esac diff --git a/scripts/coreConfigEnvHelper.py b/scripts/coreConfigEnvHelper.py deleted file mode 100644 index 9a718a4..0000000 --- a/scripts/coreConfigEnvHelper.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os - -from lxml import etree - -parser = argparse.ArgumentParser('CoreConfig Configuration Helper') -parser.add_argument('source', metavar='SOURCE', type=str, help='The source CoreConfig path') -parser.add_argument('target', metavar='TARGET', type=str, help='The target CoreConfig path') - - -CORE_CONFIG_NAMESPACE = 'http://bbn.com/marti/xml/config' - - -class ConfigEntry: - def __init__(self, env_var, xpath, attribute_name, required, hide_value): - self._env_var = env_var # type: str - self._xpath = xpath # type: str - self._attribute_name = attribute_name # type: str - self._required = required # type: bool - self._hide_value = hide_value # type: bool - - @property - def attribute_name(self): - return self._attribute_name - - @property - def xpath(self): - return self._xpath - - @property - def env_var(self): - return self._env_var - - @property - def required(self): - return self._required - - @property - def hide_value(self): - return self._hide_value - - def value(self): - if self._env_var in os.environ.keys(): - return os.environ[self._env_var] - else: - return None - - -CONFIG_VALUES = [ - ConfigEntry('POSTGRES_URL', 'tak:repository/tak:connection', 'url', False, False), - ConfigEntry('POSTGRES_USER', 'tak:repository/tak:connection', 'username', False, False), - ConfigEntry('POSTGRES_PASSWORD', 'tak:repository/tak:connection', 'password', True, True), - ConfigEntry('TAKSERVER_CERT_PASS', 'tak:security/tak:tls', 'keystorePass', True, True), - ConfigEntry('CA_PASS', 'tak:security/tak:tls', 'truststorePass', True, True) -] - - -class CoreConfigHelper: - def __init__(self, source_filepath): - self._source_filepath = source_filepath - self._tree = etree.parse(open(source_filepath), etree.XMLParser()) - self._root = self._tree.getroot() - self._namespaces = { - 'tak': CORE_CONFIG_NAMESPACE - } - - def find(self, xpath): - """ - :rtype: etree.Element - """ - results = self._tree.findall(path=xpath, namespaces=self._namespaces) - - if len(results) > 1: - raise Exception('XPath expressions that return multiple elements are not currently supported!') - return results[0] - - def process_configuration(self, config_values, target_filepath): - """ - :type config_values: list[ConfigEntry] - """ - for config in config_values: - value = config.value() - if value is None: - if config.required: - raise Exception('The environment variable "' + config.env_var + '" is required!') - else: - element = self.find(config.xpath) - element.set(config.attribute_name, value) - if config.hide_value: - print(config.xpath.replace('tak:', '') + ' attribute ' + config.attribute_name + ' set to ********') - else: - print(config.xpath.replace('tak:', '') + ' attribute ' + config.attribute_name + ' set to "' + value + '"') - - self._tree.write(target_filepath, xml_declaration=True, encoding='UTF-8') - - -def main(): - args = parser.parse_args() - helper = CoreConfigHelper(args.source) - helper.process_configuration(CONFIG_VALUES, args.target) - - -if __name__ == '__main__': - main() diff --git a/scripts/db-setup.sh b/scripts/db-setup.sh new file mode 100644 index 0000000..4bfd468 --- /dev/null +++ b/scripts/db-setup.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# Database Setup Script for TAK Server +set -e + +# Database configuration +DB_NAME="${DB_NAME:-cot}" +DB_USER="${DB_USER:-martiuser}" +DB_PASSWORD="${DB_PASSWORD:-password}" +DB_HOST="${DB_HOST:-localhost}" +DB_PORT="${DB_PORT:-5432}" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if PostgreSQL is running +check_postgres() { + if ! pg_isready -q -h "$DB_HOST" -p "$DB_PORT"; then + log_error "PostgreSQL is not running or not accessible" + return 1 + fi + log_info "PostgreSQL is running" +} + +# Create database user if not exists +create_db_user() { + log_info "Creating database user '$DB_USER'..." + + if sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" | grep -q 1; then + log_warn "User '$DB_USER' already exists" + else + sudo -u postgres createuser --createdb --no-superuser --no-createrole "$DB_USER" + log_info "User '$DB_USER' created" + fi + + # Set password + sudo -u postgres psql -c "ALTER USER $DB_USER PASSWORD '$DB_PASSWORD';" + log_info "Password set for user '$DB_USER'" +} + +# Create database if not exists +create_database() { + log_info "Creating database '$DB_NAME'..." + + if sudo -u postgres psql -lqt | cut -d \| -f 1 | grep -qw "$DB_NAME"; then + log_warn "Database '$DB_NAME' already exists" + else + sudo -u postgres createdb -O "$DB_USER" "$DB_NAME" + log_info "Database '$DB_NAME' created" + fi +} + +# Install PostGIS extension +install_postgis() { + log_info "Installing PostGIS extension..." + + if sudo -u postgres psql -d "$DB_NAME" -tAc "SELECT 1 FROM pg_extension WHERE extname='postgis'" | grep -q 1; then + log_warn "PostGIS extension already installed" + else + sudo -u postgres psql -d "$DB_NAME" -c "CREATE EXTENSION postgis;" + log_info "PostGIS extension installed" + fi +} + +# Test database connection +test_connection() { + log_info "Testing database connection..." + + if PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT version();" > /dev/null 2>&1; then + log_info "Database connection successful" + else + log_error "Database connection failed" + return 1 + fi +} + +# Main setup function +setup_database() { + log_info "Starting database setup..." + + check_postgres + create_db_user + create_database + install_postgis + test_connection + + log_info "Database setup completed successfully" +} + +# Print database configuration +print_config() { + echo "Database Configuration:" + echo " Host: $DB_HOST" + echo " Port: $DB_PORT" + echo " Database: $DB_NAME" + echo " User: $DB_USER" + echo " Password: [REDACTED]" +} + +# Main execution +case "${1:-setup}" in + "setup") + setup_database + ;; + "test") + test_connection + ;; + "config") + print_config + ;; + "user") + create_db_user + ;; + "db") + create_database + ;; + "postgis") + install_postgis + ;; + *) + echo "Usage: $0 [setup|test|config|user|db|postgis]" + echo " setup - Full database setup (default)" + echo " test - Test database connection" + echo " config - Print database configuration" + echo " user - Create database user only" + echo " db - Create database only" + echo " postgis - Install PostGIS extension only" + exit 1 + ;; +esac diff --git a/scripts/docker_entrypoint.sh b/scripts/docker_entrypoint.sh deleted file mode 100644 index e43ac01..0000000 --- a/scripts/docker_entrypoint.sh +++ /dev/null @@ -1,241 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Environment variable defaults -CONFIG_MAX_HEAP=${CONFIG_MAX_HEAP:-512} -MESSAGING_MAX_HEAP=${MESSAGING_MAX_HEAP:-2048} -API_MAX_HEAP=${API_MAX_HEAP:-1024} -PLUGIN_MANAGER_MAX_HEAP=${PLUGIN_MANAGER_MAX_HEAP:-512} -POSTGRES_DB=${POSTGRES_DB:-cot} -POSTGRES_USER=${POSTGRES_USER:-martiuser} -POSTGRES_URL=${POSTGRES_URL:-jdbc:postgresql://takdb:5432/cot} - -TR=/opt/tak -CR=${TR}/certs -CONFIG=${TR}/data/CoreConfig.xml -TAKIGNITECONFIG=${TR}/data/TAKIgniteConfig.xml -CONFIG_PID=null -MESSAGING_PID=null -API_PID=null -PM_PID=null - -check_env_var() { - if [[ "${!1}" == "" ]]; then - echo "ERROR: Environment variable '${1}' must be set for ${2}!" - exit 1 - fi -} - -cleanup() { - echo "Shutting down TAK Server..." - if [ $CONFIG_PID != null ]; then - kill $CONFIG_PID 2>/dev/null || true - fi - if [ $MESSAGING_PID != null ]; then - kill $MESSAGING_PID 2>/dev/null || true - fi - if [ $API_PID != null ]; then - kill $API_PID 2>/dev/null || true - fi - if [ $PM_PID != null ]; then - kill $PM_PID 2>/dev/null || true - fi -} - -trap cleanup SIGINT SIGTERM - -# Extract TAK Server if not already done -if [[ ! -d "${TR}" ]] || [[ ! -f "${TR}/takserver.war" ]]; then - echo "Extracting TAK Server..." - - # Find the release zip file - RELEASE_FILE=$(find /takserver-release -name "takserver-docker-*.zip" | head -1) - - if [[ -z "$RELEASE_FILE" ]]; then - echo "ERROR: No TAK Server release file found in /takserver-release" - exit 1 - fi - - echo "Found release file: $RELEASE_FILE" - - # Extract the release file - unzip -q "$RELEASE_FILE" -d /tmp/takserver_extract - - # Find the extracted directory - EXTRACTED_DIR=$(find /tmp/takserver_extract -name "takserver-docker-*" -type d | head -1) - - if [[ -z "$EXTRACTED_DIR" ]]; then - echo "ERROR: Could not find extracted TAK Server directory" - exit 1 - fi - - echo "Copying TAK Server files..." - - # Create base directory - mkdir -p "${TR}" - - # Copy all files from the extracted directory to tak directory - cp -r "${EXTRACTED_DIR}/tak"/* "${TR}/" - - # Make scripts executable - find "${TR}" -name "*.sh" -exec chmod +x {} \; - - # Copy our custom files - cp /opt/scripts/coreConfigEnvHelper.py "${TR}/coreConfigEnvHelper.py" - - # Clean up - rm -rf /tmp/takserver_extract - - echo "TAK Server extraction complete!" -fi - -# Validate required environment variables -check_env_var POSTGRES_PASSWORD "database connection" -check_env_var CA_NAME "Certificate Authority Name" -check_env_var CA_PASS "Certificate Authority Password" -check_env_var STATE "Certificate Authority generation" -check_env_var CITY "Certificate Authority generation" -check_env_var ORGANIZATION "Certificate Authority generation" -check_env_var ORGANIZATIONAL_UNIT "Certificate Authority generation" -check_env_var ADMIN_CERT_NAME "TAK Server management certificate" -check_env_var ADMIN_CERT_PASS "TAK Server management certificate password" -check_env_var TAKSERVER_CERT_PASS "TAK Server instance certificate password" - -# Initialize data directories -mkdir -p "${TR}/data/logs" "${TR}/data/certs" - -# Seed initial certificate data if necessary -if [[ ! -d "${TR}/data/certs" ]] || [[ -z "$(ls -A "${TR}/data/certs")" ]]; then - echo "Copying initial certificate configuration..." - cp -R ${TR}/certs/* ${TR}/data/certs/ -else - echo "Using existing certificates." -fi - -# Move original certificate data and symlink to certificate data in data dir -if [[ -d "${TR}/certs" ]] && [[ ! -L "${TR}/certs" ]]; then - mv ${TR}/certs ${TR}/certs.orig - ln -s "${TR}/data/certs" "${TR}/certs" -fi - -# Seed initial CoreConfig.xml if necessary -if [[ ! -f "${CONFIG}" ]]; then - echo "Copying initial CoreConfig.xml..." - if [[ -f "${TR}/CoreConfig.xml" ]]; then - cp ${TR}/CoreConfig.xml ${CONFIG} - mv ${TR}/CoreConfig.xml ${TR}/CoreConfig.xml.orig - else - cp ${TR}/CoreConfig.example.xml ${CONFIG} - fi -else - echo "Using existing CoreConfig.xml." -fi - -# Seed initial TAKIgniteConfig.xml if necessary -if [[ ! -f "${TAKIGNITECONFIG}" ]]; then - echo "Copying initial TAKIgniteConfig.xml..." - if [[ -f "${TR}/TAKIgniteConfig.xml" ]]; then - cp ${TR}/TAKIgniteConfig.xml ${TAKIGNITECONFIG} - mv ${TR}/TAKIgniteConfig.xml ${TR}/TAKIgniteConfig.xml.orig - else - cp ${TR}/TAKIgniteConfig.example.xml ${TAKIGNITECONFIG} - fi -else - echo "Using existing TAKIgniteConfig.xml." -fi - -# Symlink the log directory -if [[ ! -L "${TR}/logs" ]]; then - ln -sf "${TR}/data/logs" "${TR}/logs" -fi - -cd ${CR} - -# Generate certificates if needed -if [[ ! -f "${CR}/files/root-ca.pem" ]]; then - echo "Generating root CA certificate..." - CAPASS=${CA_PASS} bash /opt/tak/certs/makeRootCa.sh --ca-name "${CA_NAME}" -else - echo "Using existing root CA." -fi - -if [[ ! -f "${CR}/files/intermediate-signing.jks" ]]; then - echo "Making new signing certificate..." - export CAPASS=${CA_PASS} - yes | /opt/tak/certs/makeCert.sh ca intermediate -else - echo "Using existing intermediate CA certificate." -fi - -if [[ ! -f "${CR}/files/takserver.pem" ]]; then - echo "Generating TAK Server certificate..." - CAPASS=${CA_PASS} PASS="${TAKSERVER_CERT_PASS}" bash /opt/tak/certs/makeCert.sh server takserver -else - echo "Using existing takserver certificate." -fi - -if [[ ! -f "${CR}/files/${ADMIN_CERT_NAME}.pem" ]]; then - echo "Generating admin certificate..." - CAPASS=${CA_PASS} PASS="${ADMIN_CERT_PASS}" bash /opt/tak/certs/makeCert.sh client "${ADMIN_CERT_NAME}" -else - echo "Using existing ${ADMIN_CERT_NAME} certificate." -fi - -# Set permissions -chmod -R 755 ${TR}/data/ - -# Configure CoreConfig.xml with environment variables -echo "Configuring CoreConfig.xml..." -python3 ${TR}/coreConfigEnvHelper.py "${CONFIG}" "${CONFIG}" - -# Wait for database to be ready -echo "Waiting for database to be ready..." -until nc -z $(echo $POSTGRES_URL | sed 's/.*:\/\/\([^:]*\):.*/\1/') $(echo $POSTGRES_URL | sed 's/.*:\([0-9]*\)\/.*/\1/'); do - echo "Waiting for database connection..." - sleep 5 -done - -# Initialize database schema -echo "Initializing database schema..." -java -jar ${TR}/db-utils/SchemaManager.jar -url ${POSTGRES_URL} -user ${POSTGRES_USER} -password ${POSTGRES_PASSWORD} upgrade - -cd ${TR} - -# Source environment -. ./setenv.sh - -echo "Starting TAK Server services..." - -# Start services in background -echo "Starting Config service..." -java -jar -Xmx${CONFIG_MAX_HEAP}m -Dspring.profiles.active=config takserver.war & -CONFIG_PID=$! - -echo "Starting Messaging service..." -java -jar -Xmx${MESSAGING_MAX_HEAP}m -Dspring.profiles.active=messaging takserver.war & -MESSAGING_PID=$! - -echo "Starting API service..." -java -jar -Xmx${API_MAX_HEAP}m -Dspring.profiles.active=api -Dkeystore.pkcs12.legacy takserver.war & -API_PID=$! - -echo "Starting Plugin Manager service..." -java -jar -Xmx${PLUGIN_MANAGER_MAX_HEAP}m -Dloader.path=WEB-INF/lib-provided,WEB-INF/lib,WEB-INF/classes,file:lib/ takserver-pm.jar & -PM_PID=$! - -# Wait for services to start -echo "Waiting for services to start..." -sleep 60 - -# Add admin user -echo "Adding admin user..." -TAKCL_CORECONFIG_PATH="${CONFIG}" -TAKCL_TAKIGNITECONFIG_PATH="${TAKIGNITECONFIG}" -java -jar /opt/tak/utils/UserManager.jar certmod -A "/opt/tak/certs/files/${ADMIN_CERT_NAME}.pem" - -echo "TAK Server is ready!" -echo "Admin user '${ADMIN_CERT_NAME}' has been added." - -# Wait for plugin manager to complete (this keeps the container running) -wait $PM_PID diff --git a/scripts/healthcheck.sh b/scripts/healthcheck.sh new file mode 100644 index 0000000..3d6acc4 --- /dev/null +++ b/scripts/healthcheck.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# TAK Server Health Check Script +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_check() { + echo -e "${BLUE}[CHECK]${NC} $1" +} + +# Check if PostgreSQL is running +check_postgres() { + log_check "Checking PostgreSQL..." + + if pg_isready -q -h localhost -p 5432; then + log_info "PostgreSQL is running" + return 0 + else + log_error "PostgreSQL is not running" + return 1 + fi +} + +# Check database connectivity +check_database() { + log_check "Checking database connectivity..." + + if PGPASSWORD="password" psql -h localhost -p 5432 -U martiuser -d cot -c "SELECT 1;" > /dev/null 2>&1; then + log_info "Database connection successful" + return 0 + else + log_error "Database connection failed" + return 1 + fi +} + +# Check PostGIS extension +check_postgis() { + log_check "Checking PostGIS extension..." + + if PGPASSWORD="password" psql -h localhost -p 5432 -U martiuser -d cot -tAc "SELECT 1 FROM pg_extension WHERE extname='postgis'" | grep -q 1; then + log_info "PostGIS extension is installed" + return 0 + else + log_error "PostGIS extension is not installed" + return 1 + fi +} + +# Check TAK server files +check_tak_files() { + log_check "Checking TAK server files..." + + if [ -f "/opt/tak/configureInDocker.sh" ]; then + log_info "TAK server configuration script found" + return 0 + else + log_error "TAK server configuration script not found" + return 1 + fi +} + +# Check TAK server process +check_tak_process() { + log_check "Checking TAK server process..." + + if pgrep -f "takserver" > /dev/null; then + log_info "TAK server process is running" + return 0 + else + log_warn "TAK server process not found" + return 1 + fi +} + +# Check network ports +check_ports() { + log_check "Checking network ports..." + + local ports=(5432 8080 8443 8444 8446) + local all_good=true + + for port in "${ports[@]}"; do + if netstat -tuln | grep -q ":$port "; then + log_info "Port $port is listening" + else + log_warn "Port $port is not listening" + all_good=false + fi + done + + if [ "$all_good" = true ]; then + return 0 + else + return 1 + fi +} + +# Check disk space +check_disk_space() { + log_check "Checking disk space..." + + local usage=$(df /opt/tak | tail -1 | awk '{print $5}' | sed 's/%//') + + if [ "$usage" -lt 80 ]; then + log_info "Disk space usage: ${usage}% (OK)" + return 0 + elif [ "$usage" -lt 90 ]; then + log_warn "Disk space usage: ${usage}% (WARNING)" + return 1 + else + log_error "Disk space usage: ${usage}% (CRITICAL)" + return 1 + fi +} + +# Check memory usage +check_memory() { + log_check "Checking memory usage..." + + local mem_info=$(free | grep Mem) + local total=$(echo $mem_info | awk '{print $2}') + local used=$(echo $mem_info | awk '{print $3}') + local usage=$((used * 100 / total)) + + if [ "$usage" -lt 80 ]; then + log_info "Memory usage: ${usage}% (OK)" + return 0 + elif [ "$usage" -lt 90 ]; then + log_warn "Memory usage: ${usage}% (WARNING)" + return 1 + else + log_error "Memory usage: ${usage}% (CRITICAL)" + return 1 + fi +} + +# Run all health checks +run_all_checks() { + log_info "Running TAK Server Health Checks..." + echo "==================================" + + local failed=0 + + check_postgres || ((failed++)) + check_database || ((failed++)) + check_postgis || ((failed++)) + check_tak_files || ((failed++)) + check_tak_process || ((failed++)) + check_ports || ((failed++)) + check_disk_space || ((failed++)) + check_memory || ((failed++)) + + echo "==================================" + + if [ $failed -eq 0 ]; then + log_info "All health checks passed!" + return 0 + else + log_error "$failed health check(s) failed" + return 1 + fi +} + +# Main execution +case "${1:-all}" in + "all") + run_all_checks + ;; + "postgres") + check_postgres + ;; + "database") + check_database + ;; + "postgis") + check_postgis + ;; + "tak-files") + check_tak_files + ;; + "tak-process") + check_tak_process + ;; + "ports") + check_ports + ;; + "disk") + check_disk_space + ;; + "memory") + check_memory + ;; + *) + echo "Usage: $0 [all|postgres|database|postgis|tak-files|tak-process|ports|disk|memory]" + echo " all - Run all health checks (default)" + echo " postgres - Check PostgreSQL service" + echo " database - Check database connectivity" + echo " postgis - Check PostGIS extension" + echo " tak-files - Check TAK server files" + echo " tak-process- Check TAK server process" + echo " ports - Check network ports" + echo " disk - Check disk space" + echo " memory - Check memory usage" + exit 1 + ;; +esac diff --git a/scripts/tak-extract.sh b/scripts/tak-extract.sh new file mode 100644 index 0000000..8e90403 --- /dev/null +++ b/scripts/tak-extract.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# TAK Server Extraction Script + +# Colors for logging +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[EXTRACT-INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_warn() { + echo -e "${YELLOW}[EXTRACT-WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_error() { + echo -e "${RED}[EXTRACT-ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +log_debug() { + echo -e "${BLUE}[EXTRACT-DEBUG]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +# Extract TAK server from zip file +extract_tak_server() { + local zip_file="$1" + local target_dir="$2" + + if [ -z "$zip_file" ] || [ -z "$target_dir" ]; then + log_error "Usage: extract_tak_server " + return 1 + fi + + if [ ! -f "$zip_file" ]; then + log_error "ZIP file does not exist: $zip_file" + return 1 + fi + + log_info "Extracting TAK server from: $(basename $zip_file)" + log_debug "Target directory: $target_dir" + + # Create temporary extraction directory + local temp_dir="/tmp/tak_extract_$$" + mkdir -p "$temp_dir" + + log_debug "Using temporary directory: $temp_dir" + + # Extract ZIP file + cd "$temp_dir" + if ! unzip -q "$zip_file"; then + log_error "Failed to extract ZIP file" + rm -rf "$temp_dir" + return 1 + fi + + log_debug "ZIP extraction completed" + + # Find the tak directory - it could be at root level or nested + local tak_source_dir="" + + # First check if tak directory is at root level + if [ -d "$temp_dir/tak" ]; then + tak_source_dir="$temp_dir/tak" + log_info "Found 'tak' directory at root level" + else + # Look for tak directory in subdirectories + log_debug "Looking for 'tak' directory in subdirectories..." + tak_source_dir=$(find "$temp_dir" -type d -name "tak" -print -quit) + + if [ -n "$tak_source_dir" ] && [ -d "$tak_source_dir" ]; then + log_info "Found 'tak' directory at: $tak_source_dir" + else + log_error "Expected 'tak' directory not found in ZIP file" + log_debug "Available directories:" + find "$temp_dir" -type d -maxdepth 3 | while read dir; do + log_debug " $dir" + done + rm -rf "$temp_dir" + return 1 + fi + fi + + # Ensure target directory exists + mkdir -p "$target_dir" + + # Copy TAK files to target directory + log_debug "Copying files from $tak_source_dir/ to $target_dir/" + if cp -r "$tak_source_dir/"* "$target_dir/"; then + log_info "TAK files copied successfully" + else + log_error "Failed to copy TAK files" + rm -rf "$temp_dir" + return 1 + fi + + # Show what was extracted + log_debug "Files extracted to $target_dir:" + find "$target_dir" -maxdepth 2 -type f | head -10 | while read file; do + log_debug " $(basename $file)" + done + + # Clean up + rm -rf "$temp_dir" + log_debug "Temporary directory cleaned up" + + return 0 +} + +# Verify TAK installation +verify_tak_installation() { + local install_dir="$1" + + log_info "Verifying TAK installation in: $install_dir" + + # Check for required files + local required_files=( + "configureInDocker.sh" + "takserver.sh" + ) + + for file in "${required_files[@]}"; do + if [ -f "$install_dir/$file" ]; then + log_debug "Found required file: $file" + else + log_warn "Missing file: $file" + fi + done + + # Check for key directories + local key_dirs=( + "bin" + "conf" + "lib" + ) + + for dir in "${key_dirs[@]}"; do + if [ -d "$install_dir/$dir" ]; then + log_debug "Found directory: $dir" + else + log_warn "Missing directory: $dir" + fi + done + + # Main verification + if [ -f "$install_dir/configureInDocker.sh" ]; then + log_info "TAK installation verification successful" + return 0 + else + log_error "TAK installation verification failed - configureInDocker.sh not found" + return 1 + fi +} + +# Set proper permissions +set_tak_permissions() { + local install_dir="$1" + local owner="${2:-tak:tak}" + + log_info "Setting permissions on TAK installation" + + # Make scripts executable + find "$install_dir" -name "*.sh" -exec chmod +x {} \; 2>/dev/null + + # Set ownership + chown -R "$owner" "$install_dir" 2>/dev/null + + log_debug "Permissions set successfully" +} + +# Main execution if script is run directly +if [ "${BASH_SOURCE[0]}" == "${0}" ]; then + case "${1:-extract}" in + "extract") + extract_tak_server "$2" "$3" + ;; + "verify") + verify_tak_installation "$2" + ;; + "permissions") + set_tak_permissions "$2" "$3" + ;; + *) + echo "Usage: $0 [extract|verify|permissions] " + echo " extract - Extract TAK server from ZIP" + echo " verify - Verify TAK installation" + echo " permissions [owner] - Set TAK permissions" + exit 1 + ;; + esac +fi diff --git a/scripts/tak-version.sh b/scripts/tak-version.sh new file mode 100644 index 0000000..73d69d6 --- /dev/null +++ b/scripts/tak-version.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# TAK Server Version Detection Script +set -e + +# Find the latest takserver-docker-X.Y-RELEASE-Z.zip file +find_latest_tak_release() { + local takserver_dir="$1" + + if [ ! -d "$takserver_dir" ]; then + echo "ERROR: Directory $takserver_dir does not exist" + return 1 + fi + + local latest_zip=$(find "$takserver_dir" -name "takserver-docker-*-RELEASE-*.zip" -type f | \ + sed -n 's/.*takserver-docker-\([0-9]\+\.[0-9]\+\)-RELEASE-\([0-9]\+\)\.zip/\1.\2 &/p' | \ + sort -V | tail -1 | cut -d' ' -f2-) + + if [ -z "$latest_zip" ]; then + echo "ERROR: No takserver-docker-X.Y-RELEASE-Z.zip file found in $takserver_dir" + return 1 + fi + + echo "$latest_zip" +} + +# Extract version information +get_tak_version() { + local zip_file="$1" + local version=$(basename "$zip_file" | sed -n 's/takserver-docker-\([0-9]\+\.[0-9]\+\)-RELEASE-\([0-9]\+\)\.zip/\1-\2/p') + echo "$version" +} + +# List all available TAK releases +list_tak_releases() { + local takserver_dir="$1" + + echo "Available TAK server releases:" + find "$takserver_dir" -name "takserver-docker-*-RELEASE-*.zip" -type f | while read -r file; do + local version=$(get_tak_version "$file") + echo " - $(basename "$file") (version: $version)" + done +} + +# Main execution if script is run directly +if [ "${BASH_SOURCE[0]}" == "${0}" ]; then + TAKSERVER_DIR="${1:-/takserver-zip}" + + case "${2:-latest}" in + "latest") + find_latest_tak_release "$TAKSERVER_DIR" + ;; + "list") + list_tak_releases "$TAKSERVER_DIR" + ;; + "version") + if [ -n "$3" ]; then + get_tak_version "$3" + else + echo "Usage: $0 version " + exit 1 + fi + ;; + *) + echo "Usage: $0 [latest|list|version ]" + exit 1 + ;; + esac +fi diff --git a/validate.sh b/validate.sh new file mode 100755 index 0000000..dc1d966 --- /dev/null +++ b/validate.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# TAK Server Setup Validation Script + +echo "TAK Server Hybrid Container - Setup Validation" +echo "==============================================" + +# Check if takserver-release directory exists +if [ ! -d "takserver-release" ]; then + echo "❌ takserver-release directory not found" + echo " Please create the directory: mkdir -p takserver-release" + exit 1 +fi + +# Check for TAK server files +TAK_FILES=$(find takserver-release -name "takserver-docker-*.zip" 2>/dev/null) + +if [ -z "$TAK_FILES" ]; then + echo "❌ No TAK server files found in takserver-release/" + echo "" + echo "Required:" + echo " - File format: takserver-docker-X.Y-RELEASE-Z.zip" + echo " - Example: takserver-docker-5.4-RELEASE-19.zip" + echo "" + echo "Please:" + echo " 1. Obtain TAK server files through proper channels" + echo " 2. Ensure you have valid licensing/authorization" + echo " 3. Place files in takserver-release/ directory" + echo "" + exit 1 +fi + +echo "✅ TAK server files found:" +for file in $TAK_FILES; do + echo " - $(basename $file)" +done + +# Find latest version +LATEST_ZIP=$(echo "$TAK_FILES" | \ + sed -n 's/.*takserver-docker-\([0-9]\+\.[0-9]\+\)-RELEASE-\([0-9]\+\)\.zip/\1.\2 &/p' | \ + sort -V | tail -1 | cut -d' ' -f2-) + +if [ -n "$LATEST_ZIP" ]; then + echo "✅ Latest version detected: $(basename $LATEST_ZIP)" +fi + +# Check Docker +if ! command -v docker &> /dev/null; then + echo "❌ Docker not found - please install Docker" + exit 1 +fi +echo "✅ Docker found" + +# Check Docker Compose +if ! command -v docker-compose &> /dev/null; then + echo "❌ Docker Compose not found - please install Docker Compose" + exit 1 +fi +echo "✅ Docker Compose found" + +# Check if Dockerfile exists +if [ ! -f "Dockerfile" ]; then + echo "❌ Dockerfile not found" + exit 1 +fi +echo "✅ Dockerfile found" + +# Check if docker-compose.yml exists +if [ ! -f "docker-compose.yml" ]; then + echo "❌ docker-compose.yml not found" + exit 1 +fi +echo "✅ Docker Compose configuration found" + +echo "" +echo "🎉 All checks passed! You're ready to build and run the container." +echo "" +echo "Next steps:" +echo " 1. Build: ./build.sh" +echo " 2. Start: docker-compose up -d" +echo " 3. Logs: docker-compose logs -f tak-hybrid" +echo "" +echo "⚠️ Remember: Ensure you have proper licensing for TAK server software"