du_setup/walk-through.md
2025-07-01 09:45:17 +01:00

377 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

### **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.
---
### **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`.\c
#### **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.
##### **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 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.