terminal

KROTEK

menu

CADDY + Opening ports installation

Choose your system:

Debian

Debian

Logo: Tobias Benjamin Kohl
CC BY-SA
Ubuntu

Ubuntu

Logo: Canonical
CC BY-SA
Rocky Linux

Rocky Linux

Logo: Rocky Enterprise Software Foundation
CC BY-SA
Alma Linux

Alma Linux

Logo: AlmaLinux OS Foundation
CC BY-SA
Alpine Linux

Alpine Linux

Logo: Alpine Linux
CC BY-SA

Install/Uninstall script (Docker /
Warning: Undefined array key "
Deprecated: htmlspecialchars(): Passing null to parameter " in /var/www/scripts/PHP_HTML/maininstall.php on line 49

Warning: Trying to access array offset on null in /var/www/scripts/PHP_HTML/maininstall.php on line 49

Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/scripts/PHP_HTML/maininstall.php on line 49
)

download content_copy expand_more
#!/bin/bash
set +e
# ========== COLORS ==========
NC='\033[0m'
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
BLUE='\033[38;5;117m'
BOLD='\033[1m'

# ========== LOG FUNCTIONS ==========
log_info()    { echo -e "${BLUE}[INFO]${NC} $*"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $*"; }
log_success() { echo -e "${GREEN}[OK]${NC} $*"; }

# ========== PRINT BOX FUNCTION ==========
print_in_box() {
  local title="$1"
  shift
  local lines=("$@")
  local max_len=${#title}
  for line in "${lines[@]}"; do
    (( ${#line} > max_len )) && max_len=${#line}
  done
  local border_top="┌$(printf '─%.0s' $(seq 1 $((max_len + 2))))┐"
  local border_bottom="└$(printf '─%.0s' $(seq 1 $((max_len + 2))))┘"
  echo -e "${BLUE}${border_top}${NC}"
  printf "${BLUE}│ ${BOLD}%-*s${BLUE} │${NC}\n" "$max_len" "$title"
  echo -e "${BLUE}├$(printf '─%.0s' $(seq 1 $((max_len + 2))))┤${NC}"
  for line in "${lines[@]}"; do
    printf "${BLUE}│ %-*s │${NC}\n" "$max_len" "$line"
  done
  echo -e "${BLUE}${border_bottom}${NC}"
}

# ========== SPINNER & RUN TASK ==========
spinner_pid=""
start_spinner() {
  local msg="$1"
  echo -ne "${BLUE}[INFO]${NC} $msg... "
  trap stop_spinner INT
  (
    local spin='-\|/'
    while true; do
      for i in $(seq 0 $(( ${#spin} - 1 )) ); do
        echo -ne "\b${spin:$i:1}"
        sleep 0.1
      done
    done
  ) & spinner_pid=$!
  disown
}
stop_spinner() {
  if [[ -n "$spinner_pid" ]]; then
    kill "$spinner_pid" &>/dev/null || true
    wait "$spinner_pid" 2>/dev/null || true
    spinner_pid=""
  fi
  echo -e "\b${GREEN}✓${NC}"
  trap - INT
}
run_step() {
  start_spinner "$1"
  shift
  "$@" &>/dev/null
  stop_spinner
}
run_multistep() {
  start_spinner "$1"
  shift
  {
    "$@"
  } &>/dev/null
  stop_spinner
}

# ========== FILE/DIRECTORY DEFINITIONS ==========
COMPOSE_FILE="docker-compose.yml"
CADDY_DIR="caddy_config"
CADDY_FILE="$CADDY_DIR/Caddyfile"
CADDY_DATA_DIR="caddy_data"
PHP_DIR="php_config"
PHP_DOCKERFILE="$PHP_DIR/Dockerfile"
WEB_DIR="www"
TEST_FILE="$WEB_DIR/index.php"
DOCKER_COMPOSE_CMD="" # Will be set by check_deps

# ========== DETECT DISTRIBUTION ==========
DISTRO=""
if [[ -f /etc/os-release ]]; then
  . /etc/os-release
  DISTRO=$(echo "$ID" | tr '[:upper:]' '[:lower:]')
fi
[[ "$DISTRO" == "rhel" ]] && DISTRO="centos"
log_info "Detected distribution: ${BOLD}${DISTRO}${NC}"

# ========== PACKAGE UNINSTALL COMMANDS ==========
DOCKER_PKG_LIST="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras"
DOCKER_PURGE_CMD=""
DOCKER_CLEANUP_CMD="sudo rm -rf /var/lib/docker && sudo rm -rf /var/lib/containerd && sudo rm -rf /etc/docker"

case "$DISTRO" in
  debian|ubuntu)
    DOCKER_PURGE_CMD="sudo apt-get purge -y $DOCKER_PKG_LIST"
    ;;
  almalinux|rocky|centos|fedora)
    DOCKER_PURGE_CMD="sudo dnf remove -y $DOCKER_PKG_LIST"
    ;;
  *)
    DOCKER_PURGE_CMD="echo 'Distro not supported for auto-uninstall'"
    ;;
esac


# ========== CHECK DEPENDENCIES & INSTALL ==========
check_deps() {
  local docker_ok=0
  local compose_ok=0

  # Check for Docker
  if ! command -v docker >/dev/null 2>&1; then
    log_warn "Docker is not installed."
  else
    docker_ok=1
  fi

  # Check for Docker Compose (v2)
  if ! docker compose version &>/dev/null 2>&1; then
    # Check for v1 as fallback
    if ! command -v docker-compose &>/dev/null 2>&1; then
      log_warn "Docker Compose (v1 or v2) is not installed."
    else
      compose_ok=1
      DOCKER_COMPOSE_CMD="docker-compose"
    fi
  else
    compose_ok=1
    DOCKER_COMPOSE_CMD="docker compose"
  fi

  # If both are ok, we're done
  if [[ "$docker_ok" -eq 1 && "$compose_ok" -eq 1 ]]; then
     log_success "Docker & Docker Compose found. Using: ${BOLD}${DOCKER_COMPOSE_CMD}${NC}"
     return 0
  fi

  # If something is missing, ask to install
  log_info "Docker or Docker Compose is missing."
  read -p "$(echo -e "${YELLOW}[INFO]${NC} Attempt to install Docker & Docker Compose automatically? [y/n]: ")" install_docker_prompt
  if [[ ! "$install_docker_prompt" =~ ^[Yy]$ ]]; then
    log_error "Cannot proceed without Docker. Exiting."
    exit 1
  fi

  # --- Installation Step ---
  log_info "Downloading Docker installation script..."
  if ! curl -fsSL https://get.docker.com -o get-docker.sh; then
    log_error "Failed to download Docker install script."
    exit 1
  fi
  
  log_info "Running Docker installation script (requires sudo)..."
  run_multistep "Installing Docker" sudo sh get-docker.sh

  # Check if install succeeded
  if ! command -v docker >/dev/null 2>&1; then
     log_error "Docker installation failed. Please check the output and run manually."
     rm -f get-docker.sh
     exit 1
  fi
  
  log_success "Docker & Docker Compose installed successfully."
  rm -f get-docker.sh # Clean up

  # --- Post-install ---
  run_step "Adding current user ($USER) to 'docker' group" sudo usermod -aG docker $USER

  log_success "User $USER added to the 'docker' group."
  echo -e "\n${BOLD}${RED}!!!!!!!!!!!!!!!!!! IMPORTANT ACTION REQUIRED !!!!!!!!!!!!!!!!!!${NC}"
  local lines=(
    "You MUST log out and log back in for group changes to take effect."
    "Alternatively, you can run: newgrp docker"
    " "
    "Please re-run this script AFTER logging out and back in."
  )
  print_in_box "Installation Complete - RELOGIN REQUIRED" "${lines[@]}"
  exit 0 # Exit script gracefully, forcing user to relog
}

# ========== MENU ==========
echo -e "\n${BOLD}${YELLOW}=== Docker Caddy + PHP Stack Manager ===${NC}\n"

PS3="Choose an option: "
select opt in "Deploy (Start stack)" "Remove (Stop and delete stack)" "Uninstall Docker" "Exit"; do
  case $opt in
    "Deploy (Start stack)") ACTION=1; break;;
    "Remove (Stop and delete stack)") ACTION=2; break;;
    "Uninstall Docker") ACTION=3; break;;
    Exit) exit 0;;
    *) log_error "Invalid option";;
  esac
done

# ========== DEPLOY ==========
if [[ "$ACTION" == "1" ]]; then
  echo -e "\n${BOLD}${YELLOW}=== Starting Stack ===${NC}\n"
  check_deps

  run_step "Creating directory structure" mkdir -p "$CADDY_DIR" "$CADDY_DATA_DIR" "$PHP_DIR" "$WEB_DIR"

  # --- Create docker-compose.yml ---
  if [[ ! -f "$COMPOSE_FILE" ]]; then
    run_step "Generating $COMPOSE_FILE"
    cat <<EOF > "$COMPOSE_FILE"
version: '3.8'

services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp" # For HTTP/3
    volumes:
      - ./$CADDY_FILE:/etc/caddy/Caddyfile
      - ./$WEB_DIR:/var/www/html
      - ./$CADDY_DATA_DIR:/data # For SSL certs etc.
    depends_on:
      - php

  php:
    build: 
      context: ./$PHP_DIR
    restart: unless-stopped
    volumes:
      - ./$WEB_DIR:/var/www/html

volumes:
  $CADDY_DATA_DIR:
EOF
  else
    log_warn "$COMPOSE_FILE already exists, skipping."
  fi

  # --- Create Caddyfile ---
  if [[ ! -f "$CADDY_FILE" ]]; then
    run_step "Generating $CADDY_FILE"
    cat <<EOF > "$CADDY_FILE"
{
	# Email for Let's Encrypt
	email user@example.com
}

:80 {
	# Set the root directory
	root * /var/www/html

	# Enable PHP-FPM
	# Forward PHP requests to the 'php' container on port 9000
	php_fastcgi php:9000

	# Enable file serving
	file_server
}

# You can add your domain when ready, e.g.:
# yourdomain.com {
# 	root * /var/www/html
# 	php_fastcgi php:9000
# 	file_server
# }
EOF
  else
    log_warn "$CADDY_FILE already exists, skipping."
  fi

  # --- Create PHP Dockerfile ---
  if [[ ! -f "$PHP_DOCKERFILE" ]]; then
    run_step "Generating $PHP_DOCKERFILE (with extensions)"
    cat <<EOF > "$PHP_DOCKERFILE"
# Using PHP-FPM image (Alpine for smaller size)
FROM php:8.3-fpm-alpine

# Install dependencies and extensions (as per original script)
RUN apk add --no-cache \$PHPIZE_DEPS \
    && docker-php-ext-install pdo pdo_mysql mbstring xml
EOF
  else
    log_warn "$PHP_DOCKERFILE already exists, skipping."
  fi

  # --- Create test file ---
  if [[ ! -f "$TEST_FILE" ]]; then
    run_step "Generating test file $TEST_FILE"
    cat <<EOF > "$TEST_FILE"
<?php
phpinfo();
?>
EOF
  else
    log_warn "$TEST_FILE already exists, skipping."
  fi

  run_multistep "Building PHP image" $DOCKER_COMPOSE_CMD build
  run_multistep "Pulling Caddy image" $DOCKER_COMPOSE_CMD pull caddy
  run_multistep "Starting containers in background" $DOCKER_COMPOSE_CMD up -d

  lines=(
    "Caddy & PHP-FPM are running."
    " "
    "Web root dir  : $PWD/$WEB_DIR"
    "Caddy Config  : $PWD/$CADDY_FILE"
    "PHP Config    : $PWD/$PHP_DOCKERFILE"
    "Ports (HTTP)  : 80"
    "Ports (HTTPS) : 443"
    " "
    "Test at: http://localhost"
  )
  print_in_box "Stack Deployed" "${lines[@]}"
  
  log_warn "Remember to open ports 80 and 443 on your HOST firewall (e.g., ufw, firewalld)."
  log_success "Deployment complete."

# ========== REMOVE STACK ==========
elif [[ "$ACTION" == "2" ]]; then
  echo -e "\n${BOLD}${YELLOW}=== Stopping and Removing Stack ===${NC}\n"
  check_deps

  if [[ ! -f "$COMPOSE_FILE" ]]; then
    log_error "$COMPOSE_FILE not found. Are you in the correct directory?"
    exit 1
  fi

  run_multistep "Stopping and removing containers" $DOCKER_COMPOSE_CMD down

  read -p "$(echo -e "${YELLOW}[INFO]${NC} Remove config files ($COMPOSE_FILE, $CADDY_DIR, $PHP_DIR)? [y/n]: ")" remove_configs
  if [[ "$remove_configs" =~ ^[Yy]$ ]]; then
    run_step "Removing config files" rm -rf "$COMPOSE_FILE" "$CADDY_DIR" "$PHP_DIR"
  fi

  read -p "$(echo -e "${YELLOW}[INFO]${NC} Remove web data (directory $WEB_DIR)? [y/n]: ")" remove_www
  if [[ "$remove_www" =~ ^[YY]$ ]]; then
    run_step "Removing web data" rm -rf "$WEB_DIR"
  fi

  read -p "$(echo -e "${YELLOW}[INFO]${NC} Remove persistent Caddy data (SSL certs in $CADDY_DATA_DIR)? [y/n]: ")" remove_caddy_data
  if [[ "$remove_caddy_data" =~ ^[YY]$ ]]; then
    run_step "Removing Caddy data" rm -rf "$CADDY_DATA_DIR"
  fi
  
  read -p "$(echo -e "${YELLOW}[INFO]${NC} Clean unused Docker images (prune)? [y/n]: ")" prune_images
  if [[ "$prune_images" =~ ^[Yy]$ ]]; then
    run_multistep "Pruning images" docker image prune -f
  fi

  log_success "Stack removal complete."

# ========== UNINSTALL DOCKER ==========
elif [[ "$ACTION" == "3" ]]; then
  echo -e "\n${BOLD}${RED}=== UNINSTALL DOCKER ===${NC}\n"
  
  if [[ "$DISTRO" == "" ]]; then
      log_error "Unsupported distribution. Cannot determine package manager for uninstallation."
      exit 1
  fi

  log_warn "${BOLD}This action is highly destructive and will completely remove Docker from this system.${NC}"
  log_warn "It will purge all packages, data volumes, images, and configuration."
  
  read -p "$(echo -e "${RED}[DANGER]${NC} Are you absolutely sure you want to uninstall Docker? [y/n]: ")" uninstall_docker_prompt
  if [[ ! "$uninstall_docker_prompt" =~ ^[Yy]$ ]]; then
    log_info "Docker uninstallation cancelled."
    exit 0
  fi

  run_step "Stopping Docker service" sudo systemctl stop docker
  run_multistep "Purging Docker packages" bash -c "$DOCKER_PURGE_CMD"
  run_multistep "Deleting Docker data directories" bash -c "$DOCKER_CLEANUP_CMD"

  # Remove user from docker group
  if getent group docker | grep -q "\b$USER\b"; then
    run_step "Removing user $USER from 'docker' group" sudo gpasswd -d $USER docker
  else
    log_info "User $USER is not in the 'docker' group, skipping."
  fi
  
  rm -f get-docker.sh # Clean up install script if it exists

  log_success "Docker has been completely removed from the system."
fi

Use the following command to auto-download and run:


Warning: Undefined array key "
Deprecated: htmlspecialchars(): Passing null to parameter " in /var/www/scripts/PHP_HTML/autoscripts.php on line 87

Warning: Trying to access array offset on null in /var/www/scripts/PHP_HTML/autoscripts.php on line 87
curl -fsSL -o script.sh "https://krotek.serveblog.net/how-to-install/WEB-SERVER/CADDY/scripts.php?variant=docker&type=script&system=%3Cbr+%2F%3E%3Cb%3EDeprecated%3C%2Fb%3E%3A++htmlspecialchars%28%29%3A+Passing+null+to+parameter+" && chmod +x script.sh && sudo ./script.sh