diff --git a/Dockerfile b/Dockerfile index b53e49e..05546cf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,125 +1 @@ -# FreeTAKServer Docker Container -# Based on the easy_install.sh script from FreeTAKTeam/FreeTAKHub-Installation -# Licensed under the Eclipse Public License 2.0 (EPL-2.0) - -FROM ubuntu:22.04 - -# Set environment variables to prevent interactive prompts -ENV DEBIAN_FRONTEND=noninteractive -ENV NEEDRESTART_SUSPEND=1 -ENV TZ=UTC - -# Set default installation parameters -ENV INSTALL_TYPE=latest -ENV PY3_VER=3.11 -ENV STABLE_FTS_VERSION=2.0.66 -ENV LEGACY_FTS_VERSION=1.9.9.6 -ENV FTS_VENV=/opt/fts.venv -ENV REPO=https://github.com/FreeTAKTeam/FreeTAKHub-Installation.git -ENV BRANCH=main -ENV CFG_RPATH=core/configuration - -# Create application directory -WORKDIR /opt/freetak - -# Update system and install base dependencies -RUN apt-get update -qq && \ - apt-get install -y --no-install-recommends \ - software-properties-common \ - curl \ - wget \ - git \ - python3-pip \ - python3-setuptools \ - python${PY3_VER}-dev \ - python${PY3_VER}-venv \ - libpython${PY3_VER}-dev \ - build-essential \ - libssl-dev \ - libffi-dev \ - libxml2-dev \ - libxslt1-dev \ - libjpeg-dev \ - libpng-dev \ - zlib1g-dev \ - sqlite3 \ - libsqlite3-dev \ - sudo \ - openssh-client \ - ca-certificates \ - gnupg \ - lsb-release && \ - # Add Ansible PPA and install - add-apt-repository -y ppa:ansible/ansible && \ - apt-get update -qq && \ - apt-get install -y --no-install-recommends ansible && \ - # Clean up apt cache - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Get latest FTS version from PyPI -RUN LATEST_FTS_VERSION=$(curl -s https://pypi.org/pypi/FreeTAKServer/json | python3 -c "import sys, json; print(json.load(sys.stdin)['info']['version'])") && \ - echo "export LATEST_FTS_VERSION=${LATEST_FTS_VERSION}" >> /etc/environment - -# Create Python virtual environment and install dependencies -RUN python${PY3_VER} -m venv ${FTS_VENV} && \ - . ${FTS_VENV}/bin/activate && \ - python3 -m pip install --upgrade pip && \ - python3 -m pip install --force-reinstall jinja2 pyyaml psutil - -# Clone FreeTAKHub-Installation repository -RUN git clone --branch ${BRANCH} ${REPO} /opt/FreeTAKHub-Installation - -# Set working directory to the cloned repository -WORKDIR /opt/FreeTAKHub-Installation - -# Create a non-root user for running the application -RUN useradd -m -u 1000 -s /bin/bash freetak && \ - usermod -aG sudo freetak && \ - echo "freetak ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - -# Generate SSH key pair for the freetak user -RUN mkdir -p /home/freetak/.ssh && \ - ssh-keygen -t rsa -f /home/freetak/.ssh/id_rsa -N "" && \ - chown -R freetak:freetak /home/freetak/.ssh && \ - chmod 700 /home/freetak/.ssh && \ - chmod 600 /home/freetak/.ssh/id_rsa && \ - chmod 644 /home/freetak/.ssh/id_rsa.pub - -# Copy the virtual environment to be accessible by freetak user -RUN chown -R freetak:freetak ${FTS_VENV} - -# Copy the scripts -COPY scripts/install_freetak.sh /opt/install_freetak.sh -COPY scripts/start_freetak.sh /opt/start_freetak.sh -COPY scripts/healthcheck.sh /opt/healthcheck.sh -COPY scripts/entrypoint.sh /opt/entrypoint.sh - -# Make the scripts executable -RUN chmod +x /opt/install_freetak.sh /opt/start_freetak.sh /opt/healthcheck.sh /opt/entrypoint.sh - -# Run the installation -RUN /opt/install_freetak.sh - -# Set proper ownership -RUN chown -R freetak:freetak /opt/FreeTAKHub-Installation /opt/freetak /opt/*.sh - -# Switch to freetak user -USER freetak - -# Set the working directory -WORKDIR /opt/freetak - -# Expose the default FreeTAKServer ports -# 8087 - Main server port -# 8080 - Web UI port -# 8443 - HTTPS port -# 19023 - FTS API port -EXPOSE 8087 8080 8443 19023 - -# Add healthcheck -HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ - CMD /opt/healthcheck.sh - -# Default command - use the entrypoint script -CMD ["/opt/entrypoint.sh"] \ No newline at end of file +FROM alpine:3.12 \ No newline at end of file diff --git a/Readme.md b/Readme.md index 2818566..2904b26 100644 --- a/Readme.md +++ b/Readme.md @@ -1,181 +1,36 @@ -# FreeTAKServer Docker Container +# README for Docker Image Build and Publish Workflows -This Docker container provides a complete FreeTAKServer installation based on the official FreeTAKTeam installation script. It includes all necessary components and dependencies to run FreeTAKServer in a containerized environment. +## Overview -## Features +This repository contains two GitHub Actions workflows that automate the building and publishing of Docker images to an OCI registry. -- **All-in-one container**: Includes FreeTAKServer, Web UI, and Web Map -- **Multiple installation types**: Support for latest, stable, and legacy versions -- **Automated setup**: Based on the official FreeTAKHub-Installation scripts -- **Health checks**: Built-in container health monitoring -- **Persistent data**: Volume support for configuration and data persistence +### Workflows -## Quick Start +1. **On Commit to Main** + - **Trigger:** Activates on commits to the `main` branch (tags are excluded). + - **Purpose:** Builds and publishes a Docker image for each commit. -### Using Docker Compose (Recommended) +2. **On Tag Push** + - **Trigger:** Activates when a new tag is pushed. + - **Purpose:** Builds and publishes a Docker image for the tag and tags it as `latest`. -```bash -# Clone or navigate to the directory containing docker-compose.yml -docker-compose up -d -``` +## Prerequisites -### Using the Run Script +- **Secrets Needed:** + - `OCI_TOKEN`: Your OCI registry token. + - `OCI_USER`: Your OCI registry username. -```bash -# Build and run with latest version (default) -./run.sh +## How to Use -# Build and run with stable version -./run.sh stable +1. **Clone the Repository:** Get a local copy of this repository. +2. **Modify Dockerfile:** Update the `Dockerfile` for your application. +3. **Push Changes:** Push changes to the `main` branch or create a new tag. +4. **Check Workflow Status:** View the Actions tab in Forgjo to monitor workflow runs. -# Build and run with legacy version -./run.sh legacy -``` +## Notes -### Manual Docker Commands - -```bash -# Build the image -docker build -t freetak-server . - -# Run the container -docker run -d \ - --name freetak-server \ - -p 8087:8087 \ - -p 8080:8080 \ - -p 8443:8443 \ - -p 19023:19023 \ - -e INSTALL_TYPE=latest \ - freetak-server -``` - -## Installation Types - -The container supports three installation types via the `INSTALL_TYPE` environment variable: - -- **`latest`** (default): Installs the most recent version from PyPI -- **`stable`**: Installs the stable version (v2.0.66) -- **`legacy`**: Installs the legacy version (v1.9.9.6) with Python 3.8 - -## Exposed Ports - -- **8087**: Main FreeTAKServer port -- **8080**: Web UI port -- **8443**: HTTPS port (if configured) -- **19023**: FTS API port - -## Access Points - -After the container is running, you can access: - -- **Web UI**: http://localhost:8080 -- **Main API**: http://localhost:8087 -- **API Endpoint**: http://localhost:19023 - -## Project Structure - -``` -/docker/services/freetak/ -├── Dockerfile # Main container definition -├── docker-compose.yml # Docker Compose configuration -├── run.sh # Quick start script -├── scripts/ # Container scripts directory -│ ├── install_freetak.sh # Installation script -│ ├── start_freetak.sh # Simple startup script -│ ├── entrypoint.sh # Main entrypoint with signal handling -│ ├── healthcheck.sh # Health check script -│ ├── dev-helper.sh # Development helper script -│ └── README.md # Scripts documentation -└── README.md # This file -``` - -## Configuration - -The container includes: - -- Python virtual environment at `/opt/fts.venv` -- FreeTAKHub-Installation repository at `/opt/FreeTAKHub-Installation` -- Configuration files based on the installation type -- Ansible playbooks for automated setup - -## Environment Variables - -- `INSTALL_TYPE`: Installation type (latest, stable, legacy) -- `TZ`: Timezone (default: UTC) -- `DEBIAN_FRONTEND`: Set to noninteractive for automated installation -- `PY3_VER`: Python version (automatically set based on install type) -- `FTS_VENV`: Virtual environment path -- `CFG_RPATH`: Configuration path (automatically set based on install type) - -## Volumes - -To persist data and configuration: - -```yaml -volumes: - - freetak_data:/opt/freetak/data - - freetak_config:/opt/FreeTAKHub-Installation -``` - -## Health Checks - -The container includes a built-in health check that monitors the FreeTAKServer process: - -```bash -# Check container health -docker ps -# Look for "healthy" status -``` - -## Troubleshooting - -### View Logs - -```bash -docker logs freetak-server -``` - -### Access Container Shell - -```bash -docker exec -it freetak-server /bin/bash -``` - -### Check Service Status - -```bash -docker exec -it freetak-server /opt/healthcheck.sh -``` - -### Restart Container - -```bash -docker restart freetak-server -``` - -## Building from Source - -The Dockerfile is based on Ubuntu 22.04 and includes: - -1. System dependencies (Python, Ansible, Git, etc.) -2. Python virtual environment setup -3. FreeTAKHub-Installation repository clone -4. Ansible playbook execution -5. Service configuration and startup scripts - -## Security Notes - -- The container runs as a non-root user (`freetak`) -- SSH keys are generated for internal use -- All dependencies are installed from official repositories -- The installation follows the official FreeTAKTeam procedures +- Ensure your Docker environment is compatible with multi-platform builds if necessary. ## License -This Docker container is based on the FreeTAKHub-Installation scripts, which are licensed under the Eclipse Public License 2.0 (EPL-2.0). - -## Support - -For issues related to FreeTAKServer itself, please refer to the [FreeTAKTeam GitHub repository](https://github.com/FreeTAKTeam/FreeTAKServer). - -For Docker-specific issues, please check the container logs and ensure all required ports are available. \ No newline at end of file +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 24c3a28..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: '3.8' - -services: - freetak: - build: - context: . - dockerfile: Dockerfile - container_name: freetak-server - ports: - - "8087:8087" # Main server port - - "8080:8080" # Web UI port - - "8443:8443" # HTTPS port - - "19023:19023" # FTS API port - environment: - - INSTALL_TYPE=latest # Options: latest, stable, legacy - - TZ=UTC - volumes: - - freetak_data:/opt/freetak/data - - freetak_config:/opt/FreeTAKHub-Installation - restart: unless-stopped - healthcheck: - test: ["CMD", "/opt/healthcheck.sh"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 60s - networks: - - freetak_network - -networks: - freetak_network: - driver: bridge - -volumes: - freetak_data: - freetak_config: diff --git a/freetak_install.sh b/freetak_install.sh deleted file mode 100644 index 3080689..0000000 --- a/freetak_install.sh +++ /dev/null @@ -1,655 +0,0 @@ -#!/usr/bin/env bash -#: Free TAK Server Installation Script -#: Original Author: John -#: Maintainers: -#: - Sypher -#: - nailshard -#: -#: This is an unmodified copy of a script from: -#: https://github.com/FreeTAKTeam/FreeTAKHub-Installation/blob/main/scripts/easy_install.sh -#: -#: Licensed under the Eclipse Public License 2.0 (EPL-2.0) -#: SPDX-License-Identifier: EPL-2.0 -#: https://www.eclipse.org/legal/epl-2.0/ -############################################################################### - -# enforce failfast -set -o errexit -set -o nounset -set -o pipefail - -# This disables Apt's "restart services" interactive dialog -export DEBIAN_FRONTEND=noninteractive -export NEEDRESTART_SUSPEND=1 -NEEDRESTART= - -# trap or catch signals and direct execution to cleanup -trap cleanup SIGINT SIGTERM ERR EXIT - -DEFAULT_REPO="https://github.com/FreeTAKTeam/FreeTAKHub-Installation.git" -REPO=${REPO:-$DEFAULT_REPO} -DEFAULT_BRANCH="main" -BRANCH=${BRANCH:-$DEFAULT_BRANCH} -CBRANCH=${CBRANCH:-} - -STABLE_OS_REQD="Ubuntu" -STABLE_OS_VER_REQD="22.04" -STABLE_CODENAME_REQD="jammy" -LEGACY_OS_REQD="Ubuntu" -LEGACY_OS_VER_REQD="20.04" -LEGACY_CODENAME_REQD="focal" - -# the specific versions will be set later based on INSTALL_TYPE -DEFAULT_INSTALL_TYPE="latest" -INSTALL_TYPE="${INSTALL_TYPE:-$DEFAULT_INSTALL_TYPE}" - -PY3_VER_LEGACY="3.8" -PY3_VER_STABLE="3.11" - -STABLE_FTS_VERSION="2.0.66" -LEGACY_FTS_VERSION="1.9.9.6" -LATEST_FTS_VERSION=$(curl -s https://pypi.org/pypi/FreeTAKServer/json | python3 -c "import sys, json; print(json.load(sys.stdin)['info']['version'])") - -FTS_VENV="${HOME}/fts.venv" - -DRY_RUN=0 - -hsep="*********************" -# -############################################################################### -# Add coloration to output for highlighting or emphasizing words -############################################################################### -function setup_colors() { - - if [[ -t 2 ]] && [[ -z "${NO_COLOR-}" ]] && [[ "${TERM-}" != "dumb" ]]; then - - NOFORMAT='\033[0m' - RED='\033[0;31m' - GREEN='\033[0;32m' - # ORANGE='\033[0;33m' # unused - BLUE='\033[0;34m' - # PURPLE='\033[0;35m' # unused - # CYAN='\033[0;36m' # unused - YELLOW='\033[1;33m' - - else - - NOFORMAT='' - RED='' - GREEN='' - # ORANGE='' # unused - BLUE='' - # PURPLE='' # unused - # CYAN='' # unused - YELLOW='' - - fi - -} - - -############################################################################### -# Print out helpful message. -# Outputs: -# Writes usage message to stdout -############################################################################### -function usage() { - cat <] - -Install Free TAK Server and components. - -Available options: - --h, --help Print help --v, --verbose Print script debug info --c, --check Check for compatibility issues while installing - --core Install FreeTAKServer, UI, and Web Map - --latest [DEFAULT] Install latest version (v$LATEST_FTS_VERSION) --s, --stable Install latest stable version (v$STABLE_FTS_VERSION) --l, --legacy Install legacy version (v$LEGACY_FTS_VERSION) - --repo Replaces with specified ZT Installer repository [DEFAULT ${DEFAULT_REPO}] - --branch Use specified ZT Installer repository branch [DEFAULT main] - --dev-test Sets TEST Envar to 1 - --dry-run Sets up dependencies but exits before running any playbooks - --ip-addr Explicitly set IP address (when http://ifconfig.me/ip is wrong) -USAGE_TEXT - exit -} - -############################################################################### -# Cleanup here -############################################################################### -function cleanup() { - - trap - SIGINT SIGTERM ERR EXIT - - # script cleanup here - -} - -############################################################################### -# Echo a message -############################################################################### -function msg() { - - echo >&2 -e "${1-}" - -} - -############################################################################### -# Exit gracefully -############################################################################### -function die() { - - local msg=$1 - local code=${2-1} - msg "$msg" - - [[ $code -eq 0 ]] || echo -e "Exiting. Installation NOT successful." - - # default exit status 1 - exit "$code" - -} - -############################################################################### -# Parse parameters -############################################################################### -function parse_params() { - - # The default 'apt verbosity' is verbose. Set it to quiet, since that's what our script assumes - # unset this later if we want verbosity - APT_VERBOSITY="-qq" - - while true; do - case "${1-}" in - - --help | -h) - usage - exit 0 - shift - ;; - - --verbose | -v) - echo "Verbose output" - set -x - - NO_COLOR=1 - GIT_TRACE=true - GIT_CURL_VERBOSE=true - GIT_SSH_COMMAND="ssh -vvv" - unset APT_VERBOSITY # verbose is the default - ANSIBLE_VERBOSITY="-vvvvv" - - shift - ;; - - --check | -c) - CHECK=1 - shift - ;; - - --core) - CORE=1 - shift - ;; - - --stable | -s) - INSTALL_TYPE="stable" - shift - ;; - - --latest) - INSTALL_TYPE="latest" - shift - ;; - - --legacy | -l) - INSTALL_TYPE="legacy" - shift - ;; - - -B) - echo "${RED}${hsep}${hsep}${hsep}" - echo -e "This option is not supported for public use.\n\ - It will alter the version of this installer, which means:\n\ - 1. it may make breaking system alterations\n\ - 2. use at your own risk\n\ - It is highly recommended that you do not continue\n\ - unless you've selected this option for a specific reason" - echo "${hsep}${hsep}${hsep}${NOFORMAT}" - CBRANCH=$2 - shift 2 - ;; - - --repo) - REPO=$2 - shift 2 - - if [[ -d ~/FreeTAKHub-Installation ]] - then rm -rf ~/FreeTAKHub-Installation - fi - ;; - - --branch) - BRANCH=$2 - shift 2 - ;; - - --dev-test) - TEST=1 - shift - ;; - - --dry-run) - DRY_RUN=1 - shift - ;; - - --ip-addr) - FTS_IP_CUSTOM=$2 - shift 2 - echo "Using the IP of ${FTS_IP_CUSTOM}" - ;; - - --no-color) - NO_COLOR=1 - shift - ;; - - -?*) - die "ERROR: unknown option $1" - ;; - - *) - break - ;; - - esac - done - -} - - -############################################################################### -# Update variables from defaults, user inputs or implied values -############################################################################### -function set_versions() { - case $INSTALL_TYPE in - latest) - export PY3_VER=$PY3_VER_STABLE - export FTS_VERSION=$LATEST_FTS_VERSION - export CFG_RPATH="core/configuration" - export OS_REQD=$STABLE_OS_REQD - export OS_VER_REQD=$STABLE_OS_VER_REQD - export CODENAME=$STABLE_CODENAME_REQD - ;; - legacy) - export PY3_VER=$PY3_VER_LEGACY - export FTS_VERSION=$LEGACY_FTS_VERSION - export CFG_RPATH="controllers/configuration" - export OS_REQD=$LEGACY_OS_REQD - export OS_VER_REQD=$LEGACY_OS_VER_REQD - export CODENAME=$LEGACY_CODENAME_REQD - ;; - stable) - export PY3_VER=$PY3_VER_STABLE - export FTS_VERSION=$STABLE_FTS_VERSION - export CFG_RPATH="core/configuration" - export OS_REQD=$STABLE_OS_REQD - export OS_VER_REQD=$STABLE_OS_VER_REQD - export CODENAME=$STABLE_CODENAME_REQD - ;; - *) - die "Unsupport install type: $INSTALL_TYPE" - ;; - esac - -} -############################################################################### -# Do checks or skip unnecessary ones if non-interactive -############################################################################### -function do_checks() { - - check_root - - if [[ -n "${CHECK-}" ]]; then - check_os - # check_architecture - else - WEBMAP_FORCE_INSTALL="webmap_force_install=true" - fi - - if [[ -n "${TEST-}" ]]; then - REPO="https://github.com/janseptaugust/FreeTAKHub-Installation.git" - fi - -} - -############################################################################### -# Check if script was ran as root. This script requires root execution. -############################################################################### -function check_root() { - - echo -e -n "${BLUE}Checking if this script is running as root...${NOFORMAT}" - - # check Effective User ID (EUID) for root user, which has an EUID of 0. - if [[ "$EUID" -ne 0 ]]; then - - echo -e "${RED}ERROR${NOFORMAT}" - die "This script requires running as root. Use sudo before the command." - - else - - echo -e "${GREEN}Success!${NOFORMAT}" - - fi -} - -############################################################################### -# Check for supported operating system and warn user if not supported. -############################################################################### -function check_os() { - - which apt-get >/dev/null - if [[ $? -ne 0 ]]; then - die "Could not locate apt... this installation method will not work" - fi - - echo -e -n "${BLUE}Checking for supported OS...${NOFORMAT}" - - # freedesktop.org and systemd - if [[ -f /etc/os-release ]]; then - - . /etc/os-release - - OS=${NAME:-unknown} - VER=${VERSION_ID:-unknown} - CODENAME=${VERSION_CODENAME} - - # linuxbase.org - elif type lsb_release >/dev/null 2>&1; then - - OS=$(lsb_release -si) - VER=$(lsb_release -sr) - - # for some Debian-based distros - elif [[ -f /etc/lsb-release ]]; then - - . /etc/lsb-release - - OS=${DISTRIB_ID} - VER=${DISTRIB_RELEASE} - - - # older Debian-based distros - elif [[ -f /etc/debian_version ]]; then - - OS=Debian - VER=$(cat /etc/debian_version) - - # fallback - else - - OS=$(uname -s) - VER=$(uname -r) - - fi - - # check for supported OS and version and warn if not supported - if [[ "${OS}" != "${OS_REQD}" ]] || [[ "${VER}" != "${OS_VER_REQD}" ]]; then - - echo -e "${YELLOW}WARNING${NOFORMAT}" - echo "FreeTAKServer has only been tested on ${GREEN}${OS_REQD} ${OS_VER_REQD}${NOFORMAT}." - echo -e "This machine is currently running: ${YELLOW}${OS} ${VER}${NOFORMAT}" - echo "Errors may arise during installation or execution." - - read -r -e -p "Do you want to continue? [y/n]: " PROCEED - - # Default answer is "n" for NO. - DEFAULT="n" - - # Set user-inputted value and apply default if user input is null. - PROCEED="${PROCEED:-${DEFAULT}}" - - # Check user input to proceed or not. - if [[ "${PROCEED}" != "y" ]]; then - die "Answer was not y. Not proceeding." - else - echo -e "${GREEN}Proceeding...${NOFORMAT}" - fi - - else - - echo -e "${GREEN}Success!${NOFORMAT}" - echo -e "This machine is currently running: ${GREEN}${OS} ${VER}${NOFORMAT}" - echo -e "Selected install type is: ${GREEN}${DEFAULT_INSTALL_TYPE}" - - fi - -} - -############################################################################### -# Check for supported architecture -############################################################################### -function check_architecture() { - - echo -e -n "${BLUE}Checking for supported architecture...${NOFORMAT}" - - # check for non-Intel-based architecture here - arch=$(uname --hardware-platform) # uname is non-portable, but we only target Ubuntu 20.04/22.04 - if ! grep --ignore-case x86 <<<"${arch}" >/dev/null; then - - echo -e "${YELLOW}WARNING${NOFORMAT}" - echo "Possible non-Intel architecture detected, ${name}" - echo "Non-intel architectures may cause problems. The web map might not install." - - read -r -e -p "Do you want to force web map installation? [y/n]: " USER_INPUT - - # Default answer is "n" for NO. - DEFAULT="n" - - # Set user-inputted value and apply default if user input is null. - FORCE_WEBMAP_INSTALL_INPUT="${USER_INPUT:-${DEFAULT}}" - - # Check user input to force install web map or not - if [[ "${FORCE_WEBMAP_INSTALL_INPUT}" != "y" ]]; then - echo -e "${YELLOW}WARNING${NOFORMAT}: installer may skip web map installation." - else - WEBMAP_FORCE_INSTALL="webmap_force_install=true" - echo -e "${YELLOW}WARNING${NOFORMAT}: forcing web map installation!" - fi - - else # good architecture to install webmap - - echo -e "${GREEN}Success!${NOFORMAT}" - echo "Intel architecture detected, ${name}" - - fi - -} - -############################################################################### -# Download dependencies -############################################################################### -function download_dependencies() { - - echo -e "${BLUE}Downloading dependencies...${NOFORMAT}" - - echo -e "${BLUE}Adding the Ansible Personal Package Archive (PPA)...${NOFORMAT}" - - # dpkg --list | grep -q needrestart && NEEDRESTART=1 - # [[ 0 -eq $NEEDRESTART ]] || apt-get remove --yes needrestart - x=$(find /etc/apt/apt.conf.d -name "*needrestart*") - if [[ -f $x ]]; then - NEEDRESTART=$x - mv $x $HOME/nr-conf-temp - fi - - # Some programs need predictable names for certain libraries, so symlink - x="pkg inst" - for y in $x; do - z=$(find /usr/lib -name apt_${y}.so) - if [[ -z $z ]]; then - z=$(find /usr/lib -name "apt_${y}.cpython*.so") - ln -sf $z $(dirname $z)/apt_${y}.so - fi - done - - # Some Ubuntu installations do not have the software-properties-common - # package by default, so install it if not installed - which apt-add-repository >/dev/null || apt-get --yes install software-properties-common - - apt-add-repository -y ppa:ansible/ansible - - echo -e "${BLUE}Downloading package information from configured sources...${NOFORMAT}" - - apt-get -y ${APT_VERBOSITY--qq} update - - echo -e "${BLUE}Installing Ansible...${NOFORMAT}" - apt-get -y ${APT_VERBOSITY--qq} install ansible - - echo -e "${BLUE}Installing Git...${NOFORMAT}" - apt-get -y ${APT_VERBOSITY--qq} install git - -} - -############################################################################### -# We can install the python virtual environment here including the python interpreter. -# This removes any need to deal with any circular requirement between -# the installer, Ansible, and its dependencies (e.g. jinja2) and -# the application being installed, FTS, and its dependencies. -############################################################################### -function install_python_environment() { - apt-get update - apt-get install -y python3-pip python3-setuptools - apt-get install -y python${PY3_VER}-dev python${PY3_VER}-venv libpython${PY3_VER}-dev - - /usr/bin/python${PY3_VER} -m venv ${FTS_VENV} - source ${FTS_VENV}/bin/activate - - python3 -m pip install --upgrade pip - python3 -m pip install --force-reinstall jinja2 - python3 -m pip install --force-reinstall pyyaml - python3 -m pip install --force-reinstall psutil - - deactivate - -} -############################################################################### -# Handle git repository -############################################################################### -function handle_git_repository() { - - echo -e -n "${BLUE}Checking for FreeTAKHub-Installation in home directory..." - cd ~ - - [[ -n $CBRANCH ]] && BRANCH=$CBRANCH - # check for FreeTAKHub-Installation repository - if [[ ! -d ~/FreeTAKHub-Installation ]]; then - - echo -e "local working git tree NOT FOUND" - echo -e "Cloning the FreeTAKHub-Installation repository...${NOFORMAT}" - git clone --branch "${BRANCH}" ${REPO} ~/FreeTAKHub-Installation - - cd ~/FreeTAKHub-Installation - - else - - echo -e "FOUND" - - cd ~/FreeTAKHub-Installation - - echo -e \ - "Pulling latest from the FreeTAKHub-Installation repository...${NOFORMAT}" - git pull - git checkout "${BRANCH}" - - fi - - git pull - -} - -############################################################################### -# Add passwordless Ansible execution -############################################################################### -function add_passwordless_ansible_execution() { - - echo -e \ - "${BLUE}Adding passwordless Ansible execution for the current user...${NOFORMAT}" - - # line to add - LINE="${USER} ALL=(ALL) NOPASSWD:/usr/bin/ansible-playbook" - - # file to create for passwordless - FILE="/etc/sudoers.d/dont-prompt-${USER}-for-sudo-password" - - # only add if non-existent - grep -qF -- "${LINE}" "${FILE}" || echo "${LINE}" >>"${FILE}" - -} - -############################################################################### -# Generate public and private keys -############################################################################### -function generate_key_pair() { - - echo -e \ - "${BLUE}Creating a public and private keys if non-existent...${NOFORMAT}" - - # check for public and private keys - if [[ ! -e ${HOME}/.ssh/id_rsa.pub ]]; then - # generate keys - ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa" -N "" - fi - -} - -############################################################################### -# Run Ansible playbook to install -# https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#defining-variables-at-runtime -############################################################################### -function run_playbook() { - - export CODENAME - export INSTALL_TYPE - export FTS_VERSION - env_vars="python3_version=$PY3_VER codename=$CODENAME itype=$INSTALL_TYPE" - env_vars="$env_vars fts_version=$FTS_VERSION cfg_rpath=$CFG_RPATH fts_venv=${FTS_VENV}" - [[ -n "${FTS_IP_CUSTOM:-}" ]] && env_vars="$env_vars fts_ip_addr_extra=$FTS_IP_CUSTOM" - [[ -n "${WEBMAP_FORCE_INSTALL:-}" ]] && env_vars="$env_vars $WEBMAP_FORCE_INSTALL" - [[ -n "${CORE:-}" ]] && pb=install_mainserver || pb=install_all - echo -e "${BLUE}Running Ansible Playbook ${GREEN}$pb${BLUE}...${NOFORMAT}" - ansible-playbook -u root ${pb}.yml \ - --connection=local \ - --inventory localhost, \ - --extra-vars "$env_vars" \ - ${ANSIBLE_VERBOSITY-} -} - -function cleanup() { - if [[ -n $NEEDRESTART ]] - then - cp $HOME/nr-conf-temp $NEEDRESTART - fi -} -############################################################################### -# MAIN BUSINESS LOGIC HERE -############################################################################### - -setup_colors -parse_params "${@}" -set_versions -check_os -# do_checks -download_dependencies -[[ "$DEFAULT_INSTALL_TYPE" == "$INSTALL_TYPE" ]] && install_python_environment -handle_git_repository -add_passwordless_ansible_execution -generate_key_pair - -[[ 0 -eq $DRY_RUN ]] || die "Dry run complete. Not running Ansible" 0 -run_playbook -cleanup \ No newline at end of file diff --git a/run.sh b/run.sh deleted file mode 100755 index 278fcf5..0000000 --- a/run.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash -# Build and run FreeTAKServer with different installation types - -set -e - -INSTALL_TYPE=${1:-latest} -CONTAINER_NAME="freetak-server" -IMAGE_NAME="freetak-server" - -echo "Building FreeTAKServer Docker image with install type: $INSTALL_TYPE" - -# Stop and remove existing container if it exists -if docker ps -a --format 'table {{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then - echo "Stopping and removing existing container..." - docker stop $CONTAINER_NAME || true - docker rm $CONTAINER_NAME || true -fi - -# Build the Docker image -echo "Building Docker image..." -docker build -t $IMAGE_NAME . - -# Run the container -echo "Starting FreeTAKServer container..." -docker run -d \ - --name $CONTAINER_NAME \ - -p 8087:8087 \ - -p 8080:8080 \ - -p 8443:8443 \ - -p 19023:19023 \ - -e INSTALL_TYPE=$INSTALL_TYPE \ - -e TZ=UTC \ - --restart unless-stopped \ - $IMAGE_NAME - -echo "FreeTAKServer is starting up..." -echo "Web UI will be available at: http://localhost:8080" -echo "Main server API at: http://localhost:8087" -echo "API endpoint at: http://localhost:19023" -echo "" -echo "Use 'docker logs $CONTAINER_NAME' to view the logs" -echo "Use 'docker exec -it $CONTAINER_NAME /bin/bash' to access the container" -echo "" -echo "To stop the container: docker stop $CONTAINER_NAME" diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index cc71914..0000000 --- a/scripts/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# FreeTAKServer Docker Scripts - -This directory contains the scripts used by the FreeTAKServer Docker container. These scripts have been extracted from the Dockerfile for better maintainability and easier development. - -## Scripts Overview - -### `install_freetak.sh` -- **Purpose**: Installs FreeTAKServer using Ansible playbooks -- **Usage**: Called during Docker build process -- **Environment Variables**: - - `INSTALL_TYPE`: Installation type (latest, stable, legacy) - - `FTS_VENV`: Path to Python virtual environment - - `STABLE_FTS_VERSION`: Stable version number - - `LEGACY_FTS_VERSION`: Legacy version number - - `CFG_RPATH`: Configuration path - -### `start_freetak.sh` -- **Purpose**: Simple startup script for FreeTAKServer -- **Usage**: Basic container startup (deprecated, use entrypoint.sh) -- **Environment Variables**: - - `FTS_VENV`: Path to Python virtual environment - - `CFG_RPATH`: Configuration path - -### `entrypoint.sh` -- **Purpose**: Main entrypoint script with signal handling and logging -- **Usage**: Default container entrypoint -- **Features**: - - Graceful shutdown handling - - Proper signal forwarding - - Timestamped logging - - Dynamic configuration path detection - - Environment-based configuration - -### `healthcheck.sh` -- **Purpose**: Health check script for Docker container -- **Usage**: Called by Docker healthcheck -- **Functionality**: Checks if FreeTAKServer process is running - -### `dev-helper.sh` -- **Purpose**: Development helper script for validation and testing -- **Usage**: `./scripts/dev-helper.sh [validate|test|info|help]` -- **Features**: - - Script validation - - Syntax checking - - Information display - - Development workflow support - -## Development Workflow - -1. **Validate Scripts**: Ensure all scripts exist and are executable - ```bash - ./scripts/dev-helper.sh validate - ``` - -2. **Test Syntax**: Check all scripts for syntax errors - ```bash - ./scripts/dev-helper.sh test - ``` - -3. **View Information**: Display script information - ```bash - ./scripts/dev-helper.sh info - ``` - -## Script Maintenance - -### Adding New Scripts -1. Create the script in the `scripts/` directory -2. Make it executable: `chmod +x scripts/your-script.sh` -3. Add it to the Dockerfile `COPY` instruction -4. Update the `dev-helper.sh` script to include validation - -### Modifying Existing Scripts -1. Edit the script file directly -2. Test syntax: `./scripts/dev-helper.sh test` -3. Rebuild the Docker image to apply changes - -### Best Practices -- Always include proper error handling (`set -e`) -- Use descriptive variable names -- Add comments for complex logic -- Follow consistent formatting -- Test scripts before committing - -## Environment Variables - -The scripts use these key environment variables: - -- `FTS_VENV`: Python virtual environment path (default: `/opt/fts.venv`) -- `INSTALL_TYPE`: Installation type - `latest`, `stable`, or `legacy` -- `CFG_RPATH`: Configuration path (auto-detected based on install type) -- `STABLE_FTS_VERSION`: Stable version number -- `LEGACY_FTS_VERSION`: Legacy version number - -## Troubleshooting - -### Script Not Executable -```bash -chmod +x scripts/script-name.sh -``` - -### Syntax Errors -```bash -bash -n scripts/script-name.sh -``` - -### Testing Individual Scripts -```bash -# Test in container context -docker run --rm -it freetak-server /bin/bash -# Then run: /opt/script-name.sh -``` - -### Debugging -Add `set -x` at the beginning of scripts to enable debug output. - -## Integration with Dockerfile - -The scripts are copied into the container during build: - -```dockerfile -# Copy the scripts -COPY scripts/install_freetak.sh /opt/install_freetak.sh -COPY scripts/start_freetak.sh /opt/start_freetak.sh -COPY scripts/healthcheck.sh /opt/healthcheck.sh -COPY scripts/entrypoint.sh /opt/entrypoint.sh - -# Make the scripts executable -RUN chmod +x /opt/*.sh -``` - -## License - -These scripts are part of the FreeTAKServer Docker container project and follow the same licensing as the original FreeTAKHub-Installation project (Eclipse Public License 2.0). diff --git a/scripts/dev-helper.sh b/scripts/dev-helper.sh deleted file mode 100755 index 88826ae..0000000 --- a/scripts/dev-helper.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/bin/bash -# Development helper script for FreeTAKServer Docker container - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_status() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Function to check if script exists and is executable -check_script() { - local script_path="$1" - local script_name=$(basename "$script_path") - - if [[ ! -f "$script_path" ]]; then - print_error "Script $script_name not found at $script_path" - return 1 - fi - - if [[ ! -x "$script_path" ]]; then - print_warning "Script $script_name is not executable, fixing..." - chmod +x "$script_path" - fi - - print_success "Script $script_name is ready" - return 0 -} - -# Function to validate scripts -validate_scripts() { - print_status "Validating scripts..." - - local scripts=( - "$PROJECT_DIR/scripts/install_freetak.sh" - "$PROJECT_DIR/scripts/start_freetak.sh" - "$PROJECT_DIR/scripts/healthcheck.sh" - "$PROJECT_DIR/scripts/entrypoint.sh" - ) - - local all_valid=true - - for script in "${scripts[@]}"; do - if ! check_script "$script"; then - all_valid=false - fi - done - - if [[ "$all_valid" == true ]]; then - print_success "All scripts are valid and executable" - else - print_error "Some scripts have issues" - exit 1 - fi -} - -# Function to test script syntax -test_syntax() { - print_status "Testing script syntax..." - - local scripts=( - "$PROJECT_DIR/scripts/install_freetak.sh" - "$PROJECT_DIR/scripts/start_freetak.sh" - "$PROJECT_DIR/scripts/healthcheck.sh" - "$PROJECT_DIR/scripts/entrypoint.sh" - ) - - for script in "${scripts[@]}"; do - local script_name=$(basename "$script") - if bash -n "$script"; then - print_success "Syntax check passed for $script_name" - else - print_error "Syntax check failed for $script_name" - exit 1 - fi - done -} - -# Function to show script information -show_info() { - print_status "FreeTAKServer Docker Scripts Information" - echo - echo "Scripts directory: $PROJECT_DIR/scripts/" - echo - echo "Available scripts:" - echo " install_freetak.sh - Installs FreeTAKServer using Ansible" - echo " start_freetak.sh - Simple startup script" - echo " entrypoint.sh - Main entrypoint with signal handling" - echo " healthcheck.sh - Health check script" - echo - echo "Usage in Dockerfile:" - echo " COPY scripts/ /opt/scripts/" - echo " RUN chmod +x /opt/scripts/*.sh" - echo -} - -# Function to show usage -usage() { - echo "Usage: $0 [COMMAND]" - echo - echo "Commands:" - echo " validate Validate all scripts exist and are executable" - echo " test Test script syntax" - echo " info Show information about scripts" - echo " help Show this help message" - echo - echo "If no command is provided, 'validate' is run by default." -} - -# Main script logic -main() { - case "${1:-validate}" in - validate) - validate_scripts - ;; - test) - validate_scripts - test_syntax - ;; - info) - show_info - ;; - help|--help|-h) - usage - ;; - *) - print_error "Unknown command: $1" - usage - exit 1 - ;; - esac -} - -# Change to project directory -cd "$PROJECT_DIR" - -# Run main function -main "$@" diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh deleted file mode 100755 index 1f88524..0000000 --- a/scripts/entrypoint.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -set -e - -# Function to log messages with timestamp -log() { - echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" -} - -# Function to handle signals for graceful shutdown -cleanup() { - log "Received shutdown signal, stopping FreeTAKServer..." - if [ -n "$FTS_PID" ]; then - kill -TERM "$FTS_PID" 2>/dev/null || true - wait "$FTS_PID" 2>/dev/null || true - fi - log "FreeTAKServer stopped" - exit 0 -} - -# Set up signal handlers -trap cleanup SIGTERM SIGINT - -# Source the virtual environment -log "Activating Python virtual environment..." -source ${FTS_VENV}/bin/activate - -# Set up environment variables based on install type -case ${INSTALL_TYPE} in - legacy) - export CFG_RPATH=controllers/configuration - log "Using legacy configuration path: ${CFG_RPATH}" - ;; - *) - export CFG_RPATH=core/configuration - log "Using standard configuration path: ${CFG_RPATH}" - ;; -esac - -# Change to the configuration directory -CONFIG_DIR="/opt/FreeTAKHub-Installation/${CFG_RPATH}" -if [ -d "$CONFIG_DIR" ]; then - log "Changing to configuration directory: $CONFIG_DIR" - cd "$CONFIG_DIR" -else - log "WARNING: Configuration directory not found at $CONFIG_DIR" - log "Attempting to start from FreeTAKHub-Installation root..." - cd /opt/FreeTAKHub-Installation -fi - -# Start FreeTAKServer -log "Starting FreeTAKServer (Install Type: ${INSTALL_TYPE})..." -log "Python version: $(python3 --version)" -log "Working directory: $(pwd)" - -# Start the service in the background to allow signal handling -python3 -m FreeTAKServer.controllers.services.FTS & -FTS_PID=$! - -log "FreeTAKServer started with PID: $FTS_PID" -log "FreeTAKServer is running. Use Ctrl+C to stop." - -# Wait for the background process -wait "$FTS_PID" - -# Deactivate virtual environment -deactivate - -log "FreeTAKServer has stopped" diff --git a/scripts/healthcheck.sh b/scripts/healthcheck.sh deleted file mode 100755 index 2ee3b8d..0000000 --- a/scripts/healthcheck.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# Simple healthcheck - check if the FTS process is running -pgrep -f "FreeTAKServer" > /dev/null -exit $? diff --git a/scripts/install_freetak.sh b/scripts/install_freetak.sh deleted file mode 100755 index 25af185..0000000 --- a/scripts/install_freetak.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -set -e - -# Source the virtual environment -source ${FTS_VENV}/bin/activate - -# Set up environment variables -export CODENAME=jammy -export INSTALL_TYPE=${INSTALL_TYPE:-latest} -export FTS_VERSION=${STABLE_FTS_VERSION} -export PY3_VER=${PY3_VER} -export CFG_RPATH=${CFG_RPATH} -export FTS_VENV=${FTS_VENV} - -# Determine FTS version based on install type -case ${INSTALL_TYPE} in - latest) - export FTS_VERSION=$(curl -s https://pypi.org/pypi/FreeTAKServer/json | python3 -c "import sys, json; print(json.load(sys.stdin)[\"info\"][\"version\"])" 2>/dev/null || echo "${STABLE_FTS_VERSION}") - ;; - stable) - export FTS_VERSION=${STABLE_FTS_VERSION} - ;; - legacy) - export FTS_VERSION=${LEGACY_FTS_VERSION} - export PY3_VER=3.8 - export CFG_RPATH=controllers/configuration - ;; -esac - -# Set up Ansible variables -env_vars="python3_version=${PY3_VER} codename=${CODENAME} itype=${INSTALL_TYPE}" -env_vars="${env_vars} fts_version=${FTS_VERSION} cfg_rpath=${CFG_RPATH} fts_venv=${FTS_VENV}" -env_vars="${env_vars} webmap_force_install=true" - -# Run Ansible playbook -cd /opt/FreeTAKHub-Installation -echo "Installing FreeTAKServer with the following settings:" -echo " Version: ${FTS_VERSION}" -echo " Python: ${PY3_VER}" -echo " Install Type: ${INSTALL_TYPE}" -echo " Virtual Environment: ${FTS_VENV}" - -ansible-playbook -u root install_all.yml \ - --connection=local \ - --inventory localhost, \ - --extra-vars "${env_vars}" \ - -v - -deactivate diff --git a/scripts/start_freetak.sh b/scripts/start_freetak.sh deleted file mode 100755 index 754923c..0000000 --- a/scripts/start_freetak.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e - -# Source the virtual environment -source ${FTS_VENV}/bin/activate - -# Change to the configuration directory -cd /opt/FreeTAKHub-Installation/${CFG_RPATH} - -# Start FreeTAKServer -echo "Starting FreeTAKServer..." -python3 -m FreeTAKServer.controllers.services.FTS - -deactivate