From 779fde473c2ab661f76f604b75ab3b21a3c329fb Mon Sep 17 00:00:00 2001 From: hhf Date: Thu, 12 Dec 2024 10:26:31 +0530 Subject: [PATCH] Add paperless-install.sh --- paperless-install.sh | 354 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 paperless-install.sh diff --git a/paperless-install.sh b/paperless-install.sh new file mode 100644 index 0000000..4c1b8a1 --- /dev/null +++ b/paperless-install.sh @@ -0,0 +1,354 @@ +#!/bin/bash + +# Must be run with root privileges + +# Error handling +set -e +trap 'echo "Error on line $LINENO. Exit code: $?"' ERR + +# Configuration +INSTALL_DIR="/docker/paperless-ngx" +COMPOSE_FILE="${INSTALL_DIR}/docker-compose.yml" +LOG_FILE="/var/log/paperless-install.log" + +# Utility functions +log_message() { + local message="[$(date '+%Y-%m-%d %H:%M:%S')] $1" + echo "$message" + echo "$message" >> "$LOG_FILE" +} + +show_container_status() { + log_message "Current container statuses:" + echo "----------------------------------------" + docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}" + echo "----------------------------------------" +} + +check_service_status() { + local service=$1 + local container_name="paperless-ngx-${service}-1" # Fixed naming convention + + if ! docker ps -q -f name="$container_name" >/dev/null 2>&1; then + return 1 + fi + + local status=$(docker inspect -f '{{.State.Status}}' "$container_name" 2>/dev/null) + if [ "$status" != "running" ]; then + return 1 + fi + + # Only perform additional health checks for specific services + case "$service" in + "webserver") + if ! curl -sf http://localhost:8000 >/dev/null 2>&1; then + return 1 + fi + ;; + "db") + # Optional: Add PostgreSQL specific check if needed + docker exec "$container_name" pg_isready -U paperless >/dev/null 2>&1 || return 1 + ;; + "broker") + # Redis broker only needs container running status check + return 0 + ;; + esac + + return 0 +} + +verify_all_services() { + local services=("broker" "db" "webserver") + local failed_services=() + + for service in "${services[@]}"; do + case "$service" in + "broker") + # Just check if Redis is running, no wait needed + if ! check_service_status "$service"; then + failed_services+=("$service") + fi + ;; + *) + log_message "Checking $service service..." + if ! check_service_status "$service"; then + failed_services+=("$service") + fi + ;; + esac + done + + if [ ${#failed_services[@]} -ne 0 ]; then + log_message "The following services are not running properly: ${failed_services[*]}" + return 1 + fi + + log_message "All services are running properly" + return 0 +} + +check_docker_version() { + local current_version=$(docker --version | cut -d ' ' -f3 | cut -d ',' -f1) + log_message "Current Docker version: $current_version" + + # Check for updates + apt-get update >/dev/null 2>&1 + local available_version=$(apt-cache policy docker-ce | grep Candidate | cut -d ' ' -f4) + + if [ "$current_version" != "$available_version" ]; then + log_message "New Docker version available: $available_version" + read -p "Do you want to upgrade Docker? (y/N) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + apt-get install -y docker-ce docker-ce-cli containerd.io + fi + fi +} + +redeploy_service() { + local service=$1 + log_message "Redeploying $service..." + + cd "$INSTALL_DIR" + docker compose stop "$service" + docker compose rm -f "$service" + docker compose up -d "$service" + + case "$service" in + "broker") + # Redis broker needs no health wait + log_message "Redis broker redeployed" + return 0 + ;; + "db") + # Wait for database to be ready + local retries=0 + while ! check_service_status "$service" && [ $retries -lt 5 ]; do + log_message "Waiting for database to be ready..." + sleep 5 + retries=$((retries + 1)) + done + ;; + "webserver") + # Wait for webserver to be healthy + local retries=0 + while ! check_service_status "$service" && [ $retries -lt 5 ]; do + log_message "Waiting for webserver to become healthy..." + sleep 10 + retries=$((retries + 1)) + done + ;; + esac + + if [ $retries -eq 5 ]; then + log_message "Failed to redeploy $service after 5 attempts" + return 1 + fi + + log_message "$service redeployed successfully" + return 0 +} + +backup_existing_data() { + if [ -d "$INSTALL_DIR" ]; then + local backup_dir="${INSTALL_DIR}_backup_$(date +%Y%m%d_%H%M%S)" + log_message "Creating backup of existing installation at $backup_dir" + cp -r "$INSTALL_DIR" "$backup_dir" + fi +} + +check_existing_installation() { + log_message "Checking existing Paperless-ngx installation..." + + if [ -f "$COMPOSE_FILE" ]; then + log_message "Existing installation found" + show_container_status + + if verify_all_services; then + log_message "? All services are running correctly" + log_message "? Paperless-ngx is accessible at http://localhost:8000" + log_message "? Redis and PostgreSQL containers are properly isolated" + return 0 + else + log_message "? Service issues detected. Starting recovery process..." + return 1 + fi + fi + return 1 +} + +# Main script execution starts here + +# Check if script is run as root +if [ "$EUID" -ne 0 ]; then + echo "Please run as root" + exit 1 +fi + +# Initialize log file +mkdir -p "$(dirname "$LOG_FILE")" +touch "$LOG_FILE" +log_message "Starting Paperless-ngx installation/verification script" + +# Check if Docker is installed +if ! command -v docker &> /dev/null; then + log_message "Docker not found. Installing Docker..." + curl -fsSL https://get.docker.com -o get-docker.sh + sh get-docker.sh + apt-get update + apt-get install -y docker-compose-plugin + log_message "Docker installed successfully" +else + log_message "Docker already installed" + check_docker_version +fi + +# Check existing installation or proceed with new installation +if check_existing_installation; then + exit 0 +else + if [ -f "$COMPOSE_FILE" ]; then + # Attempt to recover existing installation + backup_existing_data + + # Attempt to redeploy failed services + for service in broker db webserver; do + if ! check_service_status "$service"; then + if ! redeploy_service "$service"; then + log_message "Failed to redeploy $service. Manual intervention may be required." + exit 1 + fi + fi + done + else + # New installation + log_message "Starting new Paperless-ngx installation" + + # Create installation directory + mkdir -p "$INSTALL_DIR" + cd "$INSTALL_DIR" + + # Create docker-compose.yml + cat > docker-compose.yml <<'EOF' +version: "3.4" +services: + broker: + image: redis:7 + restart: unless-stopped + networks: + - paperless_internal + expose: + - 6379 + volumes: + - redisdata:/data + + db: + image: postgres:15 + restart: unless-stopped + networks: + - paperless_internal + expose: + - 5432 + volumes: + - pgdata:/var/lib/postgresql/data + environment: + POSTGRES_DB: paperless + POSTGRES_USER: paperless + POSTGRES_PASSWORD: paperless + + webserver: + image: ghcr.io/paperless-ngx/paperless-ngx:latest + restart: unless-stopped + networks: + - paperless_internal + - paperless_external + depends_on: + - db + - broker + ports: + - "8000:8000" + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000"] + interval: 30s + timeout: 10s + retries: 5 + volumes: + - data:/usr/src/paperless/data + - media:/usr/src/paperless/media + - ./export:/usr/src/paperless/export + - ./consume:/usr/src/paperless/consume + environment: + PAPERLESS_REDIS: redis://broker:6379 + PAPERLESS_DBHOST: db + PAPERLESS_DB_USER: paperless + PAPERLESS_DB_PASSWORD: paperless + PAPERLESS_DB_NAME: paperless + PAPERLESS_TIME_ZONE: Europe/London + PAPERLESS_OCR_LANGUAGE: eng + PAPERLESS_SECRET_KEY: change-this-key + PAPERLESS_URL: https://your-domain.com + +networks: + paperless_internal: + internal: true # Only accessible within Docker + paperless_external: # For external access to webserver + +volumes: + data: + name: paperless_data + media: + name: paperless_media + pgdata: + name: paperless_pgdata + redisdata: + name: paperless_redisdata +EOF + + # Create required directories and set permissions + mkdir -p export consume + chown -R 1000:1000 export consume + + # Start services + log_message "Starting Paperless-ngx services..." + docker compose up -d + + # Give services more time to initialize on first deployment + log_message "Waiting for services to initialize (this may take a minute)..." + sleep 30 # Initial wait for containers to start + + # Additional wait loop with status checks + for i in {1..6}; do # Try for up to 1 minute more + if docker compose ps | grep -q "healthy"; then + break # Exit loop if containers are healthy + fi + log_message "Still waiting for services to be ready... (attempt $i/6)" + sleep 10 + done + if verify_all_services; then + log_message "? Installation completed successfully!" + show_container_status + + # Create superuser + log_message "Creating superuser account..." + if docker compose run --rm webserver createsuperuser; then + log_message "? Superuser created successfully" + log_message "? You can access Paperless-ngx at http://localhost:8000" + else + log_message "? Failed to create superuser. You can create one later using:" + log_message " docker compose run --rm webserver createsuperuser" + log_message "? You can access Paperless-ngx at http://localhost:8000" + fi + + log_message "Important next steps:" + log_message "1. Change the PAPERLESS_URL in docker-compose.yml to your domain" + log_message "2. Change the PAPERLESS_SECRET_KEY to a random string" + log_message "3. Set up a reverse proxy in CloudPanel" + log_message "4. Create SSL certificate for your domain" + else + log_message "Installation completed but some services are not running properly" + log_message "Please check the logs and try redeploying the failed services" + exit 1 + fi + fi +fi \ No newline at end of file