- Introduced `test_installer_config.sh` to validate the configuration generated by the installer. - The script sets up a test environment, simulates installer input, and generates a configuration file. - It includes a function to create a sample configuration and validates it against the expected structure. - Added detailed output for build success and configuration validation results. - Cleans up the test directory after execution.
1274 lines
48 KiB
Bash
Executable File
1274 lines
48 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# HMAC File Server Installer Script
|
|
# Version: 3.2
|
|
# Compatible with systemd Linux distributions
|
|
|
|
set -e
|
|
|
|
# Trap to handle script errors
|
|
trap 'handle_error $? $LINENO' ERR
|
|
|
|
# Error handling function
|
|
handle_error() {
|
|
local exit_code=$1
|
|
local line_number=$2
|
|
echo -e "${RED}Error occurred in script at line $line_number with exit code $exit_code${NC}"
|
|
echo -e "${YELLOW}Installation failed. Please check the error message above.${NC}"
|
|
exit $exit_code
|
|
}
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Default values
|
|
DEFAULT_USER="hmac-server"
|
|
DEFAULT_INSTALL_DIR="/opt/hmac-file-server"
|
|
DEFAULT_CONFIG_DIR="/etc/hmac-file-server"
|
|
DEFAULT_DATA_DIR="/var/lib/hmac-file-server"
|
|
DEFAULT_LOG_DIR="/var/log/hmac-file-server"
|
|
DEFAULT_PORT="8080"
|
|
DEFAULT_METRICS_PORT="9090"
|
|
|
|
# Help function
|
|
show_help() {
|
|
echo -e "${BLUE}HMAC File Server 3.2 Installer${NC}"
|
|
echo ""
|
|
echo "Usage: $0 [OPTION]"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --help Show this help message"
|
|
echo " --uninstall Uninstall HMAC File Server completely"
|
|
echo ""
|
|
echo "Environment Variables (optional):"
|
|
echo " HMAC_SECRET Pre-set HMAC secret (minimum 32 characters)"
|
|
echo " JWT_SECRET Pre-set JWT secret (minimum 32 characters)"
|
|
echo ""
|
|
echo "Example:"
|
|
echo " HMAC_SECRET='your-super-secret-hmac-key-here-32chars' sudo -E $0"
|
|
echo ""
|
|
echo "This installer will:"
|
|
echo " • Install Go 1.24 (if not present)"
|
|
echo " • Create system user and directories"
|
|
echo " • Build and install HMAC File Server"
|
|
echo " • Configure systemd service"
|
|
echo " • Install Redis and/or ClamAV (optional)"
|
|
echo ""
|
|
echo "For XMPP operators: This installer is optimized for easy integration"
|
|
echo "with Prosody, Ejabberd, and other XMPP servers."
|
|
echo ""
|
|
}
|
|
|
|
# Check for help flag first (before root check)
|
|
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
show_help
|
|
exit 0
|
|
fi
|
|
|
|
# Professional installer header with branding
|
|
echo ""
|
|
echo -e "${BLUE} __ _____ __ ${NC}"
|
|
echo -e "${BLUE} / /_ ____ ___ ____ ______ / __(_) /__ ________ ______ _____ _____${NC}"
|
|
echo -e "${BLUE} / __ \\/ __ \`__ \\/ __ \`/ ___/_____/ /_/ / / _ \\______/ ___/ _ \\/ ___/ | / / _ \\/ ___/${NC}"
|
|
echo -e "${BLUE} / / / / / / / / / /_/ / /__/_____/ __/ / / __/_____(__ ) __/ / | |/ / __/ / ${NC}"
|
|
echo -e "${BLUE}/_/ /_/_/ /_/ /_/\\__,_/\\___/ /_/ /_/_/\\___/ /____/\\___/_/ |___/\\___/_/ ${NC}"
|
|
echo ""
|
|
echo -e "${BLUE} █ HMAC File Server 3.2 Installer █${NC}"
|
|
echo -e "${BLUE} Professional XMPP Integration${NC}"
|
|
echo ""
|
|
echo -e "${YELLOW}────────────────────────────────────────────────────────────────────────────────${NC}"
|
|
echo -e "${GREEN} ✓ Secure File Uploads & Downloads ✓ JWT & HMAC Authentication${NC}"
|
|
echo -e "${GREEN} ✓ Prometheus Metrics Integration ✓ ClamAV Virus Scanning${NC}"
|
|
echo -e "${GREEN} ✓ Redis Cache & Session Management ✓ Chunked Upload/Download Support${NC}"
|
|
echo -e "${YELLOW}────────────────────────────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
|
|
# Check if running as root
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo -e "${RED}This script must be run as root (use sudo)${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check for systemd
|
|
if ! command -v systemctl &> /dev/null; then
|
|
echo -e "${RED}Error: systemctl not found. This installer requires a systemd-based Linux distribution.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Pre-installation checks
|
|
pre_installation_checks() {
|
|
echo -e "${YELLOW}Running pre-installation checks...${NC}"
|
|
|
|
# Check if service already exists
|
|
if systemctl is-enabled hmac-file-server.service &>/dev/null; then
|
|
echo -e "${YELLOW}Warning: HMAC File Server service already exists${NC}"
|
|
read -p "Do you want to continue and overwrite the existing installation? (y/N): " OVERWRITE
|
|
if [[ ! $OVERWRITE =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}Installation cancelled${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
# Stop existing service
|
|
echo -e "${YELLOW}Stopping existing service...${NC}"
|
|
systemctl stop hmac-file-server.service || true
|
|
fi
|
|
|
|
# Check available disk space (minimum 1GB)
|
|
AVAILABLE_SPACE=$(df / | awk 'NR==2 {print $4}')
|
|
if [[ $AVAILABLE_SPACE -lt 1048576 ]]; then
|
|
echo -e "${RED}Error: Insufficient disk space. At least 1GB required${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if we're in the correct directory (should contain go.mod)
|
|
if [[ ! -f "go.mod" ]]; then
|
|
echo -e "${RED}Error: go.mod not found. Please run this installer from the HMAC File Server source directory${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✅ Pre-installation checks passed${NC}"
|
|
echo ""
|
|
}
|
|
|
|
# Check for Go installation
|
|
check_go() {
|
|
if ! command -v go &> /dev/null; then
|
|
echo -e "${YELLOW}Go is not installed. Installing Go 1.24...${NC}"
|
|
|
|
# Detect architecture
|
|
ARCH=$(uname -m)
|
|
case $ARCH in
|
|
x86_64) GO_ARCH="amd64" ;;
|
|
aarch64|arm64) GO_ARCH="arm64" ;;
|
|
armv7l) GO_ARCH="armv6l" ;;
|
|
*) echo -e "${RED}Unsupported architecture: $ARCH${NC}"; exit 1 ;;
|
|
esac
|
|
|
|
# Download and install Go
|
|
cd /tmp
|
|
wget -q "https://go.dev/dl/go1.24.linux-${GO_ARCH}.tar.gz"
|
|
tar -C /usr/local -xzf "go1.24.linux-${GO_ARCH}.tar.gz"
|
|
|
|
# Add Go to PATH
|
|
echo 'export PATH=$PATH:/usr/local/go/bin' >> /etc/profile
|
|
export PATH=$PATH:/usr/local/go/bin
|
|
|
|
echo -e "${GREEN}Go 1.24 installed successfully${NC}"
|
|
else
|
|
GO_VERSION=$(go version | awk '{print $3}' | sed 's/go//')
|
|
echo -e "${GREEN}Go $GO_VERSION is already installed${NC}"
|
|
fi
|
|
}
|
|
|
|
# User input function
|
|
get_user_input() {
|
|
echo -e "${BLUE}Configuration Setup${NC}"
|
|
echo "Please provide the following information (or press Enter for defaults):"
|
|
echo ""
|
|
|
|
# System user
|
|
read -p "System user for HMAC File Server [$DEFAULT_USER]: " HMAC_USER
|
|
HMAC_USER=${HMAC_USER:-$DEFAULT_USER}
|
|
|
|
# Installation directory
|
|
read -p "Installation directory [$DEFAULT_INSTALL_DIR]: " INSTALL_DIR
|
|
INSTALL_DIR=${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}
|
|
|
|
# Data directory
|
|
read -p "Data directory (uploads) [$DEFAULT_DATA_DIR]: " DATA_DIR
|
|
DATA_DIR=${DATA_DIR:-$DEFAULT_DATA_DIR}
|
|
|
|
# Server port
|
|
read -p "Server port [$DEFAULT_PORT]: " SERVER_PORT
|
|
SERVER_PORT=${SERVER_PORT:-$DEFAULT_PORT}
|
|
|
|
# Metrics port
|
|
read -p "Metrics port [$DEFAULT_METRICS_PORT]: " METRICS_PORT
|
|
METRICS_PORT=${METRICS_PORT:-$DEFAULT_METRICS_PORT}
|
|
|
|
# HMAC secret
|
|
if [[ -n "$HMAC_SECRET" ]]; then
|
|
# Use environment variable if provided
|
|
if [[ ${#HMAC_SECRET} -ge 32 ]]; then
|
|
echo -e "${GREEN}✅ Using HMAC secret from environment variable${NC}"
|
|
else
|
|
echo -e "${RED}Error: HMAC_SECRET environment variable must be at least 32 characters long${NC}"
|
|
echo -e "${YELLOW}Current length: ${#HMAC_SECRET}${NC}"
|
|
exit 1
|
|
fi
|
|
else
|
|
# Interactive input with auto-generation option
|
|
echo ""
|
|
echo -e "${BLUE}HMAC Secret Configuration${NC}"
|
|
echo "Choose how to set the HMAC secret:"
|
|
echo " 1) Generate automatically (recommended)"
|
|
echo " 2) Enter manually"
|
|
echo ""
|
|
|
|
while true; do
|
|
read -p "Choice [1]: " hmac_choice
|
|
hmac_choice=${hmac_choice:-1}
|
|
|
|
case $hmac_choice in
|
|
1)
|
|
echo -e "${YELLOW}Generating secure HMAC secret...${NC}"
|
|
HMAC_SECRET=$(generate_random_key 48)
|
|
echo -e "${GREEN}✅ Generated 48-character HMAC secret${NC}"
|
|
echo -e "${BLUE}Secret preview: ${HMAC_SECRET:0:8}...${HMAC_SECRET: -8}${NC}"
|
|
break
|
|
;;
|
|
2)
|
|
while true; do
|
|
echo -n "HMAC secret (minimum 32 characters): "
|
|
# Use bash built-in silent read if available
|
|
if read -s -r HMAC_SECRET 2>/dev/null; then
|
|
echo ""
|
|
else
|
|
# Fallback: use regular read with warning
|
|
echo ""
|
|
echo -e "${YELLOW}⚠️ Note: Input will be visible (your terminal doesn't support hidden input)${NC}"
|
|
echo -n "HMAC secret (minimum 32 characters): "
|
|
read -r HMAC_SECRET
|
|
fi
|
|
|
|
if [[ ${#HMAC_SECRET} -ge 32 ]]; then
|
|
echo -e "${GREEN}✅ HMAC secret accepted (${#HMAC_SECRET} characters)${NC}"
|
|
break 2
|
|
else
|
|
echo -e "${RED}HMAC secret must be at least 32 characters long (you entered ${#HMAC_SECRET} characters)${NC}"
|
|
echo -e "${YELLOW}Tip: Choose option 1 for automatic generation${NC}"
|
|
fi
|
|
done
|
|
;;
|
|
*)
|
|
echo -e "${RED}Please enter 1 or 2${NC}"
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
# JWT settings
|
|
echo ""
|
|
read -p "Enable JWT authentication? (y/N): " ENABLE_JWT
|
|
if [[ $ENABLE_JWT =~ ^[Yy]$ ]]; then
|
|
ENABLE_JWT="true"
|
|
|
|
# JWT secret
|
|
if [[ -n "$JWT_SECRET" ]]; then
|
|
# Use environment variable if provided
|
|
if [[ ${#JWT_SECRET} -ge 32 ]]; then
|
|
echo -e "${GREEN}✅ Using JWT secret from environment variable${NC}"
|
|
else
|
|
echo -e "${RED}Error: JWT_SECRET environment variable must be at least 32 characters long${NC}"
|
|
echo -e "${YELLOW}Current length: ${#JWT_SECRET}${NC}"
|
|
exit 1
|
|
fi
|
|
else
|
|
# Interactive input with auto-generation option
|
|
echo ""
|
|
echo -e "${BLUE}JWT Secret Configuration${NC}"
|
|
echo "Choose how to set the JWT secret:"
|
|
echo " 1) Generate automatically (recommended)"
|
|
echo " 2) Enter manually"
|
|
echo ""
|
|
|
|
while true; do
|
|
read -p "Choice [1]: " jwt_choice
|
|
jwt_choice=${jwt_choice:-1}
|
|
|
|
case $jwt_choice in
|
|
1)
|
|
echo -e "${YELLOW}Generating secure JWT secret...${NC}"
|
|
JWT_SECRET=$(generate_random_key 48)
|
|
echo -e "${GREEN}✅ Generated 48-character JWT secret${NC}"
|
|
echo -e "${BLUE}Secret preview: ${JWT_SECRET:0:8}...${JWT_SECRET: -8}${NC}"
|
|
break
|
|
;;
|
|
2)
|
|
while true; do
|
|
echo -n "JWT secret (minimum 32 characters): "
|
|
# Use bash built-in silent read if available
|
|
if read -s -r JWT_SECRET 2>/dev/null; then
|
|
echo ""
|
|
else
|
|
# Fallback: use regular read with warning
|
|
echo ""
|
|
echo -e "${YELLOW}⚠️ Note: Input will be visible (your terminal doesn't support hidden input)${NC}"
|
|
echo -n "JWT secret (minimum 32 characters): "
|
|
read -r JWT_SECRET
|
|
fi
|
|
|
|
if [[ ${#JWT_SECRET} -ge 32 ]]; then
|
|
echo -e "${GREEN}✅ JWT secret accepted (${#JWT_SECRET} characters)${NC}"
|
|
break 2
|
|
else
|
|
echo -e "${RED}JWT secret must be at least 32 characters long (you entered ${#JWT_SECRET} characters)${NC}"
|
|
echo -e "${YELLOW}Tip: Choose option 1 for automatic generation${NC}"
|
|
fi
|
|
done
|
|
;;
|
|
*)
|
|
echo -e "${RED}Please enter 1 or 2${NC}"
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
# JWT expiration
|
|
read -p "JWT token expiration [24h]: " JWT_EXPIRATION
|
|
JWT_EXPIRATION=${JWT_EXPIRATION:-"24h"}
|
|
|
|
# JWT algorithm
|
|
read -p "JWT algorithm (HS256/HS384/HS512) [HS256]: " JWT_ALGORITHM
|
|
JWT_ALGORITHM=${JWT_ALGORITHM:-"HS256"}
|
|
else
|
|
ENABLE_JWT="false"
|
|
JWT_SECRET=""
|
|
JWT_EXPIRATION="24h"
|
|
JWT_ALGORITHM="HS256"
|
|
fi
|
|
|
|
# Redis settings
|
|
echo ""
|
|
read -p "Enable Redis integration? (y/N): " ENABLE_REDIS
|
|
if [[ $ENABLE_REDIS =~ ^[Yy]$ ]]; then
|
|
ENABLE_REDIS="true"
|
|
read -p "Redis host [localhost]: " REDIS_HOST
|
|
REDIS_HOST=${REDIS_HOST:-"localhost"}
|
|
read -p "Redis port [6379]: " REDIS_PORT
|
|
REDIS_PORT=${REDIS_PORT:-"6379"}
|
|
read -p "Redis database [0]: " REDIS_DB
|
|
REDIS_DB=${REDIS_DB:-"0"}
|
|
read -s -p "Redis password (optional): " REDIS_PASSWORD
|
|
echo ""
|
|
else
|
|
ENABLE_REDIS="false"
|
|
fi
|
|
|
|
# ClamAV settings
|
|
echo ""
|
|
read -p "Enable ClamAV virus scanning? (y/N): " ENABLE_CLAMAV
|
|
if [[ $ENABLE_CLAMAV =~ ^[Yy]$ ]]; then
|
|
ENABLE_CLAMAV="true"
|
|
CLAMAV_CONFIG="socket = \"/var/run/clamav/clamd.ctl\"" # Default, will be updated during installation
|
|
else
|
|
ENABLE_CLAMAV="false"
|
|
CLAMAV_CONFIG=""
|
|
fi
|
|
|
|
# SSL/TLS settings
|
|
echo ""
|
|
read -p "Enable SSL/TLS? (y/N): " ENABLE_TLS
|
|
if [[ $ENABLE_TLS =~ ^[Yy]$ ]]; then
|
|
ENABLE_TLS="true"
|
|
read -p "SSL certificate path: " SSL_CERT
|
|
read -p "SSL private key path: " SSL_KEY
|
|
else
|
|
ENABLE_TLS="false"
|
|
fi
|
|
|
|
# Show configuration summary
|
|
# Professional configuration summary
|
|
echo ""
|
|
echo -e "${BLUE} █ Configuration Summary █${NC}"
|
|
echo -e "${YELLOW}────────────────────────────────────────────────────────────────${NC}"
|
|
echo -e "${YELLOW}System User:${NC} $HMAC_USER"
|
|
echo -e "${YELLOW}Install Dir:${NC} $INSTALL_DIR"
|
|
echo -e "${YELLOW}Data Dir:${NC} $DATA_DIR"
|
|
echo -e "${YELLOW}Server Port:${NC} $SERVER_PORT"
|
|
echo -e "${YELLOW}Metrics Port:${NC} $METRICS_PORT"
|
|
echo -e "${YELLOW}JWT Auth:${NC} $([[ "$ENABLE_JWT" == "true" ]] && echo "✅ Enabled" || echo "❌ Disabled")"
|
|
echo -e "${YELLOW}Redis:${NC} $([[ "$ENABLE_REDIS" == "true" ]] && echo "✅ Enabled ($REDIS_HOST:$REDIS_PORT)" || echo "❌ Disabled")"
|
|
echo -e "${YELLOW}ClamAV:${NC} $([[ "$ENABLE_CLAMAV" == "true" ]] && echo "✅ Enabled" || echo "❌ Disabled")"
|
|
echo -e "${YELLOW}SSL/TLS:${NC} $([[ "$ENABLE_TLS" == "true" ]] && echo "✅ Enabled" || echo "❌ Disabled")"
|
|
echo -e "${YELLOW}────────────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
read -p "Continue with installation? (y/N): " CONFIRM_INSTALL
|
|
if [[ ! $CONFIRM_INSTALL =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}Installation cancelled by user${NC}"
|
|
exit 0
|
|
fi
|
|
}
|
|
|
|
# Create system user
|
|
create_user() {
|
|
if ! id "$HMAC_USER" &>/dev/null; then
|
|
echo -e "${YELLOW}Creating system user: $HMAC_USER${NC}"
|
|
useradd --system --home-dir "$INSTALL_DIR" --shell /bin/false --comment "HMAC File Server" "$HMAC_USER"
|
|
else
|
|
echo -e "${GREEN}User $HMAC_USER already exists${NC}"
|
|
fi
|
|
}
|
|
|
|
# Create directories
|
|
create_directories() {
|
|
echo -e "${YELLOW}Creating directories...${NC}"
|
|
|
|
mkdir -p "$INSTALL_DIR"
|
|
mkdir -p "$DEFAULT_CONFIG_DIR"
|
|
mkdir -p "$DATA_DIR/uploads"
|
|
mkdir -p "$DATA_DIR/deduplication"
|
|
mkdir -p "$DATA_DIR/runtime"
|
|
mkdir -p "$DEFAULT_LOG_DIR"
|
|
|
|
# Set ownership
|
|
chown -R "$HMAC_USER:$HMAC_USER" "$INSTALL_DIR"
|
|
chown -R "$HMAC_USER:$HMAC_USER" "$DATA_DIR"
|
|
chown -R "$HMAC_USER:$HMAC_USER" "$DEFAULT_LOG_DIR"
|
|
|
|
# Set permissions
|
|
chmod 755 "$INSTALL_DIR"
|
|
chmod 755 "$DATA_DIR"
|
|
chmod 750 "$DEFAULT_LOG_DIR"
|
|
}
|
|
|
|
# Build HMAC File Server
|
|
build_server() {
|
|
echo -e "${YELLOW}Building HMAC File Server...${NC}"
|
|
|
|
# Build the server
|
|
cd "$(dirname "$0")"
|
|
go build -o "$INSTALL_DIR/hmac-file-server" cmd/server/main.go cmd/server/helpers.go cmd/server/config_validator.go cmd/server/config_test_scenarios.go
|
|
|
|
# Set ownership and permissions
|
|
chown "$HMAC_USER:$HMAC_USER" "$INSTALL_DIR/hmac-file-server"
|
|
chmod 755 "$INSTALL_DIR/hmac-file-server"
|
|
|
|
echo -e "${GREEN}HMAC File Server built successfully${NC}"
|
|
}
|
|
|
|
# Generate configuration file
|
|
generate_config() {
|
|
echo -e "${YELLOW}Generating configuration file...${NC}"
|
|
|
|
cat > "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
# HMAC File Server Configuration
|
|
# Generated by installer on $(date)
|
|
|
|
[server]
|
|
bind_ip = "0.0.0.0"
|
|
listenport = "$SERVER_PORT"
|
|
unixsocket = false
|
|
storagepath = "$DATA_DIR/uploads"
|
|
metricsenabled = true
|
|
metricsport = "$METRICS_PORT"
|
|
deduplicationenabled = true
|
|
deduplicationpath = "$DATA_DIR/deduplication"
|
|
filenaming = "HMAC"
|
|
force_protocol = "auto"
|
|
pidfilepath = "$DATA_DIR/runtime/hmac-file-server.pid"
|
|
EOF
|
|
|
|
if [[ $ENABLE_TLS == "true" ]]; then
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
sslenabled = true
|
|
sslcert = "$SSL_CERT"
|
|
sslkey = "$SSL_KEY"
|
|
EOF
|
|
else
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
sslenabled = false
|
|
EOF
|
|
fi
|
|
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[security]
|
|
secret = "$HMAC_SECRET"
|
|
enablejwt = $ENABLE_JWT
|
|
EOF
|
|
|
|
if [[ $ENABLE_JWT == "true" ]]; then
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
jwtsecret = "$JWT_SECRET"
|
|
jwtalgorithm = "$JWT_ALGORITHM"
|
|
jwtexpiration = "$JWT_EXPIRATION"
|
|
EOF
|
|
fi
|
|
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[uploads]
|
|
allowedextensions = [".txt", ".pdf", ".jpg", ".jpeg", ".png", ".gif", ".webp", ".zip", ".tar", ".gz", ".7z", ".mp4", ".webm", ".ogg", ".mp3", ".wav", ".flac", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".odt", ".ods", ".odp"]
|
|
maxfilesize = "100MB"
|
|
chunkeduploadsenabled = true
|
|
chunksize = "10MB"
|
|
ttlenabled = false
|
|
ttl = "168h"
|
|
|
|
[downloads]
|
|
chunkeddownloadsenabled = true
|
|
chunksize = "10MB"
|
|
|
|
[logging]
|
|
level = "INFO"
|
|
file = "$DEFAULT_LOG_DIR/hmac-file-server.log"
|
|
max_size = 100
|
|
max_backups = 3
|
|
max_age = 30
|
|
compress = true
|
|
|
|
[workers]
|
|
numworkers = 10
|
|
uploadqueuesize = 1000
|
|
autoscaling = true
|
|
|
|
[timeouts]
|
|
readtimeout = "30s"
|
|
writetimeout = "30s"
|
|
idletimeout = "120s"
|
|
shutdown = "30s"
|
|
EOF
|
|
|
|
if [[ $ENABLE_CLAMAV == "true" ]]; then
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[clamav]
|
|
enabled = true
|
|
${CLAMAV_CONFIG}
|
|
timeout = "30s"
|
|
EOF
|
|
else
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[clamav]
|
|
enabled = false
|
|
EOF
|
|
fi
|
|
|
|
if [[ $ENABLE_REDIS == "true" ]]; then
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[redis]
|
|
enabled = true
|
|
host = "$REDIS_HOST"
|
|
port = $REDIS_PORT
|
|
database = $REDIS_DB
|
|
password = "$REDIS_PASSWORD"
|
|
timeout = "5s"
|
|
EOF
|
|
else
|
|
cat >> "$DEFAULT_CONFIG_DIR/config.toml" << EOF
|
|
|
|
[redis]
|
|
enabled = false
|
|
EOF
|
|
fi
|
|
|
|
# Set ownership and permissions
|
|
chown "$HMAC_USER:$HMAC_USER" "$DEFAULT_CONFIG_DIR/config.toml"
|
|
chmod 640 "$DEFAULT_CONFIG_DIR/config.toml"
|
|
|
|
echo -e "${GREEN}Configuration file created: $DEFAULT_CONFIG_DIR/config.toml${NC}"
|
|
}
|
|
|
|
# Create systemd service
|
|
create_systemd_service() {
|
|
echo -e "${YELLOW}Creating systemd service...${NC}"
|
|
|
|
cat > /etc/systemd/system/hmac-file-server.service << EOF
|
|
[Unit]
|
|
Description=HMAC File Server 3.2
|
|
Documentation=https://github.com/PlusOne/hmac-file-server
|
|
After=network.target
|
|
Wants=network-online.target
|
|
EOF
|
|
|
|
if [[ $ENABLE_REDIS == "true" ]]; then
|
|
echo "After=redis.service" >> /etc/systemd/system/hmac-file-server.service
|
|
fi
|
|
|
|
if [[ $ENABLE_CLAMAV == "true" ]]; then
|
|
echo "After=clamav-daemon.service" >> /etc/systemd/system/hmac-file-server.service
|
|
fi
|
|
|
|
cat >> /etc/systemd/system/hmac-file-server.service << EOF
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=$HMAC_USER
|
|
Group=$HMAC_USER
|
|
ExecStart=$INSTALL_DIR/hmac-file-server -config $DEFAULT_CONFIG_DIR/config.toml
|
|
ExecReload=/bin/kill -SIGHUP \$MAINPID
|
|
WorkingDirectory=$INSTALL_DIR
|
|
Restart=always
|
|
RestartSec=10
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
SyslogIdentifier=hmac-file-server
|
|
|
|
# Security settings
|
|
NoNewPrivileges=true
|
|
PrivateTmp=true
|
|
ProtectSystem=strict
|
|
ProtectHome=true
|
|
ReadWritePaths=$DATA_DIR $DEFAULT_LOG_DIR
|
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
|
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
|
|
# Resource limits
|
|
LimitNOFILE=65536
|
|
LimitNPROC=4096
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
# Reload systemd and enable service
|
|
systemctl daemon-reload
|
|
systemctl enable hmac-file-server.service
|
|
|
|
echo -e "${GREEN}Systemd service created and enabled${NC}"
|
|
}
|
|
|
|
# Install dependencies
|
|
install_dependencies() {
|
|
echo -e "${YELLOW}Installing dependencies...${NC}"
|
|
|
|
# Detect package manager and install dependencies
|
|
if command -v apt-get &> /dev/null; then
|
|
apt-get update
|
|
if [[ $ENABLE_REDIS == "true" ]]; then
|
|
apt-get install -y redis-server
|
|
systemctl enable redis-server
|
|
fi
|
|
if [[ $ENABLE_CLAMAV == "true" ]]; then
|
|
apt-get install -y clamav clamav-daemon
|
|
systemctl enable clamav-daemon
|
|
# Update virus definitions
|
|
freshclam || true
|
|
|
|
# Detect ClamAV configuration and configure accordingly
|
|
echo -e "${YELLOW}Configuring ClamAV connection...${NC}"
|
|
|
|
# Check if ClamAV daemon is running and detect socket/port
|
|
if systemctl is-active --quiet clamav-daemon; then
|
|
echo " ✓ ClamAV daemon is running"
|
|
|
|
# Check for Unix socket (preferred)
|
|
if [[ -S "/var/run/clamav/clamd.ctl" ]]; then
|
|
echo " ✓ Unix socket detected: /var/run/clamav/clamd.ctl"
|
|
CLAMAV_CONFIG="socket = \"/var/run/clamav/clamd.ctl\""
|
|
elif [[ -S "/run/clamav/clamd.ctl" ]]; then
|
|
echo " ✓ Unix socket detected: /run/clamav/clamd.ctl"
|
|
CLAMAV_CONFIG="socket = \"/run/clamav/clamd.ctl\""
|
|
elif [[ -S "/tmp/clamd" ]]; then
|
|
echo " ✓ Unix socket detected: /tmp/clamd"
|
|
CLAMAV_CONFIG="socket = \"/tmp/clamd\""
|
|
# Check for TCP port
|
|
elif netstat -ln | grep -q ":3310"; then
|
|
echo " ✓ TCP port detected: 127.0.0.1:3310"
|
|
CLAMAV_CONFIG="address = \"127.0.0.1:3310\""
|
|
else
|
|
echo " ⚠ ClamAV socket/port not detected, using default Unix socket"
|
|
CLAMAV_CONFIG="socket = \"/var/run/clamav/clamd.ctl\""
|
|
fi
|
|
else
|
|
echo " ⚠ ClamAV daemon not running, using default configuration"
|
|
CLAMAV_CONFIG="socket = \"/var/run/clamav/clamd.ctl\""
|
|
|
|
# Try to start the daemon
|
|
echo " 🔄 Attempting to start ClamAV daemon..."
|
|
systemctl start clamav-daemon || echo " ⚠ Failed to start ClamAV daemon"
|
|
fi
|
|
fi
|
|
elif command -v yum &> /dev/null; then
|
|
if [[ $ENABLE_REDIS == "true" ]]; then
|
|
yum install -y redis
|
|
systemctl enable redis
|
|
fi
|
|
if [[ $ENABLE_CLAMAV == "true" ]]; then
|
|
yum install -y clamav clamav-update clamd
|
|
systemctl enable clamd
|
|
freshclam || true
|
|
fi
|
|
elif command -v dnf &> /dev/null; then
|
|
if [[ $ENABLE_REDIS == "true" ]]; then
|
|
dnf install -y redis
|
|
systemctl enable redis
|
|
fi
|
|
if [[ $ENABLE_CLAMAV == "true" ]]; then
|
|
dnf install -y clamav clamav-update clamd
|
|
systemctl enable clamd
|
|
freshclam || true
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}Unknown package manager. Please install Redis and/or ClamAV manually if needed.${NC}"
|
|
fi
|
|
}
|
|
|
|
# Generate secure random key
|
|
generate_random_key() {
|
|
local length=${1:-48} # Default 48 characters for extra security
|
|
local key=""
|
|
|
|
# Try different methods in order of preference
|
|
if command -v openssl &> /dev/null; then
|
|
# Method 1: OpenSSL (most common and secure)
|
|
key=$(openssl rand -base64 $((length * 3 / 4 + 1)) | tr -d "=+/\n" | cut -c1-$length)
|
|
elif command -v head &> /dev/null && [[ -r /dev/urandom ]]; then
|
|
# Method 2: /dev/urandom with head (Linux/Unix)
|
|
key=$(head -c $((length * 3 / 4 + 1)) /dev/urandom | base64 | tr -d "=+/\n" | cut -c1-$length)
|
|
elif command -v dd &> /dev/null && [[ -r /dev/urandom ]]; then
|
|
# Method 3: dd with /dev/urandom
|
|
key=$(dd if=/dev/urandom bs=$((length * 3 / 4 + 1)) count=1 2>/dev/null | base64 | tr -d "=+/\n" | cut -c1-$length)
|
|
elif command -v date &> /dev/null; then
|
|
# Method 4: Fallback using date and process info (less secure but works)
|
|
local timestamp=$(date +%s%N)
|
|
local random_data="${timestamp}${RANDOM}${$}$(hostname)"
|
|
key=$(echo -n "$random_data" | sha256sum | cut -c1-$length)
|
|
else
|
|
# Method 5: Last resort - basic fallback
|
|
echo -e "${YELLOW}Warning: Using basic key generation (consider installing openssl)${NC}" >&2
|
|
key="hmac-file-server-$(date +%s)-$(hostname | cut -c1-16)"
|
|
key=$(echo -n "$key" | sha256sum | cut -c1-$length)
|
|
fi
|
|
|
|
# Ensure exact length
|
|
key=$(echo -n "$key" | cut -c1-$length)
|
|
|
|
# If still too short, pad with additional random data
|
|
while [[ ${#key} -lt $length ]]; do
|
|
local padding=$(date +%s | sha256sum | cut -c1-$((length - ${#key})))
|
|
key="${key}${padding}"
|
|
key=$(echo -n "$key" | cut -c1-$length)
|
|
done
|
|
|
|
echo "$key"
|
|
}
|
|
|
|
# Main installation function
|
|
main() {
|
|
echo -e "${BLUE}Starting HMAC File Server installation...${NC}"
|
|
echo ""
|
|
|
|
# Run pre-installation checks
|
|
pre_installation_checks
|
|
|
|
# Get user input
|
|
get_user_input
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Installation Summary:${NC}"
|
|
echo "User: $HMAC_USER"
|
|
echo "Install Directory: $INSTALL_DIR"
|
|
echo "Data Directory: $DATA_DIR"
|
|
echo "Config Directory: $DEFAULT_CONFIG_DIR"
|
|
echo "Server Port: $SERVER_PORT"
|
|
echo "Metrics Port: $METRICS_PORT"
|
|
echo "JWT Enabled: $ENABLE_JWT"
|
|
echo "Redis Enabled: $ENABLE_REDIS"
|
|
echo "ClamAV Enabled: $ENABLE_CLAMAV"
|
|
echo "TLS Enabled: $ENABLE_TLS"
|
|
echo ""
|
|
|
|
read -p "Continue with installation? (y/N): " CONFIRM
|
|
if [[ ! $CONFIRM =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}Installation cancelled.${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Installing...${NC}"
|
|
|
|
# Installation steps
|
|
check_go
|
|
create_user
|
|
create_directories
|
|
install_dependencies
|
|
build_server
|
|
generate_config
|
|
create_systemd_service
|
|
|
|
# Ask if user wants to start the service now
|
|
echo ""
|
|
read -p "Start HMAC File Server service now? (Y/n): " START_SERVICE
|
|
START_SERVICE=${START_SERVICE:-Y}
|
|
|
|
if [[ $START_SERVICE =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}Starting HMAC File Server service...${NC}"
|
|
systemctl start hmac-file-server.service
|
|
|
|
# Wait a moment and check status
|
|
sleep 3
|
|
if systemctl is-active --quiet hmac-file-server.service; then
|
|
echo -e "${GREEN}✅ Service started successfully${NC}"
|
|
else
|
|
echo -e "${RED}❌ Service failed to start. Check logs with: journalctl -u hmac-file-server.service${NC}"
|
|
fi
|
|
fi
|
|
|
|
print_completion_info
|
|
}
|
|
|
|
# Function to print completion information
|
|
print_completion_info() {
|
|
echo ""
|
|
echo -e "${GREEN} █ Installation Complete! █${NC}"
|
|
echo -e "${GREEN}────────────────────────────────────────────────────────────────${NC}"
|
|
echo -e "${GREEN} HMAC File Server 3.2 Successfully Deployed! ${NC}"
|
|
echo -e "${GREEN}────────────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}🚀 Service Information:${NC}"
|
|
echo -e " Status: ${YELLOW}sudo systemctl status hmac-file-server${NC}"
|
|
echo -e " Logs: ${YELLOW}sudo journalctl -u hmac-file-server -f${NC}"
|
|
echo -e " Config: ${YELLOW}sudo nano $DEFAULT_CONFIG_DIR/config.toml${NC}"
|
|
echo -e " Reload: ${YELLOW}sudo systemctl reload hmac-file-server${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}🌐 Service Endpoints:${NC}"
|
|
if [[ $ENABLE_TLS == "true" ]]; then
|
|
echo -e " Server: ${YELLOW}https://$(hostname -I | awk '{print $1}'):$SERVER_PORT${NC}"
|
|
else
|
|
echo -e " Server: ${YELLOW}http://$(hostname -I | awk '{print $1}'):$SERVER_PORT${NC}"
|
|
fi
|
|
echo -e " Metrics: ${YELLOW}http://$(hostname -I | awk '{print $1}'):$METRICS_PORT/metrics${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}📁 File Locations:${NC}"
|
|
echo -e " Binary: ${YELLOW}$INSTALL_DIR/hmac-file-server${NC}"
|
|
echo -e " Config: ${YELLOW}$DEFAULT_CONFIG_DIR/config.toml${NC}"
|
|
echo -e " Uploads: ${YELLOW}$DATA_DIR/uploads${NC}"
|
|
echo -e " Logs: ${YELLOW}$DEFAULT_LOG_DIR/hmac-file-server.log${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}⚡ Quick Commands:${NC}"
|
|
echo -e " Start: ${YELLOW}sudo systemctl start hmac-file-server${NC}"
|
|
echo -e " Stop: ${YELLOW}sudo systemctl stop hmac-file-server${NC}"
|
|
echo -e " Restart: ${YELLOW}sudo systemctl restart hmac-file-server${NC}"
|
|
echo -e " Status: ${YELLOW}sudo systemctl status hmac-file-server${NC}"
|
|
echo ""
|
|
echo -e "${BLUE}🔧 Next Steps for XMPP Integration:${NC}"
|
|
echo -e "1. ${YELLOW}Configure firewall${NC} to allow ports $SERVER_PORT (server) and $METRICS_PORT (metrics)"
|
|
echo -e "2. Configure your reverse proxy (nginx/apache) with SSL"
|
|
echo -e "3. Update your Prosody/Ejabberd configuration:"
|
|
echo -e " ${YELLOW}http_file_share = \"http://localhost:$SERVER_PORT\"${NC}"
|
|
echo -e "4. Set up monitoring and log rotation"
|
|
echo -e "5. Test file uploads with your XMPP client"
|
|
echo ""
|
|
echo -e "${BLUE}📚 Documentation & Support:${NC}"
|
|
echo -e " README: https://github.com/PlusOne/hmac-file-server/blob/main/README.MD"
|
|
echo -e " Wiki: https://github.com/PlusOne/hmac-file-server/blob/main/WIKI.MD"
|
|
echo -e " Issues: https://github.com/PlusOne/hmac-file-server/issues"
|
|
echo ""
|
|
echo -e "${GREEN}────────────────────────────────────────────────────────────────${NC}"
|
|
echo -e "${GREEN} Thank you for choosing HMAC File Server for your XMPP setup! ${NC}"
|
|
echo -e "${GREEN}────────────────────────────────────────────────────────────────${NC}"
|
|
}
|
|
|
|
# Helper function to safely preserve a directory
|
|
preserve_directory() {
|
|
local source_dir="$1"
|
|
local backup_path="$2"
|
|
|
|
if [[ -d "$source_dir" ]]; then
|
|
local parent_dir=$(dirname "$backup_path")
|
|
mkdir -p "$parent_dir"
|
|
|
|
if mv "$source_dir" "$backup_path" 2>/dev/null; then
|
|
echo " ✓ Preserved: $source_dir → $backup_path"
|
|
else
|
|
# Fallback to copy if move fails
|
|
if cp -r "$source_dir" "$backup_path" 2>/dev/null; then
|
|
echo " ✓ Copied: $source_dir → $backup_path"
|
|
rm -rf "$source_dir"
|
|
echo " ✓ Removed original: $source_dir"
|
|
else
|
|
echo " ⚠ Failed to preserve: $source_dir"
|
|
fi
|
|
fi
|
|
else
|
|
echo " ⚠ Directory not found: $source_dir"
|
|
fi
|
|
}
|
|
|
|
# Custom data selection for option 4
|
|
custom_data_selection() {
|
|
echo ""
|
|
echo -e "${BLUE}Custom Data Selection:${NC}"
|
|
echo "Choose which data directories to preserve:"
|
|
echo ""
|
|
|
|
CUSTOM_PRESERVE_UPLOADS=""
|
|
CUSTOM_PRESERVE_DEDUP=""
|
|
CUSTOM_PRESERVE_LOGS=""
|
|
|
|
# Ask about uploads
|
|
if [[ -d "$UPLOAD_DIR" ]]; then
|
|
FILE_COUNT=$(find "$UPLOAD_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$UPLOAD_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN}📤 Upload Directory: ${UPLOAD_DIR}${NC} (Files: $FILE_COUNT, Size: $DIR_SIZE)"
|
|
read -p "Preserve upload directory? (y/N): " PRESERVE_UPLOADS
|
|
if [[ $PRESERVE_UPLOADS =~ ^[Yy]$ ]]; then
|
|
CUSTOM_PRESERVE_UPLOADS="yes"
|
|
echo " ✓ Will preserve uploads"
|
|
else
|
|
echo " ✗ Will delete uploads"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}📤 Upload Directory: Not found${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Ask about deduplication
|
|
if [[ -d "$DEDUP_DIR" ]]; then
|
|
FILE_COUNT=$(find "$DEDUP_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$DEDUP_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN}🔗 Deduplication Directory: ${DEDUP_DIR}${NC} (Files: $FILE_COUNT, Size: $DIR_SIZE)"
|
|
read -p "Preserve deduplication directory? (y/N): " PRESERVE_DEDUP
|
|
if [[ $PRESERVE_DEDUP =~ ^[Yy]$ ]]; then
|
|
CUSTOM_PRESERVE_DEDUP="yes"
|
|
echo " ✓ Will preserve deduplication data"
|
|
else
|
|
echo " ✗ Will delete deduplication data"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}🔗 Deduplication Directory: Not found${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Ask about logs
|
|
if [[ -d "$LOG_DIR" ]]; then
|
|
FILE_COUNT=$(find "$LOG_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$LOG_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN}📄 Log Directory: ${LOG_DIR}${NC} (Files: $FILE_COUNT, Size: $DIR_SIZE)"
|
|
read -p "Preserve log directory? (y/N): " PRESERVE_LOGS
|
|
if [[ $PRESERVE_LOGS =~ ^[Yy]$ ]]; then
|
|
CUSTOM_PRESERVE_LOGS="yes"
|
|
echo " ✓ Will preserve logs"
|
|
else
|
|
echo " ✗ Will delete logs"
|
|
fi
|
|
else
|
|
echo -e "${YELLOW}📄 Log Directory: Not found${NC}"
|
|
fi
|
|
|
|
# Store custom selection for later processing
|
|
PRESERVE_DATA="custom"
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Custom selection complete:${NC}"
|
|
[[ "$CUSTOM_PRESERVE_UPLOADS" == "yes" ]] && echo " 📤 Uploads: Preserve" || echo " 📤 Uploads: Delete"
|
|
[[ "$CUSTOM_PRESERVE_DEDUP" == "yes" ]] && echo " 🔗 Deduplication: Preserve" || echo " 🔗 Deduplication: Delete"
|
|
[[ "$CUSTOM_PRESERVE_LOGS" == "yes" ]] && echo " 📄 Logs: Preserve" || echo " 📄 Logs: Delete"
|
|
echo ""
|
|
}
|
|
|
|
# Handle custom preservation choices
|
|
handle_custom_preservation() {
|
|
# Check if any data needs to be preserved
|
|
if [[ "$CUSTOM_PRESERVE_UPLOADS" == "yes" || "$CUSTOM_PRESERVE_DEDUP" == "yes" || "$CUSTOM_PRESERVE_LOGS" == "yes" ]]; then
|
|
BACKUP_DIR="/var/backups/hmac-file-server-$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
echo " ✓ Created backup directory: $BACKUP_DIR"
|
|
fi
|
|
|
|
# Handle uploads
|
|
if [[ "$CUSTOM_PRESERVE_UPLOADS" == "yes" ]]; then
|
|
preserve_directory "$UPLOAD_DIR" "$BACKUP_DIR/uploads"
|
|
elif [[ -d "$UPLOAD_DIR" ]]; then
|
|
rm -rf "$UPLOAD_DIR"
|
|
echo " ✓ Removed uploads: $UPLOAD_DIR"
|
|
fi
|
|
|
|
# Handle deduplication
|
|
if [[ "$CUSTOM_PRESERVE_DEDUP" == "yes" ]]; then
|
|
preserve_directory "$DEDUP_DIR" "$BACKUP_DIR/deduplication"
|
|
elif [[ -d "$DEDUP_DIR" ]]; then
|
|
rm -rf "$DEDUP_DIR"
|
|
echo " ✓ Removed deduplication: $DEDUP_DIR"
|
|
fi
|
|
|
|
# Handle logs
|
|
if [[ "$CUSTOM_PRESERVE_LOGS" == "yes" ]]; then
|
|
preserve_directory "$LOG_DIR" "$BACKUP_DIR/logs"
|
|
elif [[ -d "$LOG_DIR" ]]; then
|
|
rm -rf "$LOG_DIR"
|
|
echo " ✓ Removed logs: $LOG_DIR"
|
|
fi
|
|
|
|
# Remove the main data directory if it's separate and empty
|
|
if [[ -d "$DEFAULT_DATA_DIR" ]]; then
|
|
# Only remove if it's different from preserved directories and if it's empty or only contains subdirs we've handled
|
|
if [[ "$DEFAULT_DATA_DIR" != "$UPLOAD_DIR" && "$DEFAULT_DATA_DIR" != "$DEDUP_DIR" && "$DEFAULT_DATA_DIR" != "$LOG_DIR" ]]; then
|
|
# Check if directory is effectively empty (only contains directories we've already handled)
|
|
remaining_files=$(find "$DEFAULT_DATA_DIR" -type f 2>/dev/null | wc -l)
|
|
if [[ $remaining_files -eq 0 ]]; then
|
|
rm -rf "$DEFAULT_DATA_DIR"
|
|
echo " ✓ Removed empty data directory: $DEFAULT_DATA_DIR"
|
|
else
|
|
echo " ⚠ Data directory contains additional files: $DEFAULT_DATA_DIR"
|
|
fi
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Uninstaller function (can be called with ./installer.sh --uninstall)
|
|
uninstall() {
|
|
echo ""
|
|
echo -e "${RED} █ HMAC File Server Uninstaller █${NC}"
|
|
echo -e "${RED}────────────────────────────────────────────────────────────────${NC}"
|
|
echo -e "${RED} Warning: This will remove the server installation! ${NC}"
|
|
echo -e "${RED}────────────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
|
|
read -p "Are you sure you want to uninstall HMAC File Server? (y/N): " CONFIRM_UNINSTALL
|
|
if [[ ! $CONFIRM_UNINSTALL =~ ^[Yy]$ ]]; then
|
|
echo -e "${YELLOW}Uninstall cancelled${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}📁 Data Preservation Options:${NC}"
|
|
echo -e "${BLUE}────────────────────────────────────────────────────────────────${NC}"
|
|
echo ""
|
|
echo "The following data directories may contain important files:"
|
|
|
|
# Check what data directories exist and show their contents
|
|
PRESERVE_DATA=""
|
|
UPLOAD_DIR=""
|
|
DEDUP_DIR=""
|
|
LOG_DIR=""
|
|
|
|
# Find upload directory from config if it exists
|
|
if [[ -f "$DEFAULT_CONFIG_DIR/config.toml" ]]; then
|
|
UPLOAD_DIR=$(grep -E "^storagepath\s*=" "$DEFAULT_CONFIG_DIR/config.toml" 2>/dev/null | sed 's/.*=\s*"*\([^"]*\)"*.*/\1/' | xargs)
|
|
DEDUP_DIR=$(grep -E "^directory\s*=" "$DEFAULT_CONFIG_DIR/config.toml" 2>/dev/null | sed 's/.*=\s*"*\([^"]*\)"*.*/\1/' | xargs)
|
|
fi
|
|
|
|
# Fallback to default locations
|
|
[[ -z "$UPLOAD_DIR" ]] && UPLOAD_DIR="$DEFAULT_DATA_DIR/uploads"
|
|
[[ -z "$DEDUP_DIR" ]] && DEDUP_DIR="$DEFAULT_DATA_DIR/deduplication"
|
|
LOG_DIR="$DEFAULT_LOG_DIR"
|
|
|
|
# Show upload directory status
|
|
if [[ -d "$UPLOAD_DIR" ]]; then
|
|
FILE_COUNT=$(find "$UPLOAD_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$UPLOAD_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN} 📤 Upload Directory: ${UPLOAD_DIR}${NC}"
|
|
echo -e " Files: $FILE_COUNT, Size: $DIR_SIZE"
|
|
else
|
|
echo -e "${YELLOW} 📤 Upload Directory: Not found or empty${NC}"
|
|
fi
|
|
|
|
# Show deduplication directory status
|
|
if [[ -d "$DEDUP_DIR" ]]; then
|
|
FILE_COUNT=$(find "$DEDUP_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$DEDUP_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN} 🔗 Deduplication Directory: ${DEDUP_DIR}${NC}"
|
|
echo -e " Files: $FILE_COUNT, Size: $DIR_SIZE"
|
|
else
|
|
echo -e "${YELLOW} 🔗 Deduplication Directory: Not found or empty${NC}"
|
|
fi
|
|
|
|
# Show log directory status
|
|
if [[ -d "$LOG_DIR" ]]; then
|
|
FILE_COUNT=$(find "$LOG_DIR" -type f 2>/dev/null | wc -l)
|
|
DIR_SIZE=$(du -sh "$LOG_DIR" 2>/dev/null | cut -f1)
|
|
echo -e "${GREEN} 📄 Log Directory: ${LOG_DIR}${NC}"
|
|
echo -e " Files: $FILE_COUNT, Size: $DIR_SIZE"
|
|
else
|
|
echo -e "${YELLOW} 📄 Log Directory: Not found or empty${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${BLUE}Choose data handling option:${NC}"
|
|
echo " 1) 🗑️ Delete all data (complete removal)"
|
|
echo " 2) 💾 Preserve upload and deduplication data only"
|
|
echo " 3) 📋 Preserve all data (uploads, deduplication, and logs)"
|
|
echo " 4) 🎯 Custom selection (choose what to preserve)"
|
|
echo " 5) ❌ Cancel uninstallation"
|
|
echo ""
|
|
|
|
while true; do
|
|
read -p "Select option (1-5): " DATA_OPTION
|
|
case $DATA_OPTION in
|
|
1)
|
|
echo -e "${RED}Selected: Delete all data${NC}"
|
|
PRESERVE_DATA="none"
|
|
break
|
|
;;
|
|
2)
|
|
echo -e "${GREEN}Selected: Preserve uploads and deduplication data${NC}"
|
|
PRESERVE_DATA="uploads_dedup"
|
|
break
|
|
;;
|
|
3)
|
|
echo -e "${GREEN}Selected: Preserve all data${NC}"
|
|
PRESERVE_DATA="all"
|
|
break
|
|
;;
|
|
4)
|
|
echo -e "${BLUE}Custom selection:${NC}"
|
|
custom_data_selection
|
|
break
|
|
;;
|
|
5)
|
|
echo -e "${YELLOW}Uninstall cancelled${NC}"
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo -e "${RED}Invalid option. Please choose 1-5.${NC}"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Final confirmation for complete deletion
|
|
if [[ "$PRESERVE_DATA" == "none" ]]; then
|
|
echo ""
|
|
echo -e "${RED}⚠️ FINAL WARNING: This will permanently delete ALL data!${NC}"
|
|
echo -e "${RED} This includes all uploaded files, deduplication data, and logs.${NC}"
|
|
echo -e "${RED} This action cannot be undone!${NC}"
|
|
echo ""
|
|
read -p "Type 'DELETE' to confirm complete data removal: " FINAL_CONFIRM
|
|
if [[ "$FINAL_CONFIRM" != "DELETE" ]]; then
|
|
echo -e "${YELLOW}Uninstall cancelled - confirmation failed${NC}"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${YELLOW}🔄 Starting uninstallation process...${NC}"
|
|
echo ""
|
|
|
|
echo -e "${YELLOW}Stopping and disabling service...${NC}"
|
|
if systemctl is-active --quiet hmac-file-server.service; then
|
|
systemctl stop hmac-file-server.service || true
|
|
echo " ✓ Service stopped"
|
|
else
|
|
echo " ⚠ Service was not running"
|
|
fi
|
|
|
|
if systemctl is-enabled --quiet hmac-file-server.service 2>/dev/null; then
|
|
systemctl disable hmac-file-server.service || true
|
|
echo " ✓ Service disabled"
|
|
else
|
|
echo " ⚠ Service was not enabled"
|
|
fi
|
|
|
|
if [[ -f /etc/systemd/system/hmac-file-server.service ]]; then
|
|
rm -f /etc/systemd/system/hmac-file-server.service
|
|
echo " ✓ Service file removed"
|
|
else
|
|
echo " ⚠ Service file not found"
|
|
fi
|
|
|
|
systemctl daemon-reload
|
|
echo " ✓ Systemd reloaded"
|
|
|
|
echo -e "${YELLOW}Removing installation and configuration...${NC}"
|
|
|
|
# Always remove installation directory
|
|
if [[ -d "$DEFAULT_INSTALL_DIR" ]]; then
|
|
rm -rf "$DEFAULT_INSTALL_DIR"
|
|
echo " ✓ Removed installation directory: $DEFAULT_INSTALL_DIR"
|
|
else
|
|
echo " ⚠ Installation directory not found: $DEFAULT_INSTALL_DIR"
|
|
fi
|
|
|
|
# Always remove configuration directory
|
|
if [[ -d "$DEFAULT_CONFIG_DIR" ]]; then
|
|
rm -rf "$DEFAULT_CONFIG_DIR"
|
|
echo " ✓ Removed configuration directory: $DEFAULT_CONFIG_DIR"
|
|
else
|
|
echo " ⚠ Configuration directory not found: $DEFAULT_CONFIG_DIR"
|
|
fi
|
|
|
|
# Handle data directories based on user choice
|
|
echo -e "${YELLOW}Processing data directories...${NC}"
|
|
|
|
case $PRESERVE_DATA in
|
|
"none")
|
|
# Delete everything
|
|
for dir in "$UPLOAD_DIR" "$DEDUP_DIR" "$LOG_DIR" "$DEFAULT_DATA_DIR"; do
|
|
if [[ -d "$dir" ]]; then
|
|
rm -rf "$dir"
|
|
echo " ✓ Removed: $dir"
|
|
fi
|
|
done
|
|
;;
|
|
"uploads_dedup")
|
|
# Preserve uploads and deduplication, remove logs
|
|
if [[ -d "$LOG_DIR" ]]; then
|
|
rm -rf "$LOG_DIR"
|
|
echo " ✓ Removed logs: $LOG_DIR"
|
|
fi
|
|
# Move preserved data to a safe location
|
|
BACKUP_DIR="/var/backups/hmac-file-server-$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
preserve_directory "$UPLOAD_DIR" "$BACKUP_DIR/uploads"
|
|
preserve_directory "$DEDUP_DIR" "$BACKUP_DIR/deduplication"
|
|
# Remove original data directory structure but keep preserved data
|
|
if [[ -d "$DEFAULT_DATA_DIR" && "$DEFAULT_DATA_DIR" != "$UPLOAD_DIR" && "$DEFAULT_DATA_DIR" != "$DEDUP_DIR" ]]; then
|
|
rm -rf "$DEFAULT_DATA_DIR"
|
|
echo " ✓ Removed data directory (preserved content moved to $BACKUP_DIR)"
|
|
fi
|
|
;;
|
|
"all")
|
|
# Preserve everything
|
|
BACKUP_DIR="/var/backups/hmac-file-server-$(date +%Y%m%d-%H%M%S)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
preserve_directory "$UPLOAD_DIR" "$BACKUP_DIR/uploads"
|
|
preserve_directory "$DEDUP_DIR" "$BACKUP_DIR/deduplication"
|
|
preserve_directory "$LOG_DIR" "$BACKUP_DIR/logs"
|
|
# Remove original data directory structure but keep preserved data
|
|
if [[ -d "$DEFAULT_DATA_DIR" ]]; then
|
|
rm -rf "$DEFAULT_DATA_DIR"
|
|
echo " ✓ Removed data directory (all content preserved in $BACKUP_DIR)"
|
|
fi
|
|
;;
|
|
"custom")
|
|
# Handle custom selection
|
|
handle_custom_preservation
|
|
;;
|
|
esac
|
|
|
|
echo -e "${YELLOW}Removing system user...${NC}"
|
|
if id "$DEFAULT_USER" &>/dev/null; then
|
|
userdel "$DEFAULT_USER" || true
|
|
echo " ✓ User $DEFAULT_USER removed"
|
|
else
|
|
echo " ⚠ User $DEFAULT_USER not found"
|
|
fi
|
|
|
|
# Remove any remaining binary in common locations
|
|
echo -e "${YELLOW}Cleaning up any remaining files...${NC}"
|
|
for location in "/usr/local/bin/hmac-file-server" "/usr/bin/hmac-file-server"; do
|
|
if [[ -f "$location" ]]; then
|
|
rm -f "$location"
|
|
echo " ✓ Removed $location"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
if [[ "$PRESERVE_DATA" != "none" ]]; then
|
|
echo -e "${GREEN}✅ HMAC File Server uninstalled successfully with data preservation${NC}"
|
|
if [[ -d "$BACKUP_DIR" ]]; then
|
|
echo -e "${BLUE}📁 Preserved data location: $BACKUP_DIR${NC}"
|
|
echo -e "${BLUE} You can safely delete this directory if you no longer need the data.${NC}"
|
|
fi
|
|
else
|
|
echo -e "${GREEN}✅ HMAC File Server uninstalled completely${NC}"
|
|
echo -e "${BLUE}All files, services, and user accounts have been removed.${NC}"
|
|
fi
|
|
echo ""
|
|
}
|
|
|
|
# Check for help flag
|
|
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
show_help
|
|
exit 0
|
|
fi
|
|
|
|
# Check for uninstall flag
|
|
if [[ "$1" == "--uninstall" ]]; then
|
|
uninstall
|
|
exit 0
|
|
fi
|
|
|
|
# Run main function
|
|
main "$@"
|