#!/bin/bash # Project Tracker - One-shot deploy script # Run on a fresh Debian/Ubuntu server as root set -e echo "" echo "╔═══════════════════════════════════════════════╗" echo "║ Project Tracker — Deploy Script ║" echo "╚═══════════════════════════════════════════════╝" echo "" # Check if running as root if [ "$EUID" -ne 0 ]; then echo "ERROR: Please run as root: sudo $0" exit 1 fi # Detect OS if ! command -v apt-get &> /dev/null; then echo "ERROR: This script requires Debian/Ubuntu." exit 1 fi # Require curl if ! command -v curl &> /dev/null; then echo "ERROR: curl is required but not installed." echo "" echo "Install it with:" echo " apt-get install curl" echo "" echo "Then run this command again:" echo " curl -sL https://gitea.ledrew.me/ledadmin/project-tracker/raw/branch/master/deploy/setup.sh | bash" exit 1 fi # Check for Docker DOCKER_INSTALLED=false if command -v docker &> /dev/null; then DOCKER_INSTALLED=true DOCKER_VERSION=$(docker --version 2>/dev/null | awk '{print $3}' | tr -d ',') fi # Check for docker-compose plugin COMPOSE_INSTALLED=false if docker compose version &> /dev/null; then COMPOSE_INSTALLED=true fi # Check if repo already exists REPO_DIR="/root/project-tracker" REPO_EXISTS=false if [ -d "$REPO_DIR" ]; then REPO_EXISTS=true fi # Show pre-flight echo "Pre-flight check:" echo " OS: $(lsb_release -ds 2>/dev/null || cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)" echo " Docker: ${DOCKER_INSTALLED:+$DOCKER_VERSION (installed)}" echo " Compose: ${COMPOSE_INSTALLED:+installed}" echo " Repo dir: ${REPO_EXISTS:+WARNING — $REPO_DIR already exists (will git pull)}" echo "" echo "This script will:" echo " 1. Update system packages" echo " 2. Install Docker (if not present)" echo " 3. Clone/pull the Project Tracker repo to $REPO_DIR" echo " 4. Build and start the app via Docker Compose" echo "" echo "Container ports used:" echo " Port 80 — Web UI + API" echo "" echo "Data: SQLite database is stored in a Docker named volume." echo " Use 'docker compose down -v' to DELETE the database." echo "" # Confirm — if stdin is a TTY, ask interactively. Otherwise auto-proceed after 5s. if [ -t 0 ]; then echo -n "Continue? [Y/n]: " read -r CONFIRM CONFIRM=${CONFIRM:-Y} if [ "$CONFIRM" != "Y" ] && [ "$CONFIRM" != "y" ]; then echo "Aborted." exit 0 fi else echo -n "Continue? [Y/n] (auto-proceeding in 5s): " read -r -t 5 CONFIRM 2>/dev/null || true CONFIRM=${CONFIRM:-Y} if [ "$CONFIRM" != "Y" ] && [ "$CONFIRM" != "y" ]; then echo "Aborted." exit 0 fi fi echo "" echo "=== Starting deploy ===" echo "" # Update system echo "[1/4] Updating system packages..." rm -f /etc/apt/sources.list.d/docker.list 2>/dev/null || true apt-get update -qq 2>/dev/null || apt-get update apt-get install -y -qq curl git ca-certificates gnupg > /dev/null 2>&1 # Install Docker echo "[2/4] Installing Docker..." if [ "$DOCKER_INSTALLED" = "true" ] && [ "$COMPOSE_INSTALLED" = "true" ]; then echo " Docker and Docker Compose already installed — skipping." else if [ "$DOCKER_INSTALLED" = "false" ]; then echo " Installing docker.io from Debian repos..." apt-get install -y -qq docker.io > /dev/null 2>&1 || { echo " ERROR: Could not install docker.io." exit 1 } echo " docker.io installed." else echo " Docker already installed ($DOCKER_VERSION)." fi if [ "$COMPOSE_INSTALLED" = "false" ]; then echo " Installing docker-compose-plugin..." apt-get install -y -qq docker-compose-plugin > /dev/null 2>&1 || { echo " ERROR: Could not install docker-compose-plugin." exit 1 } echo " docker-compose-plugin installed." else echo " Docker Compose already installed." fi systemctl enable docker --now > /dev/null 2>&1 || true fi # Clone or update repo echo "[3/4] Setting up Project Tracker..." if [ "$REPO_EXISTS" = "true" ]; then echo " Pulling latest changes into existing repo..." cd "$REPO_DIR" git pull else echo " Cloning repo..." git clone https://gitea.ledrew.me/ledadmin/project-tracker.git "$REPO_DIR" cd "$REPO_DIR" fi # Build and start echo "[4/4] Building and starting containers..." cd "$REPO_DIR/deploy" docker compose down --remove-orphans 2>/dev/null || true docker compose up -d --build # Wait for backend echo "Waiting for backend to start..." sleep 4 # Verify IP=$(hostname -I 2>/dev/null | awk '{print $1}' || echo "localhost") HTTP_OK=$(curl -sf -o /dev/null -w "%{http_code}" http://localhost/api/projects 2>/dev/null || echo "000") echo "" echo "=== Deploy complete ===" if [ "$HTTP_OK" = "200" ]; then echo "Project Tracker is LIVE at http://$IP" else echo "App started — verify at http://$IP" echo "(Backend may still be initializing, give it a few seconds)" fi echo "" echo "Useful commands:" echo " cd $REPO_DIR/deploy" echo " docker compose logs -f # View logs" echo " docker compose restart # Restart" echo " docker compose down # Stop" echo " docker compose down -v # Stop and DELETE database (CAREFUL!)" echo ""