du_setup/guide.md

379 lines
18 KiB
Markdown
Raw Normal View History

2025-06-30 22:44:28 +01:00
### **Setup**
- **Environment**: A fresh VM running **Ubuntu 22.04 LTS** (a supported OS) with:
- Root privileges (`sudo` or direct root access).
- Internet connectivity (for package downloads and Tailscale).
- At least 2GB free disk space (for swap and temporary files).
- Minimal installation (no prior SSH hardening, UFW, or Fail2Ban configured).
- **Script Version**: v0.52
- **Execution Mode**: Interactive (not `--quiet`), to capture user prompts and verify decision points.
- **Inputs**: Ill provide sample inputs for prompts (e.g., username, hostname, SSH port) to simulate a realistic run.
- **Verification**: Ill check each functions logic, validate outputs against the README, and highlight any potential runtime errors or edge cases.
---
### **Walkthrough**
#### **1. Preparation**
- **Download and Permissions**:
- The README instructs downloading with `wget https://raw.githubusercontent.com/buildplan/du_setup/refs/heads/main/du_setup.sh` and setting `chmod +x du_setup.sh`.
- Assumed command: `sudo ./du_setup.sh`.
- The script starts with `#!/bin/bash` and `set -euo pipefail`, ensuring strict error handling.
- **Log File Creation**:
- The script creates `/var/log/du_setup_$(date +%Y%m%d_%H%M%S).log` (e.g., `/var/log/du_setup_20250630_222800.log`) with `chmod 600`.
- Backup directory `/root/setup_harden_backup_20250630_222800` is created with `chmod 700`.
#### **2. Main Function Execution**
##### **check_dependencies**
- **Logic**: Checks for `curl`, `sudo`, and `gpg`. Installs missing dependencies via `apt-get`.
- **Simulation**:
- On a fresh Ubuntu 22.04 VM, `sudo` and `curl` are typically present, but `gpg` might be missing in minimal installs.
- The script runs `apt-get install -y -qq gpg` if needed, which should succeed given internet access.
- **Expected Output**: `✓ All essential dependencies are installed.` (or installs `gpg` if missing).
- **Potential Issues**: None likely, as `apt-get update` and `install` are robust, and internet is assumed available.
##### **check_system**
- **Logic**: Verifies root privileges, OS compatibility (Ubuntu 22.04), internet connectivity, SSH service, and `/var/log` writability.
- **Simulation**:
- Root check: `id -u` returns 0 (root), passes.
- OS check: `/etc/os-release` confirms `ID=ubuntu`, `VERSION_ID=22.04`, passes.
- Container check: No container detected (`/proc/1/cgroup` lacks docker/lxc/kubepod), so `IS_CONTAINER=false`.
- SSH check: Assumes `openssh-server` is installed (common in Ubuntu server). Detects `ssh.service` or `sshd.service`.
- Internet check: `curl -s --head https://archive.ubuntu.com` succeeds.
- `/var/log` and `/etc/shadow` checks: Permissions are correct (640 for `/etc/shadow`, writable `/var/log`).
- **Expected Output**:
```
✓ Running with root privileges.
✓ Compatible OS detected: Ubuntu 22.04 LTS
✓ Internet connectivity confirmed.
```
- **Potential Issues**: If `openssh-server` is missing, the script installs it later in `install_packages`. No issues expected.
##### **collect_config**
- **Logic**: Prompts for username, hostname, pretty hostname, and SSH port. Validates inputs.
- **Simulation Inputs**:
- Username: `adminuser` (valid, passes `validate_username`).
- Hostname: `myserver` (valid, passes `validate_hostname`).
- Pretty hostname: `My Server` (optional, accepted).
- SSH port: `2222` (default, passes `validate_port`).
- Server IP: Detected via `curl -s https://ifconfig.me` (e.g., `192.0.2.1`).
- Confirmation: User confirms the configuration.
- **Expected Output**:
```
Configuration Summary:
Username: adminuser
Hostname: myserver
SSH Port: 2222
Server IP: 192.0.2.1
Continue with this configuration? [Y/n]: y
```
- **Log Entry**: `Configuration collected: USER=adminuser, HOST=myserver, PORT=2222`
- **Potential Issues**: Invalid inputs (e.g., username with spaces) prompt re-entry, which is robust. No issues expected.
##### **install_packages**
- **Logic**: Updates and upgrades packages, installs essentials (`ufw`, `fail2ban`, `chrony`, `rsync`, etc.).
- **Simulation**:
- `apt-get update` and `apt-get upgrade -y` run silently.
- Installs packages like `ufw`, `fail2ban`, `chrony`, `rsync`, `openssh-server`, etc.
- Assumes sufficient disk space and internet access.
- **Expected Output**: `✓ Essential packages installed.`
- **Potential Issues**: Rare chance of `apt-get` failures due to repository issues, but `set -e` ensures the script exits on error. No issues expected in a fresh VM.
##### **setup_user**
- **Logic**: Creates `adminuser` if it doesnt exist, sets a password (or skips for key-only), adds to `sudo` group, and configures SSH keys.
- **Simulation**:
- User `adminuser` doesnt exist, so `adduser --disabled-password --gecos "" adminuser` runs.
- Password prompt: User enters `securepassword123` twice, set via `chpasswd`.
- SSH key prompt: User pastes a valid key (`ssh-ed25519 AAAAC3Nza... user@local`).
- Key is added to `/home/adminuser/.ssh/authorized_keys` with `chmod 600` and `chown adminuser:adminuser`.
- Adds `adminuser` to `sudo` group with `usermod -aG sudo adminuser`.
- **Expected Output**:
```
✓ User 'adminuser' created.
✓ SSH public key added.
✓ User added to sudo group.
✓ Sudo group membership confirmed for 'adminuser'.
```
- **Potential Issues**: Password mismatch prompts re-entry. If key is invalid, user is prompted again. Robust validation prevents issues.
##### **configure_system**
- **Logic**: Sets timezone, hostname, and optionally configures locales. Backs up `/etc/hosts`, `/etc/fstab`, `/etc/sysctl.conf`.
- **Simulation**:
- Timezone: User enters `America/New_York`, validated via `/usr/share/zoneinfo`.
- Locale configuration: User skips (`dpkg-reconfigure locales` not run).
- Hostname: Sets `myserver` and pretty name `My Server` via `hostnamectl`.
- Updates `/etc/hosts` with `127.0.1.1 myserver`.
- **Expected Output**:
```
✓ Timezone set to America/New_York.
✓ Hostname configured: myserver
```
- **Potential Issues**: Invalid timezone prompts re-entry. No issues expected.
##### **configure_ssh**
- **Logic**: Hardens SSH by setting a custom port (2222), disabling root login, enforcing key-based auth, and creating `/etc/issue.net`. Includes rollback on failure.
- **Simulation**:
- Detects `ssh.service` (Ubuntu 22.04).
- Current port: 22 (default).
- Backs up `/etc/ssh/sshd_config` to `/root/setup_harden_backup_20250630_222800/sshd_config.backup_*`.
- Sets port 2222 in `/etc/ssh/sshd_config` (Ubuntu 22.04 uses direct config).
- Creates `/etc/ssh/sshd_config.d/99-hardening.conf` with:
```
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
X11Forwarding no
PrintMotd no
Banner /etc/issue.net
```
- Creates `/etc/issue.net` with a warning banner.
- Restarts `ssh.service` and verifies port 2222 with `ss -tuln`.
- User tests SSH: `ssh -p 2222 adminuser@192.0.2.1` (assumed successful).
- Verifies root login is disabled with `ssh -p 2222 root@localhost` (fails, as expected).
- **Expected Output**:
```
✓ SSH service restarted on port 2222.
✓ Confirmed: Root SSH login is disabled.
✓ SSH hardening confirmed and finalized.
```
- **Potential Issues**: If the user fails to test SSH on port 2222, the script rolls back to port 22. The `trap` ensures rollback on errors. No issues expected with correct user input.
##### **configure_firewall**
- **Logic**: Configures UFW with deny incoming, allow outgoing, and specific ports (2222/tcp, optional 80/tcp, 443/tcp, 41641/udp).
- **Simulation**:
- UFW is inactive initially.
- Sets `ufw default deny incoming`, `ufw default allow outgoing`.
- Allows `2222/tcp` (SSH).
- User allows HTTP (80/tcp) and HTTPS (443/tcp), skips Tailscale (41641/udp) and custom ports.
- Enables UFW with `ufw --force enable`.
- **Expected Output**:
```
✓ HTTP traffic allowed.
✓ HTTPS traffic allowed.
✓ Firewall is active.
Status: active
To Action From
-- ------ ----
2222/tcp (Custom SSH) ALLOW Anywhere
80/tcp (HTTP) ALLOW Anywhere
443/tcp (HTTPS) ALLOW Anywhere
```
- **Potential Issues**: If the VPS providers firewall blocks port 2222, the user is warned to check. UFW enable failure is caught by `set -e`. No issues expected.
##### **configure_fail2ban**
- **Logic**: Configures Fail2Ban to monitor SSH on port 2222 with `bantime=1h`, `findtime=10m`, `maxretry=3`.
- **Simulation**:
- Creates `/etc/fail2ban/jail.local` with:
```
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 3
backend = auto
[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s
```
- Enables and restarts `fail2ban`.
- **Expected Output**:
```
✓ Fail2Ban is active and monitoring port(s) 2222.
Status: sshd
```
- **Potential Issues**: Fail2Ban service failure is caught and exits the script. No issues expected.
##### **configure_auto_updates**
- **Logic**: Configures `unattended-upgrades` for automatic security updates.
- **Simulation**:
- User confirms enabling auto-updates.
- Sets `unattended-upgrades/enable_auto_updates` to `true` and runs `dpkg-reconfigure`.
- **Expected Output**: `✓ Automatic security updates enabled.`
- **Potential Issues**: Package is already installed via `install_packages`. No issues expected.
##### **configure_time_sync**
- **Logic**: Enables and verifies `chrony` for time synchronization.
- **Simulation**:
- `systemctl enable --now chrony` runs.
- `chronyc tracking` confirms synchronization.
- **Expected Output**:
```
✓ Chrony is active for time synchronization.
Reference ID : 192.168.1.1 (time.example.com)
Stratum : 2
...
```
- **Potential Issues**: Chrony failure is caught and exits. No issues expected.
##### **install_docker**
- **Logic**: Installs Docker if user confirms, adds `adminuser` to `docker` group, and runs a `hello-world` test.
- **Simulation**:
- User confirms Docker installation.
- Removes old runtimes, adds Docker GPG key and repository, installs `docker-ce`, `docker-ce-cli`, etc.
- Configures `/etc/docker/daemon.json` with log settings.
- Adds `adminuser` to `docker` group.
- Runs `docker run --rm hello-world` as `adminuser`.
- **Expected Output**:
```
✓ Docker sanity check passed.
NOTE: 'adminuser' must log out and back in to use Docker without sudo.
```
- **Potential Issues**: Docker repository issues are caught by `set -e`. No issues expected with internet access.
##### **install_tailscale**
- **Logic**: Installs Tailscale if confirmed, connects using a pre-auth key, and applies optional flags.
- **Simulation**:
- User confirms Tailscale installation.
- Chooses standard Tailscale (option 1).
- Enters key: `tskey-auth-xyz123`.
- Skips additional flags ( `--ssh`, `--advertise-exit-node`, etc.).
- Runs `tailscale up --auth-key=tskey-auth-xyz123 --operator=adminuser`.
- Verifies connection with `tailscale ip` (e.g., `100.64.0.1`).
- **Expected Output**:
```
✓ Tailscale connected successfully. Node IPv4 in tailnet: 100.64.0.1
```
- **Potential Issues**: Invalid key or network issues are logged to `/tmp/tailscale_status.txt`. Retries (3x) mitigate transient failures. Assumed success for simulation.
##### **setup_backup**
- **Logic**: Configures rsync backups over SSH with optional notifications and a test backup.
- **Simulation**:
- User confirms backup setup.
- Backup destination: `u12345@u12345.your-storagebox.de`.
- Port: `23` (Hetzner).
- Remote path: `/home/backups/`.
- Hetzner mode: Enabled (uses `-s` for `ssh-copy-id`).
- Key copy: Manual (user runs `ssh-copy-id -p 23 -i /root/.ssh/id_ed25519.pub -s u12345@u12345.your-storagebox.de`).
- Creates `/root/.ssh/id_ed25519` if missing.
- Creates `/root/rsync_exclude.txt` with defaults.
- Cron schedule: `5 3 * * *` (daily at 3:05 AM).
- Notifications: Skipped.
- Test backup: User confirms, creates `/root/test_backup_*`, runs `rsync` to `u12345@u12345.your-storagebox.de:/home/backups/test_backup/`.
- **Expected Output**:
```
✓ Root SSH key generated at /root/.ssh/id_ed25519
ACTION REQUIRED: Copy the root SSH key to the backup destination.
The root user's public key is: ssh-ed25519 AAAAC3Nza... root@myserver
Run the following command: ssh-copy-id -p "23" -i "/root/.ssh/id_ed25519.pub" -s "u12345@u12345.your-storagebox.de"
✓ Rsync exclude file created.
✓ Test backup successful! Check /var/log/backup_rsync.log for details.
✓ Backup cron job scheduled: 5 3 * * *
```
- **Potential Issues**: If the SSH key isnt copied, the test backup fails, logged to `/var/log/backup_rsync.log`. Manual copy instructions are clear. No issues expected with correct setup.
##### **configure_swap**
- **Logic**: Configures a swap file if confirmed, with default size 2G.
- **Simulation**:
- User confirms swap creation.
- Size: `2G`.
- Disk space check: Assumes >2GB available.
- Creates `/swapfile` with `fallocate`, `chmod 600`, `mkswap`, `swapon`.
- Adds `/swapfile none swap sw 0 0` to `/etc/fstab`.
- Sets `vm.swappiness=10`, `vm.vfs_cache_pressure=50` in `/etc/sysctl.d/99-swap.conf`.
- **Expected Output**:
```
✓ Swap file created: 2G
✓ Swap entry added to /etc/fstab.
✓ Swap settings applied to /etc/sysctl.d/99-swap.conf.
NAME TYPE SIZE USED PRIO
/swapfile file 2G 0B -2
```
- **Potential Issues**: Insufficient disk space exits the script. No issues expected.
##### **configure_security_audit**
- **Logic**: Runs Lynis and (on Debian) debsecan if confirmed.
- **Simulation**:
- User confirms audit.
- Installs `lynis`, runs `lynis audit system --quick`.
- Skips debsecan (Ubuntu 22.04, not supported).
- Logs to `/var/log/setup_harden_security_audit_20250630_222800.log`.
- Extracts hardening index (e.g., `75`).
- **Expected Output**:
```
✓ Lynis audit completed. Check /var/log/setup_harden_security_audit_20250630_222800.log for details.
debsecan is not supported on Ubuntu. Skipping debsecan audit.
```
- **Potential Issues**: Lynis failure is logged and doesnt exit the script. No issues expected.
##### **final_cleanup**
- **Logic**: Runs `apt-get update`, `upgrade`, `autoremove`, `autoclean`, and reloads daemons.
- **Simulation**: All commands succeed.
- **Expected Output**: `✓ Final system update and cleanup complete.`
- **Potential Issues**: Repository issues are logged as warnings, not fatal. No issues expected.
##### **generate_summary**
- **Logic**: Summarizes configuration, checks service status, and provides verification steps.
- **Simulation**:
- Services (`ssh.service`, `fail2ban`, `chrony`, `ufw`, `docker`, `tailscaled`) are active.
- Backup is configured, test successful.
- Tailscale is connected (IP: `100.64.0.1`).
- Audit ran, hardening index: `75`, debsecan: `Not supported on Ubuntu`.
- **Expected Output**:
```
Setup Complete!
✓ Service ssh.service is active.
✓ Service fail2ban is active.
✓ Service chrony is active.
✓ Service ufw is active.
✓ Service docker is active.
✓ Service tailscaled is active and connected.
✓ Security audit performed.
Configuration Summary:
Admin User: adminuser
Hostname: myserver
SSH Port: 2222
Server IP: 192.0.2.1
Remote Backup: Enabled
- Backup Script: /root/run_backup.sh
- Destination: u12345@u12345.your-storagebox.de
- SSH Port: 23
- Remote Path: /home/backups/
- Cron Schedule: 5 3 * * *
- Notifications: None
- Test Status: Successful
Tailscale: Enabled
- Server: https://controlplane.tailscale.com
- Tailscale IPs: 100.64.0.1
- Flags: None
Security Audit: Performed
- Audit Log: /var/log/setup_harden_security_audit_20250630_222800.log
- Hardening Index: 75
- Vulnerabilities: Not supported on Ubuntu
Log File: /var/log/du_setup_20250630_222800.log
Backups: /root/setup_harden_backup_20250630_222800
Post-Reboot Verification Steps:
- SSH access: ssh -p 2222 adminuser@192.0.2.1
- Firewall rules: sudo ufw status verbose
- Time sync: chronyc tracking
- Fail2Ban status: sudo fail2ban-client status sshd
- Swap status: sudo swapon --show && free -h
- Hostname: hostnamectl
- Docker status: docker ps
- Tailscale status: tailscale status
- Remote Backup:
- Verify SSH key: sudo cat /root/.ssh/id_ed25519.pub
- Copy key if needed: ssh-copy-id -p 23 -s u12345@u12345.your-storagebox.de
- Test backup: sudo /root/run_backup.sh
- Check logs: sudo less /var/log/backup_rsync.log
- Security Audit:
- Check results: sudo less /var/log/setup_harden_security_audit_20250630_222800.log
⚠ ACTION REQUIRED: Ensure the root SSH key (/root/.ssh/id_ed25519.pub) is copied to u12345@u12345.your-storagebox.de.
⚠ A reboot is required to apply all changes cleanly.
Reboot now? [Y/n]: n
⚠ Please reboot manually with 'sudo reboot'.
```
- **Potential Issues**: If services fail, theyre listed in `FAILED_SERVICES`. Backup key copy warning is appropriate for manual mode. No issues expected.
---
### **Potential Runtime Issues**
- **SSH Lockout**: If the user fails to test SSH on port 2222, the script rolls back to port 22, preventing lockout. The warning to test in a separate terminal is clear.
- **Backup Failure**: If the root SSH key isnt copied to the backup server, the test backup fails, and logs provide clear troubleshooting steps (e.g., `ssh-copy-id`, `nc -zv`).
- **Tailscale**: Invalid keys or network issues (e.g., UDP 41641 blocked) are caught with retries and logged to `/tmp/tailscale_status.txt`.
- **Disk Space**: Swap creation checks available space, exiting if insufficient. Assumed 2GB available in the VM.
- **Package Installation**: Repository failures are caught by `set -e`, and the script exits cleanly.