Update install-mailcow-ubuntu.sh
This commit is contained in:
parent
3e19423845
commit
3a542bf108
1 changed files with 148 additions and 170 deletions
|
@ -1,75 +1,99 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Exit on any error
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
# Checkpoint file
|
||||
CHECKPOINT_FILE="/tmp/mailcow_install_progress"
|
||||
MAILCOW_DIR="/opt/mailcow-dockerized"
|
||||
|
||||
# Function to log messages
|
||||
log_message() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
|
||||
}
|
||||
|
||||
# Function to save checkpoint
|
||||
save_checkpoint() {
|
||||
echo "$1" > "$CHECKPOINT_FILE"
|
||||
log_message "Checkpoint saved: $1"
|
||||
}
|
||||
|
||||
# Function to get last checkpoint
|
||||
get_checkpoint() {
|
||||
if [ -f "$CHECKPOINT_FILE" ]; then
|
||||
cat "$CHECKPOINT_FILE"
|
||||
else
|
||||
echo "start"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check if a step is completed
|
||||
is_step_completed() {
|
||||
local current_checkpoint=$(get_checkpoint)
|
||||
local step=$1
|
||||
|
||||
case $current_checkpoint in
|
||||
"docker_installed"|"fail2ban_configured"|"mailcow_installed"|"complete")
|
||||
if [ "$step" = "system_updated" ]; then return 0; fi
|
||||
;;
|
||||
"fail2ban_configured"|"mailcow_installed"|"complete")
|
||||
if [ "$step" = "docker_installed" ]; then return 0; fi
|
||||
;;
|
||||
"mailcow_installed"|"complete")
|
||||
if [ "$step" = "fail2ban_configured" ]; then return 0; fi
|
||||
;;
|
||||
"complete")
|
||||
if [ "$step" = "mailcow_installed" ]; then return 0; fi
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
# Check if script is run as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Update system
|
||||
log_message "Updating system packages..."
|
||||
apt-get update && apt-get upgrade -y
|
||||
# Start or resume installation
|
||||
log_message "Starting or resuming installation from checkpoint: $(get_checkpoint)"
|
||||
|
||||
# Install essential packages
|
||||
log_message "Installing essential packages..."
|
||||
apt-get install -y \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
ufw \
|
||||
fail2ban \
|
||||
git \
|
||||
sudo
|
||||
# Step 1: Update system
|
||||
if ! is_step_completed "system_updated"; then
|
||||
log_message "Updating system packages..."
|
||||
apt-get update && apt-get upgrade -y
|
||||
apt-get install -y ca-certificates curl gnupg ufw fail2ban git sudo
|
||||
save_checkpoint "system_updated"
|
||||
fi
|
||||
|
||||
# Install Docker
|
||||
log_message "Installing Docker..."
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
# Step 2: Install Docker
|
||||
if ! is_step_completed "docker_installed"; then
|
||||
log_message "Installing Docker..."
|
||||
install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add Docker repository
|
||||
echo \
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
apt-get update
|
||||
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
apt-get update
|
||||
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# Create docker user and set up permissions
|
||||
log_message "Creating docker user and setting up permissions..."
|
||||
useradd -m -s /bin/bash dockeruser
|
||||
usermod -aG docker dockeruser
|
||||
echo "dockeruser ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/docker-compose" | sudo tee /etc/sudoers.d/dockeruser
|
||||
# Create docker user if not exists
|
||||
if ! id "dockeruser" &>/dev/null; then
|
||||
useradd -m -s /bin/bash dockeruser
|
||||
usermod -aG docker dockeruser
|
||||
fi
|
||||
|
||||
# Configure UFW
|
||||
log_message "Configuring firewall..."
|
||||
ufw default deny incoming
|
||||
ufw default allow outgoing
|
||||
ufw allow 22/tcp
|
||||
ufw allow 25/tcp
|
||||
ufw allow 80/tcp
|
||||
ufw allow 110/tcp
|
||||
ufw allow 143/tcp
|
||||
ufw allow 443/tcp
|
||||
ufw allow 465/tcp
|
||||
ufw allow 587/tcp
|
||||
ufw allow 993/tcp
|
||||
ufw allow 995/tcp
|
||||
ufw allow 4190/tcp
|
||||
ufw --force enable
|
||||
save_checkpoint "docker_installed"
|
||||
fi
|
||||
|
||||
# Configure fail2ban for SSH
|
||||
log_message "Configuring fail2ban for SSH protection..."
|
||||
cat > /etc/fail2ban/jail.local << EOL
|
||||
# Step 3: Configure fail2ban
|
||||
if ! is_step_completed "fail2ban_configured"; then
|
||||
log_message "Configuring fail2ban..."
|
||||
cat > /etc/fail2ban/jail.local << EOL
|
||||
[DEFAULT]
|
||||
bantime = 1h
|
||||
findtime = 10m
|
||||
|
@ -89,129 +113,83 @@ bantime = 1d
|
|||
findtime = 10m
|
||||
EOL
|
||||
|
||||
# Reload systemd daemon
|
||||
systemctl daemon-reload
|
||||
|
||||
# Restart fail2ban
|
||||
systemctl restart fail2ban
|
||||
|
||||
# Restart fail2ban
|
||||
systemctl restart fail2ban
|
||||
|
||||
# Set up Mailcow directory and permissions
|
||||
log_message "Setting up Mailcow directory..."
|
||||
mkdir -p /opt/mailcow-dockerized
|
||||
chown dockeruser:dockeruser /opt/mailcow-dockerized
|
||||
|
||||
# Function to get FQDN input
|
||||
get_fqdn() {
|
||||
local fqdn
|
||||
while true; do
|
||||
read -p "Please enter your Fully Qualified Domain Name (FQDN) (e.g., mail.example.com): " fqdn
|
||||
if [[ $fqdn =~ ^[a-zA-Z0-9][a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
||||
echo "$fqdn"
|
||||
return 0
|
||||
else
|
||||
echo "Invalid FQDN format. Please try again."
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Get timezone
|
||||
get_timezone() {
|
||||
local timezone
|
||||
while true; do
|
||||
read -p "Please enter your timezone (e.g., Europe/Berlin) [default: UTC]: " timezone
|
||||
timezone=${timezone:-UTC}
|
||||
if [ -f "/usr/share/zoneinfo/$timezone" ]; then
|
||||
echo "$timezone"
|
||||
return 0
|
||||
else
|
||||
echo "Invalid timezone. Please try again."
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Function to configure mailcow
|
||||
configure_mailcow() {
|
||||
local fqdn=$1
|
||||
local timezone=$2
|
||||
|
||||
# Create temporary config file
|
||||
cat > /tmp/mailcow_config << EOL
|
||||
MAILCOW_HOSTNAME=${fqdn}
|
||||
TIMEZONE=${timezone}
|
||||
EOL
|
||||
|
||||
# Ask for additional configuration
|
||||
read -p "Do you want to customize additional mailcow configuration? (y/N): " customize
|
||||
if [[ $customize =~ ^[Yy]$ ]]; then
|
||||
nano /tmp/mailcow_config
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Switch to dockeruser and install Mailcow
|
||||
log_message "Installing Mailcow as dockeruser..."
|
||||
|
||||
# Get configuration parameters
|
||||
FQDN=$(get_fqdn)
|
||||
TIMEZONE=$(get_timezone)
|
||||
|
||||
# Store configuration for dockeruser
|
||||
echo "FQDN=$FQDN" > /tmp/mailcow_vars
|
||||
echo "TIMEZONE=$TIMEZONE" >> /tmp/mailcow_vars
|
||||
|
||||
configure_mailcow "$FQDN" "$TIMEZONE"
|
||||
|
||||
su - dockeruser << 'EOF'
|
||||
# Source the configuration variables
|
||||
source /tmp/mailcow_vars
|
||||
|
||||
# Clone and set up mailcow
|
||||
cd /opt
|
||||
git clone https://github.com/mailcow/mailcow-dockerized
|
||||
cd mailcow-dockerized
|
||||
|
||||
# Use the prepared configuration
|
||||
cat /tmp/mailcow_config > mailcow.conf
|
||||
|
||||
# Generate config with the provided FQDN
|
||||
printf "%s\n" "$FQDN" | ./generate_config.sh
|
||||
|
||||
# Offer to edit the full configuration
|
||||
read -p "Would you like to review and edit the full mailcow configuration? (y/N): " edit_conf
|
||||
if [[ $edit_conf =~ ^[Yy]$ ]]; then
|
||||
nano mailcow.conf
|
||||
systemctl restart fail2ban
|
||||
save_checkpoint "fail2ban_configured"
|
||||
fi
|
||||
|
||||
# Start Mailcow
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
EOF
|
||||
# Step 4: Install and configure Mailcow
|
||||
if ! is_step_completed "mailcow_installed"; then
|
||||
log_message "Setting up Mailcow..."
|
||||
|
||||
# Clean up temporary files
|
||||
rm -f /tmp/mailcow_vars /tmp/mailcow_config
|
||||
# Check if FQDN is already set
|
||||
if [ ! -f "/tmp/mailcow_hostname" ]; then
|
||||
read -p "Please enter your Fully Qualified Domain Name (FQDN) (e.g., mail.example.com): " MAILCOW_HOSTNAME
|
||||
echo "$MAILCOW_HOSTNAME" > /tmp/mailcow_hostname
|
||||
else
|
||||
MAILCOW_HOSTNAME=$(cat /tmp/mailcow_hostname)
|
||||
log_message "Using saved FQDN: $MAILCOW_HOSTNAME"
|
||||
fi
|
||||
|
||||
# Final security checks
|
||||
log_message "Performing final security checks..."
|
||||
su - dockeruser -c "cd /opt/mailcow-dockerized && docker compose ps"
|
||||
ufw status
|
||||
systemctl status fail2ban
|
||||
# Create mailcow directory if not exists
|
||||
if [ ! -d "$MAILCOW_DIR" ]; then
|
||||
mkdir -p "$MAILCOW_DIR"
|
||||
chown dockeruser:dockeruser "$MAILCOW_DIR"
|
||||
|
||||
log_message "Installation complete! Please check the logs above for any errors."
|
||||
log_message "Remember to:"
|
||||
log_message "1. Change the default passwords"
|
||||
log_message "2. Configure your DNS records"
|
||||
log_message "3. Set up SSL certificates"
|
||||
log_message "4. Regular backup your configuration"
|
||||
# Clone repository
|
||||
su - dockeruser -c "cd /opt && git clone https://github.com/mailcow/mailcow-dockerized"
|
||||
fi
|
||||
|
||||
# Print access information
|
||||
echo "================================================================"
|
||||
echo "Mailcow web interface: https://$(hostname)"
|
||||
echo "Docker user: dockeruser"
|
||||
echo "Mailcow location: /opt/mailcow-dockerized"
|
||||
echo "Firewall status:"
|
||||
ufw status numbered
|
||||
echo "================================================================"
|
||||
# Generate config if not already generated
|
||||
if [ ! -f "$MAILCOW_DIR/mailcow.conf" ]; then
|
||||
cd "$MAILCOW_DIR"
|
||||
echo "$MAILCOW_HOSTNAME" | ./generate_config.sh
|
||||
|
||||
echo "Would you like to edit the mailcow configuration? (y/N)"
|
||||
read -n1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
nano mailcow.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start Mailcow services
|
||||
log_message "Starting Mailcow services..."
|
||||
su - dockeruser -c "cd $MAILCOW_DIR && docker compose pull && docker compose up -d"
|
||||
|
||||
save_checkpoint "mailcow_installed"
|
||||
fi
|
||||
|
||||
# Configure UFW if not already configured
|
||||
if ! ufw status | grep -q "Status: active"; then
|
||||
log_message "Configuring firewall..."
|
||||
ufw default deny incoming
|
||||
ufw default allow outgoing
|
||||
ufw allow 22/tcp
|
||||
ufw allow 25/tcp
|
||||
ufw allow 80/tcp
|
||||
ufw allow 110/tcp
|
||||
ufw allow 143/tcp
|
||||
ufw allow 443/tcp
|
||||
ufw allow 465/tcp
|
||||
ufw allow 587/tcp
|
||||
ufw allow 993/tcp
|
||||
ufw allow 995/tcp
|
||||
ufw allow 4190/tcp
|
||||
ufw --force enable
|
||||
fi
|
||||
|
||||
# Final steps and cleanup
|
||||
if [ "$(get_checkpoint)" = "mailcow_installed" ]; then
|
||||
log_message "Installation completed successfully!"
|
||||
rm -f "$CHECKPOINT_FILE" "/tmp/mailcow_hostname"
|
||||
save_checkpoint "complete"
|
||||
|
||||
# Print access information
|
||||
echo "================================================================"
|
||||
echo "Mailcow web interface: https://$MAILCOW_HOSTNAME"
|
||||
echo "Docker user: dockeruser"
|
||||
echo "Mailcow location: $MAILCOW_DIR"
|
||||
echo "Firewall status:"
|
||||
ufw status numbered
|
||||
echo "================================================================"
|
||||
fi
|
Loading…
Reference in a new issue