Private
Public Access
1
0
Files
websitebox/install.sh
constantprojects b7dc25fbf2 Automate server hardening in install.sh, update guide accordingly
Move firewall (UFW), fail2ban, auto-updates, and Docker log rotation
from manual guide steps into install.sh automation. Update guide.md
to describe the automated process instead of manual commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 16:32:47 -07:00

222 lines
7.3 KiB
Bash
Executable File

#!/bin/bash
set -eo pipefail
# WebsiteBox Install Script
# Bootstrap script: installs Docker, clones repo, runs setup wizard
# Usage: curl -fsSL <url>/install.sh | bash
echo ""
echo "═══════════════════════════════════════════════════════════"
echo " WebsiteBox Installer"
echo "═══════════════════════════════════════════════════════════"
echo ""
# --- Check for root/sudo ---
if [ "$(id -u)" -eq 0 ]; then
SUDO=""
ACTUAL_USER="${SUDO_USER:-root}"
else
if ! command -v sudo &>/dev/null; then
echo "ERROR: This script requires root or sudo access."
exit 1
fi
SUDO="sudo"
ACTUAL_USER="$(whoami)"
fi
# --- Detect OS ---
if [ -f /etc/os-release ]; then
# shellcheck disable=SC1091
. /etc/os-release
OS_ID="$ID"
OS_VERSION="$VERSION_ID"
else
echo "ERROR: Cannot detect OS. /etc/os-release not found."
echo "WebsiteBox supports Ubuntu 20.04+ and Debian 11+."
exit 1
fi
case "$OS_ID" in
ubuntu)
if [ "${OS_VERSION%%.*}" -lt 20 ]; then
echo "ERROR: Ubuntu 20.04 or later is required (detected: ${OS_VERSION})."
exit 1
fi
;;
debian)
if [ "${OS_VERSION%%.*}" -lt 11 ]; then
echo "ERROR: Debian 11 or later is required (detected: ${OS_VERSION})."
exit 1
fi
;;
*)
echo "WARNING: Unsupported OS detected (${OS_ID} ${OS_VERSION})."
echo "WebsiteBox is tested on Ubuntu 20.04+ and Debian 11+."
read -rp "Continue anyway? (y/N) " cont
if [ "$cont" != "y" ] && [ "$cont" != "Y" ]; then
exit 1
fi
;;
esac
echo "Detected: ${OS_ID} ${OS_VERSION}"
# --- Secure the Server ---
echo ""
echo "───────────────────────────────────────────────────────────"
echo " Securing your server..."
echo "───────────────────────────────────────────────────────────"
# Update system packages
echo "Updating system packages..."
$SUDO apt-get update -qq
$SUDO apt-get upgrade -y -qq
echo "System packages updated."
# Install firewall, fail2ban, and automatic updates
echo "Installing firewall, fail2ban, and automatic updates..."
$SUDO apt-get install -y -qq ufw fail2ban unattended-upgrades
# Configure firewall — allow SSH first to avoid lockout
if ! $SUDO ufw status | grep -q "Status: active"; then
echo "Configuring firewall..."
$SUDO ufw allow OpenSSH
$SUDO ufw allow 80/tcp
$SUDO ufw allow 443/tcp
$SUDO ufw --force enable
echo "Firewall enabled: SSH, HTTP, and HTTPS allowed. All other ports blocked."
else
# Firewall already active — just make sure our ports are open
$SUDO ufw allow OpenSSH 2>/dev/null || true
$SUDO ufw allow 80/tcp 2>/dev/null || true
$SUDO ufw allow 443/tcp 2>/dev/null || true
echo "Firewall already active. Verified SSH, HTTP, and HTTPS are allowed."
fi
# Enable fail2ban
$SUDO systemctl enable fail2ban --quiet 2>/dev/null || true
$SUDO systemctl start fail2ban 2>/dev/null || true
echo "Fail2ban enabled: brute-force SSH protection active."
# Enable automatic security updates (non-interactive)
echo 'Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
"${distro_id}ESM:${distro_codename}-infra-security";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";' | $SUDO tee /etc/apt/apt.conf.d/50unattended-upgrades-websitebox > /dev/null
echo 'APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";' | $SUDO tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null
echo "Automatic security updates enabled."
# Configure Docker log rotation (create config before Docker install)
$SUDO mkdir -p /etc/docker
if [ ! -f /etc/docker/daemon.json ]; then
echo '{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}' | $SUDO tee /etc/docker/daemon.json > /dev/null
echo "Docker log rotation configured (10MB max per log, 3 files per container)."
else
echo "Docker daemon.json already exists. Skipping log rotation config."
fi
echo ""
echo " Server secured:"
echo " Firewall: active (SSH, HTTP, HTTPS only)"
echo " Fail2ban: active (SSH brute-force protection)"
echo " Auto-updates: enabled (daily security patches)"
echo " Docker log limits: configured (30MB max per container)"
echo ""
# --- Install Docker if needed ---
DOCKER_JUST_INSTALLED=false
if command -v docker &>/dev/null; then
echo "Docker is already installed."
else
echo "Installing Docker..."
# Install prerequisites
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq ca-certificates curl gnupg lsb-release
# Add Docker's GPG key
$SUDO install -m 0755 -d /etc/apt/keyrings
curl -fsSL "https://download.docker.com/linux/${OS_ID}/gpg" | $SUDO gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$SUDO chmod a+r /etc/apt/keyrings/docker.gpg
# Add Docker repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/${OS_ID} \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
$SUDO tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Add user to docker group
if [ "$ACTUAL_USER" != "root" ]; then
$SUDO usermod -aG docker "$ACTUAL_USER"
DOCKER_JUST_INSTALLED=true
echo "Docker installed. User '${ACTUAL_USER}' added to docker group."
fi
# Start and enable Docker
$SUDO systemctl start docker
$SUDO systemctl enable docker
echo "Docker installation complete."
else
# Docker exists — restart to pick up daemon.json if it was just created
if [ -f /etc/docker/daemon.json ]; then
$SUDO systemctl restart docker 2>/dev/null || true
fi
fi
# --- Clone Repository ---
INSTALL_DIR="${HOME}/websitebox"
if [ -d "$INSTALL_DIR" ]; then
echo "WebsiteBox directory already exists at ${INSTALL_DIR}"
echo "Pulling latest changes..."
cd "$INSTALL_DIR"
git pull || true
else
echo "Cloning WebsiteBox..."
git clone https://github.com/websitebox/websitebox.git "$INSTALL_DIR"
cd "$INSTALL_DIR"
fi
# Make scripts executable
chmod +x setup.sh install.sh scripts/*.sh
# --- Run Setup Wizard ---
echo ""
if [ "$DOCKER_JUST_INSTALLED" = true ] && [ "$ACTUAL_USER" != "root" ]; then
# Activate docker group for this session without requiring logout/login
echo "Activating Docker permissions for current session..."
sg docker -c "./setup.sh"
else
./setup.sh
fi
echo ""
echo "If 'docker compose' commands fail later, log out and back in"
echo "to permanently activate Docker permissions, then try again."
echo ""