feat: Major v2.0.0 rewrite - Enterprise-grade NAS setup script

🚀 BREAKING CHANGE: Complete rewrite to enterprise-grade standards

###  New Features:
- Enhanced input validation (IP, port, username, path)
- Automatic rollback mechanism on failures
- Comprehensive unit testing framework (50+ tests)
- Advanced logging with timestamps and levels
- Interactive configuration system with persistence
- Performance optimization suite (kernel, Docker, Samba)
- Advanced firewall configuration with monitoring
- System health monitoring and maintenance tools
- Multi-distribution support with version validation

### 🛡️ Security Enhancements:
- SSH hardening with security policies
- Rate limiting for critical services
- IP blocking/unblocking tools
- Intrusion detection capabilities
- Firewall monitoring with alerts
- Secure input sanitization

### 🔧 Architecture Improvements:
- Modular library structure
- Centralized configuration management
- Common functions separation
- Professional error handling with set -euo pipefail
- Signal handling for graceful shutdowns
- Resource cleanup mechanisms

### 📚 Documentation:
- Professional README with comprehensive guides
- Enhanced CONTRIBUTING.md with development standards
- Complete CHANGELOG.md with version history
- Troubleshooting guides and best practices

### 🧪 Testing & Quality:
- Unit tests for all critical functions
- Performance regression testing
- Multi-distribution integration testing
- Input validation testing
- Error scenario testing

This release transforms the script from a basic tool to a production-ready,
enterprise-grade NAS setup solution suitable for professional environments.
This commit is contained in:
Sebastian Palencsár
2025-06-17 10:57:46 +02:00
parent cf27011875
commit cb91166616
11 changed files with 3486 additions and 444 deletions

484
setup.sh
View File

@@ -1,14 +1,14 @@
#!/bin/bash
# NAS Setup Script - Version 1.0
# NAS Setup Script - Version 2.0.0
#
# This script automates the setup of a NAS system with various services.
# It is designed to run on multiple Linux distributions, including:
# - Ubuntu
# - Debian
# - Fedora
# - Ubuntu 20.04+
# - Debian 11+
# - Fedora 35+
# - Arch Linux
# - openSUSE
# - openSUSE Leap 15.4+
#
# Disclaimer:
# This script is provided "as is", without warranty of any kind, express or implied,
@@ -25,116 +25,392 @@
# License: MIT License
# (c) 2025 Sebastian Palencsár
# Import configuration and functions
source "$(dirname "$0")/config/defaults.sh"
source "$(dirname "$0")/lib/logging.sh"
source "$(dirname "$0")/lib/network.sh"
source "$(dirname "$0")/lib/docker.sh"
source "$(dirname "$0")/lib/security.sh"
source "$(dirname "$0")/lib/internet.sh"
source "$(dirname "$0")/lib/nfs.sh"
source "$(dirname "$0")/lib/netdata.sh"
source "$(dirname "$0")/lib/firewall.sh"
source "$(dirname "$0")/lib/unattended-upgrades.sh"
source "$(dirname "$0")/lib/vaultwarden.sh"
source "$(dirname "$0")/lib/jellyfin.sh"
source "$(dirname "$0")/lib/portainer.sh"
set -euo pipefail # Strict error handling
# Logging configuration
# Script directory and imports
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Import configuration and functions
source "${SCRIPT_DIR}/config/defaults.sh"
source "${SCRIPT_DIR}/lib/logging.sh"
source "${SCRIPT_DIR}/lib/common.sh"
source "${SCRIPT_DIR}/lib/network.sh"
source "${SCRIPT_DIR}/lib/docker.sh"
source "${SCRIPT_DIR}/lib/security.sh"
source "${SCRIPT_DIR}/lib/internet.sh"
source "${SCRIPT_DIR}/lib/nfs.sh"
source "${SCRIPT_DIR}/lib/netdata.sh"
source "${SCRIPT_DIR}/lib/firewall.sh"
source "${SCRIPT_DIR}/lib/unattended-upgrades.sh"
source "${SCRIPT_DIR}/lib/vaultwarden.sh"
source "${SCRIPT_DIR}/lib/jellyfin.sh"
source "${SCRIPT_DIR}/lib/portainer.sh"
source "${SCRIPT_DIR}/lib/performance.sh"
# Initialize logging
mkdir -p "$(dirname "${LOG_FILE}")"
mkdir -p "${TEMP_DIR}"
# Setup logging with rotation
exec > >(tee -a "${LOG_FILE}") 2>&1
# Improved error handling
# Enhanced error handling with rollback
handle_error() {
"$@"
local status=$?
if [ $status -ne 0 ]; then
log_error "Error executing $* (exit code: $status)"
local exit_code=$?
local line_number=$1
local command="$2"
log_error "Script failed at line ${line_number}: ${command} (exit code: ${exit_code})"
if ask_yes_no "An error occurred. Would you like to rollback changes?" "y"; then
execute_rollback
fi
cleanup
exit $exit_code
}
# Set error trap
trap 'handle_error ${LINENO} "$BASH_COMMAND"' ERR
# Signal handlers
cleanup_on_exit() {
log_info "Script interrupted. Performing cleanup..."
cleanup
exit 130
}
trap cleanup_on_exit SIGINT SIGTERM
# Detect Linux distribution with version check
detect_distro() {
if [[ -f /etc/os-release ]]; then
source /etc/os-release
DISTRO=$ID
DISTRO_VERSION=$VERSION_ID
DISTRO_CODENAME=${VERSION_CODENAME:-""}
log_info "Detected distribution: $PRETTY_NAME"
# Validate supported distribution
if [[ ! " ${SUPPORTED_DISTROS[*]} " =~ " ${DISTRO} " ]]; then
log_error "Unsupported Linux distribution: $DISTRO"
log_info "Supported distributions: ${SUPPORTED_DISTROS[*]}"
exit 1
fi
# Check minimum versions
case $DISTRO in
ubuntu)
if [[ $(echo "$DISTRO_VERSION >= 20.04" | bc -l) -eq 0 ]]; then
log_warning "Ubuntu version $DISTRO_VERSION is not officially supported. Minimum: 20.04"
fi
;;
debian)
if [[ ${DISTRO_VERSION%%.*} -lt 11 ]]; then
log_warning "Debian version $DISTRO_VERSION is not officially supported. Minimum: 11"
fi
;;
esac
else
log_error "Cannot detect Linux distribution. /etc/os-release not found."
exit 1
fi
}
# Detect Linux distribution
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO=$ID
else
log_error "Unsupported Linux distribution."
# System requirements check
check_system_requirements() {
log_info "Checking system requirements..."
local requirements_met=true
# Check disk space
if ! check_disk_space $MIN_DISK_SPACE_GB; then
requirements_met=false
fi
# Check RAM
check_ram $MIN_RAM_MB
# Check if running as root
check_root
# Check internet connectivity
if ! check_internet_enhanced; then
requirements_met=false
fi
# Check architecture
local arch=$(uname -m)
case $arch in
x86_64|amd64)
log_info "Architecture check passed: $arch"
;;
aarch64|arm64)
log_warning "ARM64 architecture detected. Some packages may not be available."
;;
*)
log_error "Unsupported architecture: $arch"
requirements_met=false
;;
esac
if [[ "$requirements_met" == false ]]; then
log_error "System requirements not met. Exiting."
exit 1
fi
log_success "All system requirements met"
}
# Configuration management
load_or_create_config() {
log_info "Loading configuration..."
if load_config; then
log_info "Configuration loaded from ${CONFIG_FILE}"
if ! validate_config; then
log_error "Configuration validation failed"
exit 1
fi
else
log_info "Creating new configuration..."
create_interactive_config
fi
}
create_interactive_config() {
log_info "Interactive configuration setup"
echo
# SSH configuration
local ssh_port=$(ask_input "SSH port" "$DEFAULT_SSH_PORT" "validate_port")
save_config "SSH_PORT" "$ssh_port"
# User configuration
local username=$(ask_input "Admin username" "$NEW_USER" "validate_username")
save_config "ADMIN_USER" "$username"
# Network configuration
if ask_yes_no "Configure static IP?" "n"; then
save_config "CONFIGURE_STATIC_IP" "true"
else
save_config "CONFIGURE_STATIC_IP" "false"
fi
# Service selection
save_config "INSTALL_DOCKER" "$(ask_yes_no "Install Docker?" "y" && echo "true" || echo "false")"
save_config "INSTALL_NFS" "$(ask_yes_no "Install NFS?" "n" && echo "true" || echo "false")"
save_config "INSTALL_NETDATA" "$(ask_yes_no "Install Netdata monitoring?" "y" && echo "true" || echo "false")"
save_config "INSTALL_VAULTWARDEN" "$(ask_yes_no "Install Vaultwarden password manager?" "n" && echo "true" || echo "false")"
save_config "INSTALL_JELLYFIN" "$(ask_yes_no "Install Jellyfin media server?" "n" && echo "true" || echo "false")"
save_config "INSTALL_PORTAINER" "$(ask_yes_no "Install Portainer Docker management?" "n" && echo "true" || echo "false")"
log_success "Configuration created and saved to ${CONFIG_FILE}"
}
# System update with progress
update_system() {
log_info "Updating system packages..."
show_progress 1 10 "System Update"
case $DISTRO in
ubuntu|debian)
sudo apt-get update -qq
show_progress 5 10 "System Update"
sudo apt-get upgrade -y -qq
;;
fedora)
sudo dnf update -y -q
;;
arch)
sudo pacman -Syu --noconfirm --quiet
;;
opensuse)
sudo zypper refresh -q
sudo zypper update -y -q
;;
esac
show_progress 10 10 "System Update"
add_rollback_action "# System packages updated - no rollback needed"
}
# Main installation orchestrator
run_installation() {
local total_steps=12
local current_step=0
log_info "Starting NAS installation process..."
# Core system setup
((current_step++)); show_progress $current_step $total_steps "Installing dependencies"
install_dependencies
((current_step++)); show_progress $current_step $total_steps "Configuring network"
if [[ "${CONFIGURE_STATIC_IP:-false}" == "true" ]]; then
configure_network
fi
((current_step++)); show_progress $current_step $total_steps "Configuring SSH"
configure_ssh
((current_step++)); show_progress $current_step $total_steps "Setting up Samba"
setup_samba
((current_step++)); show_progress $current_step $total_steps "Configuring firewall"
configure_firewall
# Security setup
((current_step++)); show_progress $current_step $total_steps "Implementing security measures"
secure_shared_memory
install_fail2ban
configure_automatic_updates
# Optional services
if [[ "${INSTALL_DOCKER:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing Docker"
install_docker
else
((current_step++))
fi
if [[ "${INSTALL_NFS:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing NFS"
install_nfs
else
((current_step++))
fi
if [[ "${INSTALL_NETDATA:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing Netdata"
install_netdata
else
((current_step++))
fi
if [[ "${INSTALL_VAULTWARDEN:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing Vaultwarden"
install_vaultwarden
else
((current_step++))
fi
if [[ "${INSTALL_JELLYFIN:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing Jellyfin"
install_jellyfin
else
((current_step++))
fi
if [[ "${INSTALL_PORTAINER:-false}" == "true" ]]; then
((current_step++)); show_progress $current_step $total_steps "Installing Portainer"
install_portainer
else
((current_step++))
fi
}
# Installation summary
show_installation_summary() {
echo
log_success "=== NAS Setup Completed Successfully ==="
echo
log_info "Installation Summary:"
echo " ✓ System updated and secured"
echo " ✓ User '${ADMIN_USER:-$NEW_USER}' created with sudo access"
echo " ✓ SSH configured on port ${SSH_PORT:-$DEFAULT_SSH_PORT}"
echo " ✓ Samba file sharing configured"
echo " ✓ Firewall configured and enabled"
echo " ✓ Fail2ban installed and configured"
echo " ✓ Automatic updates enabled"
# Service summary
if [[ "${INSTALL_DOCKER:-false}" == "true" ]]; then
echo " ✓ Docker installed and configured"
fi
if [[ "${INSTALL_NFS:-false}" == "true" ]]; then
echo " ✓ NFS server installed"
fi
if [[ "${INSTALL_NETDATA:-false}" == "true" ]]; then
echo " ✓ Netdata monitoring: http://$(hostname -I | awk '{print $1}'):${NETDATA_PORT}"
fi
if [[ "${INSTALL_JELLYFIN:-false}" == "true" ]]; then
echo " ✓ Jellyfin media server: http://$(hostname -I | awk '{print $1}'):8096"
fi
if [[ "${INSTALL_PORTAINER:-false}" == "true" ]]; then
echo " ✓ Portainer Docker management: http://$(hostname -I | awk '{print $1}'):9000"
fi
echo
log_info "Next steps:"
echo " 1. Reboot the system to ensure all changes take effect"
echo " 2. Access your NAS via SSH on port ${SSH_PORT:-$DEFAULT_SSH_PORT}"
echo " 3. Configure file shares through Samba"
echo " 4. Review firewall rules with: sudo ufw status"
echo
log_warning "Important: Please save the following information:"
echo " - SSH Port: ${SSH_PORT:-$DEFAULT_SSH_PORT}"
echo " - Admin User: ${ADMIN_USER:-$NEW_USER}"
echo " - Configuration saved in: ${CONFIG_FILE}"
echo " - Installation log: ${LOG_FILE}"
}
# Main script execution
log_info "NAS Setup Script started."
main() {
clear
echo -e "${CYAN}${BOLD}"
echo "╔══════════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "${SCRIPT_NAME} v${SCRIPT_VERSION}"
echo "║ ║"
echo "║ Automated NAS Setup for Multiple Linux Distros ║"
echo "║ ║"
echo "║ by ${SCRIPT_AUTHOR}"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════════╝"
echo -e "${NC}"
echo
log_info "${SCRIPT_NAME} v${SCRIPT_VERSION} started"
log_info "Running on: $(uname -a)"
# Pre-flight checks
detect_distro
check_system_requirements
get_system_info
# Configuration
load_or_create_config
# Confirmation
echo
if ! ask_yes_no "Ready to start installation?" "y"; then
log_info "Installation cancelled by user"
exit 0
fi
# Main installation
log_info "Starting installation process..."
update_system
run_installation
# Cleanup and summary
cleanup
optimize_nas_performance
perform_health_check
show_installation_summary
# Reboot prompt
echo
if ask_yes_no "Reboot system now to complete setup?" "y"; then
log_info "System will reboot in 5 seconds..."
sleep 5
sudo reboot
else
log_warning "Please reboot the system manually to complete the setup"
fi
}
detect_distro
check_internet_connection
case $DISTRO in
ubuntu|debian)
check_ubuntu_version
;;
fedora|arch|opensuse)
# Add specific checks here if needed
;;
*)
log_error "Unsupported Linux distribution: $DISTRO"
exit 1
;;
esac
check_system_requirements
load_or_create_config
update_system
configure_network
configure_ssh
setup_samba
configure_firewall
secure_shared_memory
install_fail2ban
configure_automatic_updates
setup_basic_monitoring
if ask_yes_no "Do you want to install Docker?"; then
install_docker
fi
if ask_yes_no "Do you want to install additional components?"; then
install_additional_components
else
log_info "Installation of additional components skipped."
fi
if ask_yes_no "Do you want to install NFS?"; then
install_nfs
fi
if ask_yes_no "Do you want to install Netdata for advanced monitoring?"; then
install_netdata
fi
if ask_yes_no "Do you want to install Vaultwarden?"; then
install_vaultwarden
fi
if ask_yes_no "Do you want to install Jellyfin?"; then
install_jellyfin
fi
if ask_yes_no "Do you want to install Portainer?"; then
install_portainer
fi
cleanup
log_info "Setup completed. User $NEW_USER has been created with sudo and Samba access. Installation of optional components completed."
show_progress 100 100 "Setup completed"
log_info "Please reboot your system to ensure all changes take effect."
if ask_yes_no "Do you want to reboot now?"; then
sudo reboot
fi
# Run main function
main "$@"