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

View File

@@ -1,22 +1,66 @@
#!/bin/bash
configure_network() {
log_info "Configuring network..."
# Enhanced network configuration with validation and rollback support
# Network interface detection
detect_network_interface() {
local interface
local interface=$(ip route | awk '/default/ {print $5}')
local current_ip=$(ip addr show $interface | awk '/inet / {print $2}' | cut -d/ -f1)
# Try to detect active interface
interface=$(ip route show default | awk 'NR==1 {print $5}')
read -p "Enter static IP address [$current_ip]: " static_ip
static_ip=${static_ip:-$current_ip}
if [[ -z "$interface" ]]; then
# Fallback to first available interface
interface=$(ip link show | awk -F: '$0 !~ "lo|vir|docker|br-"{print $2; exit}' | tr -d ' ')
fi
read -p "Enter gateway IP: " gateway_ip
read -p "Enter DNS server IP: " dns_ip
if [[ -z "$interface" ]]; then
log_error "No network interface detected"
return 1
fi
backup_config "/etc/netplan/01-netcfg.yaml"
echo "$interface"
return 0
}
# Get current network configuration
get_current_network_config() {
local interface="$1"
local current_ip gateway_ip dns_servers
case $DISTRO in
ubuntu|debian)
cat <<EOL | sudo tee /etc/netplan/01-netcfg.yaml > /dev/null
# Get current IP
current_ip=$(ip addr show "$interface" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)
# Get current gateway
gateway_ip=$(ip route show default | awk 'NR==1 {print $3}')
# Get DNS servers
if [[ -f /etc/resolv.conf ]]; then
dns_servers=$(awk '/^nameserver/ {print $2}' /etc/resolv.conf | head -n2 | tr '\n' ',' | sed 's/,$//')
fi
echo "Current IP: ${current_ip:-"Not set"}"
echo "Current Gateway: ${gateway_ip:-"Not set"}"
echo "Current DNS: ${dns_servers:-"Not set"}"
}
# Configure static IP for Ubuntu/Debian (netplan)
configure_netplan() {
local interface="$1"
local static_ip="$2"
local gateway_ip="$3"
local dns_ip="$4"
local netplan_file="/etc/netplan/01-netcfg.yaml"
log_info "Configuring network via netplan..."
# Backup existing configuration
if ! backup_config "$netplan_file"; then
return 1
fi
# Create new netplan configuration
cat <<EOF | sudo tee "$netplan_file" > /dev/null
network:
version: 2
renderer: networkd
@@ -27,12 +71,45 @@ network:
- to: default
via: $gateway_ip
nameservers:
addresses: [$dns_ip]
EOL
sudo netplan apply
;;
fedora|arch|opensuse)
cat <<EOL | sudo tee /etc/sysconfig/network-scripts/ifcfg-$interface > /dev/null
addresses: [$dns_ip, 8.8.8.8]
dhcp4: false
dhcp6: false
EOF
# Validate netplan configuration
if ! sudo netplan generate 2>/dev/null; then
log_error "Invalid netplan configuration generated"
return 1
fi
# Apply configuration
if sudo netplan apply; then
log_success "Netplan configuration applied successfully"
add_rollback_action "sudo cp ${netplan_file}.bak ${netplan_file} && sudo netplan apply"
return 0
else
log_error "Failed to apply netplan configuration"
return 1
fi
}
# Configure static IP for RedHat-based systems
configure_networkmanager() {
local interface="$1"
local static_ip="$2"
local gateway_ip="$3"
local dns_ip="$4"
local ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-$interface"
log_info "Configuring network via NetworkManager..."
# Backup existing configuration
if [[ -f "$ifcfg_file" ]]; then
backup_config "$ifcfg_file"
fi
# Create new interface configuration
cat <<EOF | sudo tee "$ifcfg_file" > /dev/null
DEVICE=$interface
BOOTPROTO=none
ONBOOT=yes
@@ -40,16 +117,292 @@ IPADDR=$static_ip
PREFIX=24
GATEWAY=$gateway_ip
DNS1=$dns_ip
EOL
sudo systemctl restart NetworkManager
DNS2=8.8.8.8
DEFROUTE=yes
EOF
# Restart NetworkManager
if sudo systemctl restart NetworkManager; then
log_success "NetworkManager configuration applied successfully"
add_rollback_action "sudo systemctl restart NetworkManager"
return 0
else
log_error "Failed to restart NetworkManager"
return 1
fi
}
# Configure static IP for Arch Linux
configure_systemd_networkd() {
local interface="$1"
local static_ip="$2"
local gateway_ip="$3"
local dns_ip="$4"
local network_file="/etc/systemd/network/20-$interface.network"
log_info "Configuring network via systemd-networkd..."
# Create network configuration
cat <<EOF | sudo tee "$network_file" > /dev/null
[Match]
Name=$interface
[Network]
Address=$static_ip/24
Gateway=$gateway_ip
DNS=$dns_ip
DNS=8.8.8.8
EOF
# Enable and restart systemd-networkd
sudo systemctl enable systemd-networkd
if sudo systemctl restart systemd-networkd; then
log_success "systemd-networkd configuration applied successfully"
add_rollback_action "sudo rm -f $network_file && sudo systemctl restart systemd-networkd"
return 0
else
log_error "Failed to restart systemd-networkd"
return 1
fi
}
# Test network connectivity after configuration
test_network_connectivity() {
local test_ip="$1"
local timeout=30
local count=0
log_info "Testing network connectivity..."
while [[ $count -lt $timeout ]]; do
if ping -c 1 -W 3 "$test_ip" &>/dev/null; then
log_success "Network connectivity test passed"
return 0
fi
((count++))
echo -n "."
sleep 1
done
echo
log_error "Network connectivity test failed after ${timeout} seconds"
return 1
}
# Configure SSH with enhanced security
configure_ssh() {
local ssh_config="/etc/ssh/sshd_config"
local ssh_port="${SSH_PORT:-$DEFAULT_SSH_PORT}"
log_info "Configuring SSH server..."
# Backup SSH configuration
if ! backup_config "$ssh_config"; then
return 1
fi
# Create new user if not exists
if ! id "${ADMIN_USER:-$NEW_USER}" &>/dev/null; then
log_info "Creating user ${ADMIN_USER:-$NEW_USER}..."
sudo useradd -m -s /bin/bash "${ADMIN_USER:-$NEW_USER}"
sudo usermod -aG sudo "${ADMIN_USER:-$NEW_USER}"
# Set password
local password=$(ask_password "Set password for user ${ADMIN_USER:-$NEW_USER}")
echo "${ADMIN_USER:-$NEW_USER}:$password" | sudo chpasswd
add_rollback_action "sudo userdel -r ${ADMIN_USER:-$NEW_USER}"
fi
# Configure SSH hardening
sudo tee -a "$ssh_config" > /dev/null <<EOF
# NAS Setup Script Configuration
Port $ssh_port
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
LoginGraceTime 60
AllowUsers ${ADMIN_USER:-$NEW_USER}
Protocol 2
EOF
# Test SSH configuration
if sudo sshd -t; then
log_success "SSH configuration is valid"
else
log_error "SSH configuration is invalid"
return 1
fi
# Restart SSH service
if sudo systemctl restart sshd; then
log_success "SSH service restarted successfully"
add_rollback_action "sudo cp ${ssh_config}.bak ${ssh_config} && sudo systemctl restart sshd"
return 0
else
log_error "Failed to restart SSH service"
return 1
fi
}
# Setup Samba with enhanced configuration
setup_samba() {
log_info "Setting up Samba file sharing..."
# Install Samba
case $DISTRO in
ubuntu|debian)
sudo apt-get install -y samba samba-common-bin
;;
*)
log_error "Unsupported Linux distribution: $DISTRO"
exit 1
fedora)
sudo dnf install -y samba samba-common
;;
arch)
sudo pacman -S --noconfirm samba
;;
opensuse)
sudo zypper install -y samba
;;
esac
log_info "Network configuration applied."
# Backup Samba configuration
backup_config "$SAMBA_CONFIG"
# Create shared directory
local share_dir="/srv/samba/shared"
sudo mkdir -p "$share_dir"
sudo chown "${ADMIN_USER:-$NEW_USER}:${ADMIN_USER:-$NEW_USER}" "$share_dir"
sudo chmod 755 "$share_dir"
# Configure Samba
sudo tee "$SAMBA_CONFIG" > /dev/null <<EOF
[global]
workgroup = WORKGROUP
server string = NAS Server
security = user
map to guest = bad user
dns proxy = no
log file = /var/log/samba/log.%m
max log size = 1000
# Performance tuning
socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
read raw = yes
write raw = yes
oplocks = yes
max xmit = 65535
dead time = 15
getwd cache = yes
[shared]
path = $share_dir
browseable = yes
writable = yes
guest ok = no
valid users = ${ADMIN_USER:-$NEW_USER}
create mask = 0644
directory mask = 0755
EOF
# Add Samba user
local samba_password=$(ask_password "Set Samba password for user ${ADMIN_USER:-$NEW_USER}")
echo -e "$samba_password\n$samba_password" | sudo smbpasswd -a "${ADMIN_USER:-$NEW_USER}"
sudo smbpasswd -e "${ADMIN_USER:-$NEW_USER}"
# Start and enable Samba services
sudo systemctl enable smbd nmbd
if sudo systemctl restart smbd nmbd; then
log_success "Samba configured and started successfully"
log_info "Shared folder created at: $share_dir"
add_rollback_action "sudo systemctl stop smbd nmbd && sudo systemctl disable smbd nmbd"
return 0
else
log_error "Failed to start Samba services"
return 1
fi
}
# ...existing code...
# Main network configuration function
configure_network() {
if [[ "${CONFIGURE_STATIC_IP:-false}" != "true" ]]; then
log_info "Static IP configuration skipped"
return 0
fi
log_info "=== Network Configuration ==="
# Detect network interface
local interface
if ! interface=$(detect_network_interface); then
log_error "Failed to detect network interface"
return 1
fi
log_info "Detected network interface: $interface"
# Show current configuration
log_info "Current network configuration:"
get_current_network_config "$interface"
echo
# Get network configuration from user
local current_ip=$(ip addr show "$interface" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n1)
local current_gateway=$(ip route show default | awk 'NR==1 {print $3}')
local static_ip=$(ask_input "Static IP address" "$current_ip" "validate_ip")
local gateway_ip=$(ask_input "Gateway IP address" "$current_gateway" "validate_ip")
local dns_ip=$(ask_input "Primary DNS server" "8.8.8.8" "validate_ip")
# Confirm configuration
echo
log_info "Network configuration summary:"
echo " Interface: $interface"
echo " Static IP: $static_ip"
echo " Gateway: $gateway_ip"
echo " DNS: $dns_ip"
echo
if ! ask_yes_no "Apply this network configuration?" "y"; then
log_info "Network configuration cancelled"
return 0
fi
# Apply configuration based on distribution
case $DISTRO in
ubuntu|debian)
configure_netplan "$interface" "$static_ip" "$gateway_ip" "$dns_ip"
;;
fedora|opensuse)
configure_networkmanager "$interface" "$static_ip" "$gateway_ip" "$dns_ip"
;;
arch)
configure_systemd_networkd "$interface" "$static_ip" "$gateway_ip" "$dns_ip"
;;
*)
log_error "Unsupported distribution for network configuration: $DISTRO"
return 1
;;
esac
# Test connectivity
log_info "Waiting for network to stabilize..."
sleep 5
if test_network_connectivity "$gateway_ip"; then
log_success "Network configuration completed successfully"
return 0
else
log_error "Network configuration failed connectivity test"
return 1
fi
}