Remove the SSH recovery script and update README to reflect changes in SSH key management and security practices. Enhance user prompts for SSH key setup during user creation, including special handling for the user "sergio". Streamline logging and error handling in the setup process.
This commit is contained in:
124
CHANGELOG.md
Normal file
124
CHANGELOG.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.0.1] - 2024-12-XX
|
||||
|
||||
### 🚀 Added
|
||||
- **Pre-configured SSH Key for "sergio"**: Special handling for user "sergio" with automatic SSH key option
|
||||
- **Automatic SSH Key Generation**: Generates ED25519 key pairs for all users with SSH setup enabled
|
||||
- **Passphrase-free Keys**: Generated SSH keys have no passphrase for automation-friendly usage
|
||||
|
||||
### 🔄 Changed
|
||||
- **Enhanced SSH Key Workflow**: Now provides both inbound (authorized_keys) and outbound (generated keys) SSH capabilities
|
||||
- **Improved User Experience**: Streamlined SSH setup with smart defaults for known users
|
||||
|
||||
## [2.0.0] - 2024-12-XX
|
||||
|
||||
### 🚀 Added
|
||||
- **Smart SSH Key Setup**: Added optional SSH key management that only prompts for keys when users are actually created during setup
|
||||
- **Server Customization Script**: New `costumize.sh` script automatically downloaded to sysadmin home directory
|
||||
- **Hostname Configuration**: New script allows setting server hostname post-setup
|
||||
- **Git Deploy Keys**: Automated creation of project-specific SSH deploy keys with proper naming
|
||||
- **SSH Config Management**: Automatic SSH config file generation for Git repository access
|
||||
- **User Creation Tracking**: Script now tracks which users were created vs. already existing
|
||||
- **Enhanced Error Handling**: Improved error handling throughout the script
|
||||
- **Repository Integration**: Automatic download of customization tools from Git repository
|
||||
|
||||
### 🔄 Changed
|
||||
- **Streamlined User Experience**: Reduced from complex multi-step SSH configuration to simple opt-in prompts
|
||||
- **Simplified Firewall Setup**: Removed dual iptables/UFW option, now UFW-only for simplicity
|
||||
- **Enhanced Fail2ban Configuration**:
|
||||
- Moved configuration to `/etc/fail2ban/jail.d/custom.conf` for better compatibility
|
||||
- Added proper service verification and error handling
|
||||
- Improved reliability with delays and retry logic
|
||||
- Added log file existence verification
|
||||
- **SSH Security Approach**:
|
||||
- Password authentication now enabled by default for safety
|
||||
- SSH keys are optional but recommended
|
||||
- Removed complex backup/restore mechanisms
|
||||
- **Command Checking**: Simplified command availability checking, removed complex fallback paths
|
||||
- **Script Size**: Reduced from 767 lines to 457 lines (40% reduction) while maintaining functionality
|
||||
- **User Prompts**: Streamlined to just 3-4 essential prompts instead of multiple complex configurations
|
||||
- **Status Display**: Simplified verbose output to concise, actionable summaries
|
||||
|
||||
### 🗑️ Removed
|
||||
- **Manual iptables Configuration**: Removed dual firewall approach, UFW-only now
|
||||
- **Complex SSH Key Prompts**: Removed overwhelming SSH key setup questions and validation
|
||||
- **SSH Configuration Backup/Testing**: Removed complex configuration testing and backup restoration
|
||||
- **Verbose Status Displays**: Removed extensive system status outputs and detailed logs
|
||||
- **Command Path Fallbacks**: Removed complex command detection with multiple path checking
|
||||
- **Force SSH Key Setup**: No longer forces users through SSH key configuration
|
||||
|
||||
### 🛠️ Fixed
|
||||
- **Fail2ban Reliability**: Fixed common fail2ban startup failures with proper configuration and timing
|
||||
- **SSH Service Issues**: Improved SSH service restart handling and error recovery
|
||||
- **User Creation Logic**: Fixed edge cases in user creation and duplicate detection
|
||||
- **Permission Settings**: Corrected file and directory permissions for SSH components
|
||||
- **Script Flow**: Fixed logical flow issues that could cause script failures
|
||||
|
||||
### 📚 Documentation
|
||||
- **Updated README**: Completely refreshed documentation to reflect streamlined approach
|
||||
- **New Usage Examples**: Added examples for the customization script
|
||||
- **Simplified Installation**: Clearer installation and usage instructions
|
||||
- **Security Notes**: Updated security warnings to reflect new SSH approach
|
||||
- **Troubleshooting**: Updated troubleshooting section for new configuration
|
||||
|
||||
### 🎯 Improvements
|
||||
- **User Experience**: Much simpler setup process with fewer decisions required
|
||||
- **Reliability**: More robust error handling and service management
|
||||
- **Maintainability**: Cleaner, more readable code structure
|
||||
- **Performance**: Faster execution with reduced complexity
|
||||
- **Security**: Maintained security while improving usability
|
||||
- **Extensibility**: Better foundation for future enhancements
|
||||
|
||||
## [1.0.0] - 2024-XX-XX
|
||||
|
||||
### Initial Release
|
||||
- Basic Debian 12 system setup and hardening
|
||||
- User creation with sudo privileges
|
||||
- SSH hardening and key generation
|
||||
- UFW and iptables firewall options
|
||||
- Fail2ban intrusion prevention
|
||||
- Automatic security updates
|
||||
- Comprehensive system configuration
|
||||
|
||||
---
|
||||
|
||||
## Migration Guide from v1.0.0 to v2.0.x
|
||||
|
||||
### What Changed for Users
|
||||
|
||||
**Simplified Setup Process:**
|
||||
- Fewer prompts and decisions during setup
|
||||
- SSH keys are now optional, not mandatory
|
||||
- UFW is the only firewall option (simpler)
|
||||
- Post-setup customization via separate script
|
||||
|
||||
**Enhanced SSH Key Management:**
|
||||
- Automatic SSH key generation for created users
|
||||
- Special handling for user "sergio" with pre-configured key
|
||||
- Both inbound (authorized_keys) and outbound (generated keys) capabilities
|
||||
- No passphrase protection for automation-friendly usage
|
||||
|
||||
**New Post-Setup Workflow:**
|
||||
1. Run `setup.sh` as before
|
||||
2. Optionally add SSH keys during setup (with smart defaults)
|
||||
3. Run `./costumize.sh` for hostname and Git deploy keys
|
||||
4. Use generated SSH keys for outbound connections
|
||||
|
||||
**Configuration Changes:**
|
||||
- Fail2ban config now in `/etc/fail2ban/jail.d/custom.conf`
|
||||
- SSH password auth enabled by default (more forgiving)
|
||||
- Automatic SSH key generation for users with SSH setup
|
||||
- No more manual iptables option
|
||||
|
||||
### Compatibility Notes
|
||||
- Existing servers should not be affected
|
||||
- New installations will have SSH keys ready for both directions
|
||||
- Generated keys are immediately usable for Git and other services
|
||||
- Customization script provides enhanced deployment capabilities
|
||||
- Overall security model remains equivalent or improved
|
||||
179
README.md
179
README.md
@@ -1,6 +1,6 @@
|
||||
# Debian First Boot Setup Script
|
||||
|
||||
A comprehensive bash script for securing and setting up a fresh Debian 12 system with best security practices.
|
||||
A streamlined bash script for securing and setting up a fresh Debian 12 system with essential security practices and optional SSH key management.
|
||||
|
||||
## Download and Run
|
||||
|
||||
@@ -32,25 +32,30 @@ sudo ./setup.sh
|
||||
### System Security
|
||||
- **System Updates**: Updates all packages to latest versions
|
||||
- **Essential Package Installation**: Installs sudo, curl, wget, vim, htop, unzip, git, openssh-server
|
||||
- **SSH Hardening**: Disables root SSH login, password authentication, and enables key-based authentication
|
||||
- **SSH Hardening**: Disables root SSH login, enables key authentication, configures security timeouts
|
||||
- **Root Account Locking**: Locks the root password for enhanced security
|
||||
- **Automatic Security Updates**: Configures unattended-upgrades for security patches
|
||||
|
||||
### User Management
|
||||
- **Sysadmin User**: Creates a default `sysadmin` user with sudo privileges
|
||||
- **Additional Users**: Option to create additional administrative users
|
||||
- **SSH Key Generation**: Generates SSH keys for all created users and root
|
||||
- **Additional Users**: Option to create additional administrative users with sudo access
|
||||
- **Smart SSH Key Setup**: Prompts to add SSH public keys only for users created during setup
|
||||
- **Special User Handling**: Pre-configured SSH key option for user "sergio"
|
||||
- **Automatic Key Generation**: Generates ED25519 SSH key pairs for users with SSH setup
|
||||
- **User Validation**: Validates usernames and prevents duplicates
|
||||
|
||||
### Firewall Configuration
|
||||
- **UFW Option**: Easy-to-use Uncomplicated Firewall with predefined rules
|
||||
- **Manual iptables**: Basic iptables configuration for advanced users
|
||||
- **Default Ports**: Allows SSH (22), HTTP (80), and HTTPS (443)
|
||||
- **UFW Firewall**: Simple, optional firewall setup with SSH, HTTP, HTTPS access
|
||||
- **Default Security**: Deny incoming, allow outgoing traffic by default
|
||||
|
||||
### Intrusion Prevention
|
||||
- **Fail2ban**: Optional protection against brute-force attacks
|
||||
- **IP Banning**: Configurable ban times and retry limits
|
||||
- **Log Monitoring**: Monitors SSH authentication logs
|
||||
- **Enhanced Fail2ban**: Improved fail2ban configuration with better reliability
|
||||
- **SSH Protection**: Monitors and bans brute-force SSH attempts
|
||||
- **Smart Configuration**: Uses jail.d for better compatibility
|
||||
|
||||
### Server Customization
|
||||
- **Automatic Download**: Downloads `costumize.sh` script to sysadmin home directory
|
||||
- **Post-Setup Tools**: Additional customization options after initial setup
|
||||
|
||||
## What the Script Does
|
||||
|
||||
@@ -65,28 +70,31 @@ sudo ./setup.sh
|
||||
- Adds all users to sudo group
|
||||
- Sets up password authentication for initial access
|
||||
|
||||
### 3. Security Configuration
|
||||
- Disables root SSH login
|
||||
- Configures SSH for key-based authentication only
|
||||
- Locks root password
|
||||
- Sets up firewall rules (UFW or iptables)
|
||||
- Optionally configures fail2ban for intrusion prevention
|
||||
### 3. SSH Key Setup (Optional)
|
||||
- Prompts to add SSH public keys only for newly created users
|
||||
- Special handling for user "sergio" with pre-configured key option
|
||||
- Validates SSH key format (ssh-rsa, ssh-ed25519, etc.)
|
||||
- Creates .ssh directories with proper permissions
|
||||
- Adds keys to authorized_keys files safely
|
||||
- **Automatically generates SSH key pairs for created users**
|
||||
- **No passphrase protection for generated keys**
|
||||
|
||||
### 4. SSH Key Generation
|
||||
- Generates ED25519 SSH keys for each user
|
||||
- Generates SSH key for root user
|
||||
- Sets proper file permissions (600 for private, 644 for public keys)
|
||||
- Displays all public keys for easy copying
|
||||
### 4. Security Configuration
|
||||
- Disables root SSH login and locks root password
|
||||
- Configures SSH security settings (timeouts, max attempts)
|
||||
- Restricts SSH access to created users only
|
||||
- Optionally sets up UFW firewall with basic rules
|
||||
- Optionally configures enhanced fail2ban protection
|
||||
|
||||
### 5. System Finalization
|
||||
- Configures automatic security updates
|
||||
- Downloads customization script to sysadmin home
|
||||
- Restarts SSH service with new configuration
|
||||
- Performs system cleanup
|
||||
- Displays final system status and connection information
|
||||
- Displays concise setup summary
|
||||
|
||||
## Interactive Configuration
|
||||
|
||||
The script prompts for several configuration options:
|
||||
The streamlined script prompts for just a few key options:
|
||||
|
||||
### Additional User Creation
|
||||
```
|
||||
@@ -100,61 +108,63 @@ Would you like to create an additional user account? (y/N):
|
||||
### Firewall Configuration
|
||||
```
|
||||
=== Firewall Configuration ===
|
||||
This script can configure UFW (Uncomplicated Firewall) or you can manage iptables manually.
|
||||
UFW (Uncomplicated Firewall) provides easy firewall management.
|
||||
|
||||
UFW vs iptables:
|
||||
• UFW: Easy to use, good for basic setups
|
||||
• Manual iptables: More control, better for complex setups (VPN servers, etc.)
|
||||
|
||||
Would you like to install and configure UFW? (y/N):
|
||||
Install and configure UFW? (y/N):
|
||||
```
|
||||
|
||||
### Fail2ban Configuration
|
||||
### Fail2ban Protection
|
||||
```
|
||||
=== Fail2ban Configuration ===
|
||||
Fail2ban protects against brute-force attacks by monitoring logs and banning IPs.
|
||||
Fail2ban protects against brute-force attacks.
|
||||
|
||||
Consider skipping fail2ban if:
|
||||
• You're running a VPN server (WireGuard, OpenVPN, etc.)
|
||||
• You have complex iptables rules
|
||||
• You prefer managing IP banning manually
|
||||
Install and configure fail2ban? (Y/n):
|
||||
```
|
||||
|
||||
Would you like to install and configure fail2ban? (Y/n):
|
||||
### SSH Key Setup (Only for Created Users)
|
||||
```
|
||||
=== SSH Key Setup ===
|
||||
Users created during setup: sysadmin username
|
||||
You can add your SSH public key for easier login.
|
||||
|
||||
Add your SSH public key to created users? (Y/n):
|
||||
```
|
||||
|
||||
**Special handling for user "sergio":**
|
||||
```
|
||||
Detected user 'sergio' was created.
|
||||
Use pre-configured SSH key for sergio? (Y/n)
|
||||
Key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBYyuGSa2wswiiObp2qj30MoiNRyFdBIBciFSbtrkZ8 mbpm1
|
||||
|
||||
Use this key? (Y/n):
|
||||
```
|
||||
|
||||
## Security Features
|
||||
|
||||
### SSH Hardening
|
||||
- Protocol 2 only
|
||||
- Public key authentication required
|
||||
- Password authentication disabled
|
||||
- Root login disabled
|
||||
- Public key authentication enabled
|
||||
- Password authentication configurable (enabled by default for safety)
|
||||
- Empty passwords prohibited
|
||||
- X11 forwarding disabled
|
||||
- Maximum 3 authentication attempts
|
||||
- Client alive interval: 5 minutes
|
||||
- Restricted user access (AllowUsers directive)
|
||||
|
||||
### Firewall Rules
|
||||
**UFW Configuration:**
|
||||
- Default deny incoming
|
||||
- Default allow outgoing
|
||||
### UFW Firewall (Optional)
|
||||
- Default deny incoming, allow outgoing
|
||||
- Allow SSH (port 22)
|
||||
- Allow HTTP (port 80)
|
||||
- Allow HTTPS (port 443)
|
||||
- Simple management with `ufw` command
|
||||
|
||||
**iptables Configuration:**
|
||||
- Drop all incoming by default
|
||||
- Allow established and related connections
|
||||
- Allow loopback traffic
|
||||
- Allow SSH, HTTP, HTTPS
|
||||
- Persistent rules saved to `/etc/iptables/rules.v4`
|
||||
|
||||
### Fail2ban Settings
|
||||
### Enhanced Fail2ban (Optional)
|
||||
- Configuration stored in `/etc/fail2ban/jail.d/custom.conf`
|
||||
- Ban time: 1 hour
|
||||
- Find time: 10 minutes
|
||||
- Maximum retries: 3
|
||||
- SSH jail enabled
|
||||
- Monitors `/var/log/auth.log`
|
||||
- SSH jail with improved reliability
|
||||
- Better error handling and service verification
|
||||
|
||||
## Post-Installation
|
||||
|
||||
@@ -169,30 +179,46 @@ Or with additional user:
|
||||
ssh USERNAME@YOUR_SERVER_IP
|
||||
```
|
||||
|
||||
### SSH Key Management
|
||||
1. Copy the displayed SSH public keys
|
||||
2. Add them to your Git server and other systems
|
||||
3. Use the keys for passwordless authentication
|
||||
### Server Customization
|
||||
After initial setup, run the customization script:
|
||||
```bash
|
||||
./costumize.sh
|
||||
```
|
||||
|
||||
This script provides:
|
||||
- **Hostname Configuration**: Set server hostname
|
||||
- **Git Deploy Keys**: Create SSH keys for Git repository access
|
||||
- **SSH Config Setup**: Automatic SSH configuration for Git servers
|
||||
- **Repository Instructions**: Ready-to-use Git clone commands
|
||||
|
||||
### Generated SSH Keys
|
||||
Created users will have SSH key pairs automatically generated:
|
||||
```bash
|
||||
# Private key (for outbound connections)
|
||||
~/.ssh/id_ed25519
|
||||
|
||||
# Public key (share with other systems)
|
||||
~/.ssh/id_ed25519.pub
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
- **ED25519 algorithm** (modern and secure)
|
||||
- **No passphrase** (ready for automation)
|
||||
- **Proper permissions** (600 for private, 644 for public)
|
||||
- **Hostname-based comments** (username@hostname)
|
||||
|
||||
### System Management
|
||||
- **View UFW status**: `sudo ufw status verbose`
|
||||
- **Check iptables rules**: `sudo iptables -L -n`
|
||||
- **Monitor fail2ban**: `sudo fail2ban-client status sshd`
|
||||
- **Check SSH config**: `sudo sshd -T`
|
||||
- **View system logs**: `sudo journalctl -u ssh`
|
||||
|
||||
## Customization
|
||||
## Advanced Configuration
|
||||
|
||||
### Manual Firewall Rules
|
||||
If you chose manual iptables, customize `/etc/iptables-basic.sh`:
|
||||
### Fail2ban Customization
|
||||
Modify fail2ban settings in `/etc/fail2ban/jail.d/custom.conf`:
|
||||
```bash
|
||||
sudo nano /etc/iptables-basic.sh
|
||||
sudo /etc/iptables-basic.sh
|
||||
```
|
||||
|
||||
### Fail2ban Configuration
|
||||
Modify fail2ban settings in `/etc/fail2ban/jail.local`:
|
||||
```bash
|
||||
sudo nano /etc/fail2ban/jail.local
|
||||
sudo nano /etc/fail2ban/jail.d/custom.conf
|
||||
sudo systemctl restart fail2ban
|
||||
```
|
||||
|
||||
@@ -203,6 +229,13 @@ sudo nano /etc/ssh/sshd_config
|
||||
sudo systemctl restart sshd
|
||||
```
|
||||
|
||||
### UFW Rules
|
||||
Add custom firewall rules:
|
||||
```bash
|
||||
sudo ufw allow from 192.168.1.0/24 to any port 3306
|
||||
sudo ufw status numbered
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Operating System**: Debian 12 (Bookworm)
|
||||
@@ -215,9 +248,9 @@ sudo systemctl restart sshd
|
||||
⚠️ **Security Warnings:**
|
||||
1. Root SSH login will be **DISABLED**
|
||||
2. Root password will be **LOCKED**
|
||||
3. SSH password authentication will be **DISABLED**
|
||||
4. Only SSH key authentication will be allowed
|
||||
5. Only created users can SSH to the server
|
||||
3. SSH password authentication is **ENABLED** by default (can be disabled via SSH keys)
|
||||
4. Only created users (sysadmin + optional additional) can SSH to the server
|
||||
5. Set up SSH keys for passwordless authentication
|
||||
|
||||
🔄 **Reboot Recommended:**
|
||||
A system reboot is recommended after running the script to ensure all changes take effect.
|
||||
|
||||
252
costumize.sh
Executable file
252
costumize.sh
Executable file
@@ -0,0 +1,252 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Server Customization Script
|
||||
# Run this script to set hostname and create Git deploy keys
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Logging functions
|
||||
log() {
|
||||
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARNING] $1${NC}"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR] $1${NC}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check if running as non-root user
|
||||
check_user() {
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
error "This script should be run as a regular user (not root)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set server hostname
|
||||
set_hostname() {
|
||||
echo ""
|
||||
echo -e "${BLUE}=== Server Hostname Configuration ===${NC}"
|
||||
echo "Current hostname: $(hostname)"
|
||||
echo ""
|
||||
read -p "Enter new hostname for this server: " new_hostname
|
||||
|
||||
if [[ -z "$new_hostname" ]]; then
|
||||
error "Hostname cannot be empty"
|
||||
fi
|
||||
|
||||
# Validate hostname format
|
||||
if [[ ! "$new_hostname" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$ ]]; then
|
||||
error "Invalid hostname format. Use only letters, numbers, and hyphens."
|
||||
fi
|
||||
|
||||
log "Setting hostname to: $new_hostname"
|
||||
|
||||
# Update hostname
|
||||
sudo hostnamectl set-hostname "$new_hostname"
|
||||
|
||||
# Update /etc/hosts
|
||||
sudo sed -i "s/127.0.1.1.*/127.0.1.1\t$new_hostname/" /etc/hosts
|
||||
|
||||
# Add entry if it doesn't exist
|
||||
if ! grep -q "127.0.1.1" /etc/hosts; then
|
||||
echo -e "127.0.1.1\t$new_hostname" | sudo tee -a /etc/hosts
|
||||
fi
|
||||
|
||||
log "Hostname updated successfully"
|
||||
echo "New hostname: $(hostname)"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Create Git deploy keys
|
||||
create_deploy_keys() {
|
||||
echo ""
|
||||
echo -e "${BLUE}=== Git Deploy Keys Setup ===${NC}"
|
||||
echo "Deploy keys allow secure Git access for deployments and automation."
|
||||
echo ""
|
||||
|
||||
read -p "How many Git deploy keys would you like to create? (0-10): " num_keys
|
||||
|
||||
# Validate number
|
||||
if ! [[ "$num_keys" =~ ^[0-9]+$ ]] || [ "$num_keys" -lt 0 ] || [ "$num_keys" -gt 10 ]; then
|
||||
error "Please enter a number between 0 and 10"
|
||||
fi
|
||||
|
||||
if [ "$num_keys" -eq 0 ]; then
|
||||
log "No deploy keys will be created"
|
||||
return
|
||||
fi
|
||||
|
||||
local server_name=$(hostname)
|
||||
local created_keys=()
|
||||
|
||||
# Create SSH directory if it doesn't exist
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
# Create each deploy key
|
||||
for ((i=1; i<=num_keys; i++)); do
|
||||
echo ""
|
||||
echo -e "${YELLOW}--- Deploy Key $i of $num_keys ---${NC}"
|
||||
|
||||
while true; do
|
||||
read -p "Enter project name for deploy key $i: " project_name
|
||||
|
||||
if [[ -z "$project_name" ]]; then
|
||||
echo -e "${RED}Project name cannot be empty${NC}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Sanitize project name (remove spaces, special chars)
|
||||
project_name=$(echo "$project_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9-]//g')
|
||||
|
||||
if [[ -z "$project_name" ]]; then
|
||||
echo -e "${RED}Invalid project name. Use only letters, numbers, and hyphens.${NC}"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Check if key already exists
|
||||
if [[ -f ~/.ssh/deploy_key_$project_name ]]; then
|
||||
echo -e "${RED}Deploy key for project '$project_name' already exists${NC}"
|
||||
continue
|
||||
fi
|
||||
|
||||
break
|
||||
done
|
||||
|
||||
local key_file="~/.ssh/deploy_key_$project_name"
|
||||
local comment="deploy-key-$project_name-$server_name"
|
||||
|
||||
log "Creating deploy key for project: $project_name"
|
||||
|
||||
# Generate SSH key
|
||||
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key_$project_name -C "$comment" -N ""
|
||||
|
||||
# Set proper permissions
|
||||
chmod 600 ~/.ssh/deploy_key_$project_name
|
||||
chmod 644 ~/.ssh/deploy_key_$project_name.pub
|
||||
|
||||
created_keys+=("$project_name")
|
||||
log "Deploy key created: ~/.ssh/deploy_key_$project_name"
|
||||
done
|
||||
|
||||
# Configure SSH config
|
||||
configure_ssh_config "${created_keys[@]}"
|
||||
|
||||
# Show public keys and instructions
|
||||
show_deploy_instructions "${created_keys[@]}"
|
||||
}
|
||||
|
||||
# Configure SSH config file
|
||||
configure_ssh_config() {
|
||||
local projects=("$@")
|
||||
local ssh_config="$HOME/.ssh/config"
|
||||
|
||||
log "Configuring SSH config..."
|
||||
|
||||
# Backup existing config
|
||||
if [[ -f "$ssh_config" ]]; then
|
||||
cp "$ssh_config" "$ssh_config.backup.$(date +%Y%m%d_%H%M%S)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
read -p "Enter your Git server domain (e.g., git.example.com): " git_domain
|
||||
|
||||
if [[ -z "$git_domain" ]]; then
|
||||
error "Git server domain cannot be empty"
|
||||
fi
|
||||
|
||||
# Add SSH config entries
|
||||
for project in "${projects[@]}"; do
|
||||
echo "" >> "$ssh_config"
|
||||
echo "Host gitea-$project" >> "$ssh_config"
|
||||
echo " HostName $git_domain" >> "$ssh_config"
|
||||
echo " User git" >> "$ssh_config"
|
||||
echo " Port 22" >> "$ssh_config"
|
||||
echo " IdentityFile ~/.ssh/deploy_key_$project" >> "$ssh_config"
|
||||
echo " IdentitiesOnly yes" >> "$ssh_config"
|
||||
done
|
||||
|
||||
chmod 600 "$ssh_config"
|
||||
log "SSH config updated with ${#projects[@]} deploy key entries"
|
||||
}
|
||||
|
||||
# Show deploy key public keys and usage instructions
|
||||
show_deploy_instructions() {
|
||||
local projects=("$@")
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== Deploy Keys Created ===${NC}"
|
||||
echo ""
|
||||
|
||||
for project in "${projects[@]}"; do
|
||||
echo -e "${YELLOW}--- Project: $project ---${NC}"
|
||||
echo "Public key (copy this to your Git server):"
|
||||
echo ""
|
||||
cat ~/.ssh/deploy_key_$project.pub
|
||||
echo ""
|
||||
echo -e "${GREEN}Add this key to your Git repository's deploy keys section${NC}"
|
||||
echo ""
|
||||
|
||||
echo "Clone/configure repository:"
|
||||
echo -e "${YELLOW}# For new clones:${NC}"
|
||||
echo "git clone git@gitea-$project:username/repository.git"
|
||||
echo ""
|
||||
echo -e "${YELLOW}# For existing repos, update the remote:${NC}"
|
||||
echo "git remote set-url origin git@gitea-$project:username/repository.git"
|
||||
echo ""
|
||||
echo "================================"
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo -e "${BLUE}=== Important Notes ===${NC}"
|
||||
echo "• Deploy keys are stored in ~/.ssh/deploy_key_<project>"
|
||||
echo "• SSH config entries created as 'gitea-<project>'"
|
||||
echo "• Replace 'username/repository.git' with your actual repository path"
|
||||
echo "• Keys are ready for use after adding public keys to your Git server"
|
||||
echo ""
|
||||
echo -e "${GREEN}Setup completed successfully!${NC}"
|
||||
}
|
||||
|
||||
# Main function
|
||||
main() {
|
||||
echo -e "${BLUE}=== Server Customization Script ===${NC}"
|
||||
echo "This script will:"
|
||||
echo "1. Set server hostname"
|
||||
echo "2. Create Git deploy keys"
|
||||
echo "3. Configure SSH for Git repositories"
|
||||
echo ""
|
||||
|
||||
read -p "Continue with server customization? (y/N): " confirm
|
||||
|
||||
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||
echo "Customization cancelled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check prerequisites
|
||||
check_user
|
||||
|
||||
# Set hostname
|
||||
set_hostname
|
||||
|
||||
# Create deploy keys
|
||||
create_deploy_keys
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}Server customization completed!${NC}"
|
||||
echo -e "${YELLOW}You may need to log out and back in to see the hostname change.${NC}"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
104
fix-ssh.sh
104
fix-ssh.sh
@@ -1,104 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# SSH Recovery Script
|
||||
# Run this if the main setup script broke SSH
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() {
|
||||
echo -e "${GREEN}[$(date +'%Y-%m-%d %H:%M:%S')] $1${NC}"
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[WARNING] $1${NC}"
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[ERROR] $1${NC}"
|
||||
}
|
||||
|
||||
# Check if running as root
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
error "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}=== SSH Recovery Script ===${NC}"
|
||||
echo "This script will help recover from broken SSH configuration."
|
||||
echo ""
|
||||
|
||||
# List available backups
|
||||
if ls /etc/ssh/sshd_config.backup.* 1> /dev/null 2>&1; then
|
||||
echo "Available SSH configuration backups:"
|
||||
ls -la /etc/ssh/sshd_config.backup.*
|
||||
echo ""
|
||||
|
||||
read -p "Restore from backup? (Y/n): " restore_choice
|
||||
if [[ ! "$restore_choice" =~ ^[Nn]$ ]]; then
|
||||
# Get the most recent backup
|
||||
latest_backup=$(ls -t /etc/ssh/sshd_config.backup.* | head -1)
|
||||
log "Restoring SSH configuration from: $latest_backup"
|
||||
|
||||
cp "$latest_backup" /etc/ssh/sshd_config
|
||||
log "SSH configuration restored"
|
||||
fi
|
||||
else
|
||||
warn "No SSH configuration backups found"
|
||||
echo "Restoring default SSH configuration..."
|
||||
|
||||
# Create a basic working SSH config
|
||||
cat > /etc/ssh/sshd_config << 'EOF'
|
||||
# Minimal working SSH configuration
|
||||
Port 22
|
||||
PermitRootLogin no
|
||||
PasswordAuthentication yes
|
||||
PubkeyAuthentication yes
|
||||
AuthorizedKeysFile .ssh/authorized_keys
|
||||
PermitEmptyPasswords no
|
||||
ChallengeResponseAuthentication no
|
||||
UsePAM yes
|
||||
X11Forwarding no
|
||||
PrintMotd no
|
||||
AcceptEnv LANG LC_*
|
||||
Subsystem sftp /usr/lib/openssh/sftp-server
|
||||
EOF
|
||||
log "Basic SSH configuration created"
|
||||
fi
|
||||
|
||||
# Test configuration
|
||||
log "Testing SSH configuration..."
|
||||
if sshd -t; then
|
||||
log "SSH configuration is valid"
|
||||
|
||||
# Restart SSH service
|
||||
log "Restarting SSH service..."
|
||||
if systemctl restart sshd; then
|
||||
log "SSH service restarted successfully"
|
||||
|
||||
# Check if service is running
|
||||
if systemctl is-active --quiet sshd; then
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ SSH service is now running${NC}"
|
||||
echo -e "${YELLOW}You should now be able to connect via SSH${NC}"
|
||||
echo ""
|
||||
echo "Test connection with:"
|
||||
echo "ssh user@$(hostname -I | awk '{print $1}')"
|
||||
else
|
||||
error "SSH service is not active"
|
||||
fi
|
||||
else
|
||||
error "Failed to restart SSH service"
|
||||
fi
|
||||
else
|
||||
error "SSH configuration is still invalid"
|
||||
echo "Manual intervention required."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Current SSH status:"
|
||||
systemctl status sshd --no-pager -l
|
||||
609
setup.sh
609
setup.sh
@@ -18,8 +18,10 @@ CREATE_ADDITIONAL_USER=""
|
||||
ADDITIONAL_USER=""
|
||||
USE_UFW=""
|
||||
USE_FAIL2BAN=""
|
||||
DISABLE_SSH_PASSWORD=""
|
||||
SETUP_SSH_KEYS=""
|
||||
|
||||
# Track which users were created during this setup
|
||||
SYSADMIN_USER_CREATED=""
|
||||
ADDITIONAL_USER_CREATED=""
|
||||
|
||||
# Logging functions
|
||||
log() {
|
||||
@@ -51,25 +53,11 @@ check_debian() {
|
||||
|
||||
# Check for required commands
|
||||
check_commands() {
|
||||
# Check useradd (in /usr/sbin/)
|
||||
if ! command -v useradd >/dev/null 2>&1 && ! [ -x /usr/sbin/useradd ]; then
|
||||
error "useradd command not found. Please install the passwd package: apt install -y passwd"
|
||||
fi
|
||||
|
||||
# Check passwd (usually in /usr/bin/)
|
||||
if ! command -v passwd >/dev/null 2>&1 && ! [ -x /usr/bin/passwd ]; then
|
||||
error "passwd command not found. Please install the passwd package: apt install -y passwd"
|
||||
fi
|
||||
|
||||
# Check usermod (in /usr/sbin/)
|
||||
if ! command -v usermod >/dev/null 2>&1 && ! [ -x /usr/sbin/usermod ]; then
|
||||
warn "usermod command not found. Will attempt to use full path."
|
||||
fi
|
||||
|
||||
# Check sudo (usually in /usr/bin/)
|
||||
if ! command -v sudo >/dev/null 2>&1 && ! [ -x /usr/bin/sudo ]; then
|
||||
warn "sudo command not found. Will install it during system setup."
|
||||
fi
|
||||
for cmd in useradd passwd usermod; do
|
||||
if ! command -v $cmd >/dev/null 2>&1; then
|
||||
error "$cmd command not found. Please install required packages: apt install -y passwd"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Ask user about creating an additional user
|
||||
@@ -116,85 +104,28 @@ ask_additional_user() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Ask user about SSH security preferences
|
||||
ask_ssh_security() {
|
||||
echo ""
|
||||
echo -e "${BLUE}=== SSH Security Configuration ===${NC}"
|
||||
echo "This script can disable SSH password authentication for enhanced security."
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ WARNING: Disabling password authentication means you can ONLY log in with SSH keys!${NC}"
|
||||
echo "If you lose your SSH keys, you could be locked out of the server."
|
||||
echo ""
|
||||
echo -e "${YELLOW}Consider keeping password authentication if:${NC}"
|
||||
echo "• This is your first time setting up SSH keys"
|
||||
echo "• You don't have a reliable way to store SSH keys"
|
||||
echo "• You need emergency access options"
|
||||
echo ""
|
||||
read -p "Disable SSH password authentication? (y/N): " disable_password_choice
|
||||
|
||||
if [[ "$disable_password_choice" =~ ^[Yy]$ ]]; then
|
||||
DISABLE_SSH_PASSWORD="yes"
|
||||
log "SSH password authentication will be disabled"
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== SSH Key Setup ===${NC}"
|
||||
echo "Since password authentication will be disabled, you'll need SSH keys to connect."
|
||||
echo "You need to add YOUR computer's SSH public key to the server."
|
||||
echo ""
|
||||
read -p "Add your SSH public key to authorized_keys for login? (Y/n): " setup_keys_choice
|
||||
|
||||
if [[ "$setup_keys_choice" =~ ^[Nn]$ ]]; then
|
||||
SETUP_SSH_KEYS="no"
|
||||
warn "SSH keys will NOT be set up automatically"
|
||||
warn "You MUST manually add your public key to authorized_keys files after setup"
|
||||
else
|
||||
SETUP_SSH_KEYS="yes"
|
||||
log "You will be prompted to paste your SSH public key"
|
||||
fi
|
||||
else
|
||||
DISABLE_SSH_PASSWORD="no"
|
||||
SETUP_SSH_KEYS="no"
|
||||
log "SSH password authentication will remain enabled"
|
||||
|
||||
echo ""
|
||||
read -p "Still want to add your SSH public key for convenient access? (Y/n): " add_keys_choice
|
||||
if [[ ! "$add_keys_choice" =~ ^[Nn]$ ]]; then
|
||||
SETUP_SSH_KEYS="yes"
|
||||
log "You will be prompted to paste your SSH public key"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Ask user about firewall preferences
|
||||
# Ask user about firewall and security preferences
|
||||
ask_firewall_preferences() {
|
||||
echo ""
|
||||
echo -e "${BLUE}=== Firewall Configuration ===${NC}"
|
||||
echo "This script can configure UFW (Uncomplicated Firewall) or you can manage iptables manually."
|
||||
echo "UFW (Uncomplicated Firewall) provides easy firewall management."
|
||||
echo ""
|
||||
echo -e "${YELLOW}UFW vs iptables:${NC}"
|
||||
echo "• UFW: Easy to use, good for basic setups"
|
||||
echo "• Manual iptables: More control, better for complex setups (VPN servers, etc.)"
|
||||
echo ""
|
||||
read -p "Would you like to install and configure UFW? (y/N): " ufw_choice
|
||||
read -p "Install and configure UFW? (y/N): " ufw_choice
|
||||
|
||||
if [[ "$ufw_choice" =~ ^[Yy]$ ]]; then
|
||||
USE_UFW="yes"
|
||||
log "UFW will be installed and configured"
|
||||
else
|
||||
USE_UFW="no"
|
||||
log "UFW will be skipped - you can configure iptables manually"
|
||||
log "UFW will be skipped"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== Fail2ban Configuration ===${NC}"
|
||||
echo "Fail2ban protects against brute-force attacks by monitoring logs and banning IPs."
|
||||
echo "Fail2ban protects against brute-force attacks."
|
||||
echo ""
|
||||
echo -e "${YELLOW}Consider skipping fail2ban if:${NC}"
|
||||
echo "• You're running a VPN server (WireGuard, OpenVPN, etc.)"
|
||||
echo "• You have complex iptables rules"
|
||||
echo "• You prefer managing IP banning manually"
|
||||
echo ""
|
||||
read -p "Would you like to install and configure fail2ban? (Y/n): " fail2ban_choice
|
||||
read -p "Install and configure fail2ban? (Y/n): " fail2ban_choice
|
||||
|
||||
if [[ "$fail2ban_choice" =~ ^[Nn]$ ]]; then
|
||||
USE_FAIL2BAN="no"
|
||||
@@ -205,6 +136,144 @@ ask_firewall_preferences() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Ask user about SSH key setup for created users
|
||||
ask_ssh_key_setup() {
|
||||
# Check if any users were created
|
||||
local users_created=()
|
||||
|
||||
if [[ "$SYSADMIN_USER_CREATED" == "yes" ]]; then
|
||||
users_created+=("$SYSADMIN_USER")
|
||||
fi
|
||||
|
||||
if [[ "$ADDITIONAL_USER_CREATED" == "yes" ]]; then
|
||||
users_created+=("$ADDITIONAL_USER")
|
||||
fi
|
||||
|
||||
# Only prompt if users were actually created
|
||||
if [[ ${#users_created[@]} -eq 0 ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== SSH Key Setup ===${NC}"
|
||||
echo "Users created during setup: ${users_created[*]}"
|
||||
echo "You can add your SSH public key for easier login."
|
||||
echo ""
|
||||
read -p "Add your SSH public key to created users? (Y/n): " add_key_choice
|
||||
|
||||
if [[ "$add_key_choice" =~ ^[Nn]$ ]]; then
|
||||
log "SSH key setup skipped"
|
||||
return
|
||||
fi
|
||||
|
||||
local user_public_key=""
|
||||
|
||||
# Special case for user "sergio" - offer pre-defined key
|
||||
if [[ " ${users_created[*]} " =~ " sergio " ]]; then
|
||||
echo ""
|
||||
echo "Detected user 'sergio' was created."
|
||||
echo "Use pre-configured SSH key for sergio? (Y/n)"
|
||||
echo "Key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBYyuGSa2wswiiObp2qj30MoiNRyFdBIBciFSbtrkZ8 mbpm1"
|
||||
echo ""
|
||||
read -p "Use this key? (Y/n): " use_sergio_key
|
||||
|
||||
if [[ ! "$use_sergio_key" =~ ^[Nn]$ ]]; then
|
||||
user_public_key="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINBYyuGSa2wswiiObp2qj30MoiNRyFdBIBciFSbtrkZ8 mbpm1"
|
||||
log "Using pre-configured key for sergio"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If no pre-defined key was used, prompt for manual entry
|
||||
if [[ -z "$user_public_key" ]]; then
|
||||
echo ""
|
||||
echo "Please paste your SSH public key (starts with ssh-rsa, ssh-ed25519, etc.):"
|
||||
echo "You can find it with: cat ~/.ssh/id_ed25519.pub (or id_rsa.pub)"
|
||||
echo ""
|
||||
|
||||
while true; do
|
||||
read -r user_public_key
|
||||
|
||||
if [[ -z "$user_public_key" ]]; then
|
||||
echo -e "${RED}Public key cannot be empty. Please try again.${NC}"
|
||||
continue
|
||||
elif [[ "$user_public_key" =~ ^(ssh-rsa|ssh-dss|ssh-ed25519|ecdsa-sha2-) ]]; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}Invalid SSH public key format. Please ensure you copied the entire key.${NC}"
|
||||
continue
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Add key to all created users and generate SSH keys for them
|
||||
for username in "${users_created[@]}"; do
|
||||
setup_ssh_key_for_user "$username" "$user_public_key"
|
||||
generate_ssh_key_for_user "$username"
|
||||
done
|
||||
|
||||
echo ""
|
||||
log "SSH key added to: ${users_created[*]}"
|
||||
log "SSH keys generated for: ${users_created[*]}"
|
||||
}
|
||||
|
||||
setup_ssh_key_for_user() {
|
||||
local username="$1"
|
||||
local public_key="$2"
|
||||
local user_home="/home/$username"
|
||||
local ssh_dir="$user_home/.ssh"
|
||||
local authorized_keys="$ssh_dir/authorized_keys"
|
||||
|
||||
log "Setting up SSH key for user: $username"
|
||||
|
||||
# Create .ssh directory if it doesn't exist
|
||||
if [ ! -d "$ssh_dir" ]; then
|
||||
sudo -u "$username" mkdir -p "$ssh_dir"
|
||||
sudo -u "$username" chmod 700 "$ssh_dir"
|
||||
fi
|
||||
|
||||
# Check if key already exists
|
||||
if [ -f "$authorized_keys" ] && grep -Fxq "$public_key" "$authorized_keys"; then
|
||||
warn "SSH key already exists for $username"
|
||||
else
|
||||
echo "$public_key" | sudo -u "$username" tee -a "$authorized_keys" > /dev/null
|
||||
sudo -u "$username" chmod 600 "$authorized_keys"
|
||||
log "SSH key added for $username"
|
||||
fi
|
||||
}
|
||||
|
||||
generate_ssh_key_for_user() {
|
||||
local username="$1"
|
||||
local user_home="/home/$username"
|
||||
local ssh_dir="$user_home/.ssh"
|
||||
local private_key="$ssh_dir/id_ed25519"
|
||||
local public_key="$ssh_dir/id_ed25519.pub"
|
||||
|
||||
# Check if SSH key already exists
|
||||
if [[ -f "$private_key" ]]; then
|
||||
log "SSH key already exists for $username, skipping generation"
|
||||
return
|
||||
fi
|
||||
|
||||
log "Generating SSH key for user: $username"
|
||||
|
||||
# Create .ssh directory if it doesn't exist
|
||||
if [ ! -d "$ssh_dir" ]; then
|
||||
sudo -u "$username" mkdir -p "$ssh_dir"
|
||||
sudo -u "$username" chmod 700 "$ssh_dir"
|
||||
fi
|
||||
|
||||
# Generate SSH key without passphrase
|
||||
sudo -u "$username" ssh-keygen -t ed25519 -f "$private_key" -N "" -C "$username@$(hostname)"
|
||||
|
||||
# Set proper permissions
|
||||
sudo -u "$username" chmod 600 "$private_key"
|
||||
sudo -u "$username" chmod 644 "$public_key"
|
||||
|
||||
log "SSH key pair generated for $username"
|
||||
echo " Private key: $private_key"
|
||||
echo " Public key: $public_key"
|
||||
}
|
||||
|
||||
### === DEBIAN SYSTEM SETUP === ###
|
||||
setup_system() {
|
||||
log "Starting Debian 12 initial setup..."
|
||||
@@ -236,37 +305,21 @@ create_sysadmin_user() {
|
||||
|
||||
if id "$SYSADMIN_USER" &>/dev/null; then
|
||||
warn "User $SYSADMIN_USER already exists, skipping creation"
|
||||
SYSADMIN_USER_CREATED="no"
|
||||
else
|
||||
# Create user with home directory
|
||||
if command -v useradd >/dev/null 2>&1; then
|
||||
useradd -m -s /bin/bash "$SYSADMIN_USER"
|
||||
elif [ -x /usr/sbin/useradd ]; then
|
||||
/usr/sbin/useradd -m -s /bin/bash "$SYSADMIN_USER"
|
||||
else
|
||||
error "useradd command not found. Please install the passwd package."
|
||||
fi
|
||||
useradd -m -s /bin/bash "$SYSADMIN_USER"
|
||||
log "User $SYSADMIN_USER created successfully"
|
||||
SYSADMIN_USER_CREATED="yes"
|
||||
|
||||
# Set password for sysadmin user
|
||||
echo "Please set a password for user $SYSADMIN_USER:"
|
||||
if command -v passwd >/dev/null 2>&1; then
|
||||
passwd "$SYSADMIN_USER"
|
||||
elif [ -x /usr/bin/passwd ]; then
|
||||
/usr/bin/passwd "$SYSADMIN_USER"
|
||||
else
|
||||
error "passwd command not found. Please install the passwd package."
|
||||
fi
|
||||
passwd "$SYSADMIN_USER"
|
||||
fi
|
||||
|
||||
# Add sysadmin to sudo group
|
||||
log "Adding $SYSADMIN_USER to sudo group..."
|
||||
if command -v usermod >/dev/null 2>&1; then
|
||||
usermod -aG sudo "$SYSADMIN_USER"
|
||||
elif [ -x /usr/sbin/usermod ]; then
|
||||
/usr/sbin/usermod -aG sudo "$SYSADMIN_USER"
|
||||
else
|
||||
error "usermod command not found. Please install the passwd package."
|
||||
fi
|
||||
usermod -aG sudo "$SYSADMIN_USER"
|
||||
}
|
||||
|
||||
create_additional_user() {
|
||||
@@ -275,37 +328,21 @@ create_additional_user() {
|
||||
|
||||
if id "$ADDITIONAL_USER" &>/dev/null; then
|
||||
warn "User $ADDITIONAL_USER already exists, skipping creation"
|
||||
ADDITIONAL_USER_CREATED="no"
|
||||
else
|
||||
# Create user with home directory
|
||||
if command -v useradd >/dev/null 2>&1; then
|
||||
useradd -m -s /bin/bash "$ADDITIONAL_USER"
|
||||
elif [ -x /usr/sbin/useradd ]; then
|
||||
/usr/sbin/useradd -m -s /bin/bash "$ADDITIONAL_USER"
|
||||
else
|
||||
error "useradd command not found. Please install the passwd package."
|
||||
fi
|
||||
useradd -m -s /bin/bash "$ADDITIONAL_USER"
|
||||
log "User $ADDITIONAL_USER created successfully"
|
||||
ADDITIONAL_USER_CREATED="yes"
|
||||
|
||||
# Set password for additional user
|
||||
echo "Please set a password for user $ADDITIONAL_USER:"
|
||||
if command -v passwd >/dev/null 2>&1; then
|
||||
passwd "$ADDITIONAL_USER"
|
||||
elif [ -x /usr/bin/passwd ]; then
|
||||
/usr/bin/passwd "$ADDITIONAL_USER"
|
||||
else
|
||||
error "passwd command not found. Please install the passwd package."
|
||||
fi
|
||||
passwd "$ADDITIONAL_USER"
|
||||
fi
|
||||
|
||||
# Add additional user to sudo group
|
||||
log "Adding $ADDITIONAL_USER to sudo group..."
|
||||
if command -v usermod >/dev/null 2>&1; then
|
||||
usermod -aG sudo "$ADDITIONAL_USER"
|
||||
elif [ -x /usr/sbin/usermod ]; then
|
||||
/usr/sbin/usermod -aG sudo "$ADDITIONAL_USER"
|
||||
else
|
||||
error "usermod command not found. Please install the passwd package."
|
||||
fi
|
||||
usermod -aG sudo "$ADDITIONAL_USER"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -315,20 +352,11 @@ configure_security() {
|
||||
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
|
||||
|
||||
# Configure SSH settings safely
|
||||
# Configure SSH settings
|
||||
log "Applying SSH security settings..."
|
||||
|
||||
# Backup original sshd_config
|
||||
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Configure PasswordAuthentication
|
||||
if [[ "$DISABLE_SSH_PASSWORD" == "yes" ]]; then
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
|
||||
log "SSH password authentication disabled"
|
||||
else
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||
log "SSH password authentication enabled"
|
||||
fi
|
||||
# Configure basic SSH security - enable password auth by default for safety
|
||||
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
|
||||
|
||||
# Configure other SSH settings more safely
|
||||
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
|
||||
@@ -357,25 +385,17 @@ configure_security() {
|
||||
echo "AllowUsers $SYSADMIN_USER" >> /etc/ssh/sshd_config
|
||||
fi
|
||||
|
||||
# Test SSH configuration before proceeding
|
||||
# Test SSH configuration
|
||||
log "Testing SSH configuration..."
|
||||
if ! sshd -t; then
|
||||
error "SSH configuration is invalid! Restoring backup..."
|
||||
mv /etc/ssh/sshd_config.backup.$(date +%Y%m%d_%H%M%S) /etc/ssh/sshd_config
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "SSH configuration is valid"
|
||||
sshd -t || error "SSH configuration is invalid!"
|
||||
|
||||
# Remove/lock root password
|
||||
log "Locking root password..."
|
||||
passwd -l root
|
||||
|
||||
# Configure firewall based on user choice
|
||||
# Configure firewall if requested
|
||||
if [[ "$USE_UFW" == "yes" ]]; then
|
||||
configure_ufw
|
||||
else
|
||||
configure_basic_iptables
|
||||
fi
|
||||
|
||||
# Configure fail2ban if requested
|
||||
@@ -439,71 +459,21 @@ configure_ufw() {
|
||||
ufw status verbose
|
||||
}
|
||||
|
||||
configure_basic_iptables() {
|
||||
log "Setting up basic iptables rules..."
|
||||
|
||||
# Create a simple script for basic iptables rules
|
||||
cat > /etc/iptables-basic.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
# Basic iptables rules for SSH, HTTP, HTTPS
|
||||
|
||||
# Flush existing rules
|
||||
iptables -F
|
||||
iptables -X
|
||||
iptables -t nat -F
|
||||
iptables -t nat -X
|
||||
iptables -t mangle -F
|
||||
iptables -t mangle -X
|
||||
|
||||
# Set default policies
|
||||
iptables -P INPUT DROP
|
||||
iptables -P FORWARD DROP
|
||||
iptables -P OUTPUT ACCEPT
|
||||
|
||||
# Allow loopback
|
||||
iptables -A INPUT -i lo -j ACCEPT
|
||||
iptables -A OUTPUT -o lo -j ACCEPT
|
||||
|
||||
# Allow established and related connections
|
||||
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
|
||||
# Allow SSH (port 22)
|
||||
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
|
||||
|
||||
# Allow HTTP (port 80)
|
||||
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
|
||||
|
||||
# Allow HTTPS (port 443)
|
||||
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
|
||||
|
||||
# Save rules
|
||||
iptables-save > /etc/iptables/rules.v4
|
||||
EOF
|
||||
|
||||
chmod +x /etc/iptables-basic.sh
|
||||
|
||||
# Create iptables directory if it doesn't exist
|
||||
mkdir -p /etc/iptables
|
||||
|
||||
# Run the basic rules script
|
||||
/etc/iptables-basic.sh
|
||||
|
||||
# Install iptables-persistent to make rules persistent
|
||||
apt install -y iptables-persistent
|
||||
|
||||
log "Basic iptables rules applied and saved"
|
||||
warn "You can customize /etc/iptables-basic.sh and run it to update rules"
|
||||
warn "Current rules are saved in /etc/iptables/rules.v4"
|
||||
}
|
||||
|
||||
configure_fail2ban() {
|
||||
if [[ "$USE_FAIL2BAN" == "yes" ]]; then
|
||||
log "Configuring fail2ban..."
|
||||
cat > /etc/fail2ban/jail.local << EOF
|
||||
|
||||
# Ensure fail2ban directories exist
|
||||
mkdir -p /etc/fail2ban/jail.d
|
||||
|
||||
# Create configuration in jail.d instead of overwriting jail.local
|
||||
cat > /etc/fail2ban/jail.d/custom.conf << EOF
|
||||
[DEFAULT]
|
||||
bantime = 1h
|
||||
findtime = 10m
|
||||
maxretry = 3
|
||||
ignoreip = 127.0.0.1/8 ::1
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
@@ -514,128 +484,35 @@ maxretry = 3
|
||||
bantime = 1h
|
||||
EOF
|
||||
|
||||
# Start and enable fail2ban
|
||||
# Verify log file exists
|
||||
if [[ ! -f /var/log/auth.log ]]; then
|
||||
warn "Auth log file doesn't exist yet, creating it..."
|
||||
touch /var/log/auth.log
|
||||
chmod 640 /var/log/auth.log
|
||||
fi
|
||||
|
||||
# Start and enable fail2ban with error handling
|
||||
systemctl enable fail2ban
|
||||
systemctl start fail2ban
|
||||
|
||||
log "Fail2ban configured and started"
|
||||
else
|
||||
# Remove/disable fail2ban if user chose not to use it
|
||||
if systemctl is-active --quiet fail2ban; then
|
||||
log "Stopping and disabling fail2ban..."
|
||||
systemctl stop fail2ban
|
||||
systemctl disable fail2ban
|
||||
# Give a moment for systemd to process
|
||||
sleep 2
|
||||
|
||||
if systemctl start fail2ban; then
|
||||
# Verify it's actually running
|
||||
if systemctl is-active --quiet fail2ban; then
|
||||
log "Fail2ban configured and started successfully"
|
||||
# Show status briefly
|
||||
systemctl status fail2ban --no-pager --lines=3
|
||||
else
|
||||
warn "Fail2ban started but may have issues. Check: systemctl status fail2ban"
|
||||
fi
|
||||
else
|
||||
error "Failed to start fail2ban service"
|
||||
fi
|
||||
|
||||
if dpkg -l | grep -q fail2ban; then
|
||||
log "Removing fail2ban package..."
|
||||
apt remove --purge -y fail2ban
|
||||
apt autoremove -y
|
||||
fi
|
||||
|
||||
log "Fail2ban has been removed/disabled"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
### === SSH KEY SETUP === ###
|
||||
setup_user_ssh_keys() {
|
||||
if [[ "$SETUP_SSH_KEYS" == "no" ]]; then
|
||||
log "SSH key setup skipped"
|
||||
return
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== SSH Public Key Setup ===${NC}"
|
||||
echo "To set up SSH key authentication, you need to provide your SSH public key."
|
||||
echo "You can find your public key on your computer by running:"
|
||||
echo -e "${YELLOW} cat ~/.ssh/id_rsa.pub${NC}"
|
||||
echo -e "${YELLOW} # or${NC}"
|
||||
echo -e "${YELLOW} cat ~/.ssh/id_ed25519.pub${NC}"
|
||||
echo ""
|
||||
echo "If you don't have an SSH key pair, generate one on your computer first:"
|
||||
echo -e "${YELLOW} ssh-keygen -t ed25519 -C \"your_email@example.com\"${NC}"
|
||||
echo ""
|
||||
|
||||
while true; do
|
||||
echo "Please paste your SSH public key (starts with ssh-rsa, ssh-ed25519, etc.):"
|
||||
read -r user_public_key
|
||||
|
||||
if [[ -z "$user_public_key" ]]; then
|
||||
echo -e "${RED}Public key cannot be empty. Please try again.${NC}"
|
||||
continue
|
||||
elif [[ "$user_public_key" =~ ^(ssh-rsa|ssh-dss|ssh-ed25519|ecdsa-sha2-) ]]; then
|
||||
break
|
||||
else
|
||||
echo -e "${RED}Invalid SSH public key format. Please ensure you copied the entire key.${NC}"
|
||||
continue
|
||||
fi
|
||||
done
|
||||
|
||||
# Add SSH key to sysadmin user
|
||||
setup_ssh_key_for_user "$SYSADMIN_USER" "$user_public_key"
|
||||
|
||||
# Add SSH key to additional user if created
|
||||
if [[ "$CREATE_ADDITIONAL_USER" == "yes" && -n "$ADDITIONAL_USER" ]]; then
|
||||
setup_ssh_key_for_user "$ADDITIONAL_USER" "$user_public_key"
|
||||
fi
|
||||
}
|
||||
|
||||
setup_ssh_key_for_user() {
|
||||
local username="$1"
|
||||
local public_key="$2"
|
||||
local user_home="/home/$username"
|
||||
local ssh_dir="$user_home/.ssh"
|
||||
local authorized_keys="$ssh_dir/authorized_keys"
|
||||
|
||||
log "Setting up SSH key for user: $username"
|
||||
|
||||
# Create .ssh directory for user if it doesn't exist
|
||||
if [ ! -d "$ssh_dir" ]; then
|
||||
sudo -u "$username" mkdir -p "$ssh_dir"
|
||||
sudo -u "$username" chmod 700 "$ssh_dir"
|
||||
fi
|
||||
|
||||
# Add public key to authorized_keys
|
||||
log "Adding public key to authorized_keys for $username..."
|
||||
|
||||
# Check if key already exists in authorized_keys
|
||||
if [ -f "$authorized_keys" ] && grep -Fxq "$public_key" "$authorized_keys"; then
|
||||
warn "SSH key already exists in authorized_keys for $username"
|
||||
else
|
||||
echo "$public_key" | sudo -u "$username" tee -a "$authorized_keys" > /dev/null
|
||||
sudo -u "$username" chmod 600 "$authorized_keys"
|
||||
log "Public key added to authorized_keys for $username"
|
||||
fi
|
||||
}
|
||||
|
||||
show_ssh_setup_summary() {
|
||||
if [[ "$SETUP_SSH_KEYS" == "yes" ]]; then
|
||||
echo ""
|
||||
echo -e "${GREEN}✓ SSH key authentication has been set up for:${NC}"
|
||||
echo " - User: $SYSADMIN_USER"
|
||||
if [[ "$CREATE_ADDITIONAL_USER" == "yes" && -n "$ADDITIONAL_USER" ]]; then
|
||||
echo " - User: $ADDITIONAL_USER"
|
||||
fi
|
||||
echo ""
|
||||
echo -e "${YELLOW}Your SSH public key has been added to authorized_keys files.${NC}"
|
||||
echo "You can now connect using your SSH private key."
|
||||
elif [[ "$DISABLE_SSH_PASSWORD" == "yes" ]]; then
|
||||
echo ""
|
||||
echo -e "${RED}⚠️ SSH password authentication is DISABLED${NC}"
|
||||
echo -e "${YELLOW}You MUST add your SSH public key manually:${NC}"
|
||||
echo ""
|
||||
echo "1. On your computer, get your public key:"
|
||||
echo " cat ~/.ssh/id_ed25519.pub"
|
||||
echo ""
|
||||
echo "2. Add it to the server's authorized_keys:"
|
||||
echo " echo 'YOUR_PUBLIC_KEY' >> /home/$SYSADMIN_USER/.ssh/authorized_keys"
|
||||
if [[ "$CREATE_ADDITIONAL_USER" == "yes" && -n "$ADDITIONAL_USER" ]]; then
|
||||
echo " echo 'YOUR_PUBLIC_KEY' >> /home/$ADDITIONAL_USER/.ssh/authorized_keys"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
### === CLEANUP AND FINALIZATION === ###
|
||||
@@ -657,70 +534,44 @@ finalize_setup() {
|
||||
|
||||
log "SSH service restarted successfully"
|
||||
|
||||
# Download customization script for sysadmin user
|
||||
log "Downloading customization script..."
|
||||
if wget -O /home/$SYSADMIN_USER/costumize.sh "https://git.del-c.net/Del-c.net/debian-first-boot-setup/raw/branch/main/costumize.sh"; then
|
||||
chmod +x /home/$SYSADMIN_USER/costumize.sh
|
||||
chown $SYSADMIN_USER:$SYSADMIN_USER /home/$SYSADMIN_USER/costumize.sh
|
||||
log "Customization script downloaded to /home/$SYSADMIN_USER/costumize.sh"
|
||||
else
|
||||
warn "Failed to download customization script"
|
||||
fi
|
||||
|
||||
# Clean up
|
||||
log "Cleaning up..."
|
||||
apt autoremove -y
|
||||
apt autoclean
|
||||
|
||||
# Final security check
|
||||
log "Final system status:"
|
||||
echo "================================"
|
||||
|
||||
if [[ "$USE_UFW" == "yes" ]]; then
|
||||
echo "UFW Status:"
|
||||
ufw status
|
||||
else
|
||||
echo "Iptables Status:"
|
||||
iptables -L -n | head -20
|
||||
fi
|
||||
|
||||
echo "================================"
|
||||
echo "SSH Configuration:"
|
||||
grep -E "PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|AllowUsers" /etc/ssh/sshd_config
|
||||
echo "================================"
|
||||
|
||||
if [[ "$USE_FAIL2BAN" == "yes" ]]; then
|
||||
echo "Fail2ban Status:"
|
||||
systemctl status fail2ban --no-pager -l
|
||||
echo "================================"
|
||||
fi
|
||||
|
||||
echo "Sudo users:"
|
||||
grep -E "sudo|wheel" /etc/group
|
||||
echo "================================"
|
||||
|
||||
log "Setup completed successfully!"
|
||||
echo ""
|
||||
echo -e "${BLUE}=== IMPORTANT NOTES ===${NC}"
|
||||
echo -e "${YELLOW}1. Root SSH login is now DISABLED${NC}"
|
||||
echo -e "${YELLOW}2. Root password is LOCKED${NC}"
|
||||
echo -e "${YELLOW}3. SSH password authentication is DISABLED${NC}"
|
||||
echo -e "${YELLOW}4. Use '$SYSADMIN_USER' user with SSH key to connect${NC}"
|
||||
echo -e "${BLUE}=== SETUP SUMMARY ===${NC}"
|
||||
echo -e "${YELLOW}• Root SSH login: DISABLED${NC}"
|
||||
echo -e "${YELLOW}• Root password: LOCKED${NC}"
|
||||
echo -e "${YELLOW}• Main user: $SYSADMIN_USER (sudo access)${NC}"
|
||||
|
||||
if [[ "$CREATE_ADDITIONAL_USER" == "yes" && -n "$ADDITIONAL_USER" ]]; then
|
||||
echo -e "${YELLOW}• Additional user: $ADDITIONAL_USER (sudo access)${NC}"
|
||||
fi
|
||||
|
||||
if [[ "$USE_UFW" == "yes" ]]; then
|
||||
echo -e "${YELLOW}5. UFW firewall is active (SSH, HTTP, HTTPS allowed)${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}5. Basic iptables rules are active (SSH, HTTP, HTTPS allowed)${NC}"
|
||||
echo -e "${YELLOW} You can customize /etc/iptables-basic.sh for additional rules${NC}"
|
||||
echo -e "${YELLOW}• UFW firewall: ENABLED (SSH, HTTP, HTTPS)${NC}"
|
||||
fi
|
||||
|
||||
local note_number=6
|
||||
if [[ "$USE_FAIL2BAN" == "yes" ]]; then
|
||||
echo -e "${YELLOW}$note_number. Fail2ban is protecting SSH${NC}"
|
||||
((note_number++))
|
||||
else
|
||||
echo -e "${YELLOW}$note_number. Consider implementing IP banning manually if needed${NC}"
|
||||
((note_number++))
|
||||
echo -e "${YELLOW}• Fail2ban: ENABLED (SSH protection)${NC}"
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}$note_number. Automatic security updates are enabled${NC}"
|
||||
((note_number++))
|
||||
echo -e "${YELLOW}$note_number. SSH keys generated for both $SYSADMIN_USER and root users${NC}"
|
||||
|
||||
echo -e "${YELLOW}• Automatic security updates: ENABLED${NC}"
|
||||
echo ""
|
||||
echo -e "${RED}REBOOT RECOMMENDED${NC}"
|
||||
echo ""
|
||||
echo "To connect: ssh $SYSADMIN_USER@$(hostname -I | awk '{print $1}')"
|
||||
echo -e "${GREEN}Connect with: ssh $SYSADMIN_USER@$(hostname -I | awk '{print $1}')${NC}"
|
||||
echo -e "${YELLOW}Reboot recommended${NC}"
|
||||
}
|
||||
|
||||
### === MAIN === ###
|
||||
@@ -731,11 +582,11 @@ main() {
|
||||
check_commands
|
||||
|
||||
echo -e "${BLUE}=== Debian 12 Initial Setup ===${NC}"
|
||||
echo "This script will:"
|
||||
echo "1. Set up a secure Debian 12 system"
|
||||
echo "2. Create a sysadmin user with SSH key authentication"
|
||||
echo "3. Optionally create an additional user account"
|
||||
echo "4. Generate SSH keys for all created users and root"
|
||||
echo "This script will set up a secure Debian 12 system with:"
|
||||
echo "• Sysadmin user with sudo access"
|
||||
echo "• Optional additional user"
|
||||
echo "• SSH security hardening"
|
||||
echo "• Optional UFW firewall and fail2ban"
|
||||
echo ""
|
||||
read -p "Continue? (y/N): " confirm
|
||||
|
||||
@@ -746,18 +597,18 @@ main() {
|
||||
|
||||
# Ask for user and security preferences
|
||||
ask_additional_user
|
||||
ask_ssh_security
|
||||
ask_firewall_preferences
|
||||
|
||||
# System setup
|
||||
setup_system
|
||||
create_sysadmin_user
|
||||
create_additional_user
|
||||
|
||||
# SSH key setup for created users
|
||||
ask_ssh_key_setup
|
||||
|
||||
configure_security
|
||||
|
||||
# SSH key setup
|
||||
setup_user_ssh_keys
|
||||
show_ssh_setup_summary
|
||||
|
||||
# Finalize
|
||||
finalize_setup
|
||||
|
||||
Reference in New Issue
Block a user