diff --git a/fix-apache.sh b/fix-apache.sh
new file mode 100755
index 0000000..5055e47
--- /dev/null
+++ b/fix-apache.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+
+# Fix Apache Configuration Script
+# This script fixes common Apache issues after the main setup
+
+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
+
+error() {
+ echo -e "${RED}ERROR: $1${NC}" >&2
+ exit 1
+}
+
+info() {
+ echo -e "${BLUE}INFO: $1${NC}"
+}
+
+success() {
+ echo -e "${GREEN}SUCCESS: $1${NC}"
+}
+
+warning() {
+ echo -e "${YELLOW}WARNING: $1${NC}"
+}
+
+# Check if running as root
+if [[ $EUID -ne 0 ]]; then
+ error "This script must be run as root"
+fi
+
+info "Fixing Apache configuration..."
+
+# Stop any conflicting services
+info "Stopping conflicting services..."
+if systemctl is-active --quiet nginx 2>/dev/null; then
+ systemctl stop nginx
+ systemctl disable nginx
+ success "Nginx stopped and disabled"
+fi
+
+if pgrep nginx > /dev/null; then
+ pkill nginx
+ success "Killed remaining nginx processes"
+fi
+
+# Stop Apache
+systemctl stop apache2 2>/dev/null || true
+
+# Check what's listening on ports 80 and 443
+info "Checking port usage..."
+if ss -tlnp | grep -q ":80 "; then
+ warning "Something is listening on port 80:"
+ ss -tlnp | grep ":80 "
+fi
+
+if ss -tlnp | grep -q ":443 "; then
+ warning "Something is listening on port 443:"
+ ss -tlnp | grep ":443 "
+fi
+
+# Enable required Apache modules
+info "Enabling Apache modules..."
+a2enmod ssl
+a2enmod rewrite
+a2enmod proxy
+a2enmod proxy_fcgi
+a2enmod setenvif
+
+# Enable PHP-FPM
+info "Configuring PHP-FPM..."
+a2enconf php*-fpm
+systemctl enable php*-fpm
+systemctl restart php*-fpm
+
+# Check if PostfixAdmin site exists and enable it
+if [[ -f "/etc/apache2/sites-available/postfixadmin.conf" ]]; then
+ a2ensite postfixadmin
+ success "PostfixAdmin site enabled"
+else
+ warning "PostfixAdmin site configuration not found"
+fi
+
+# Disable default site
+a2dissite 000-default 2>/dev/null || true
+
+# Test Apache configuration
+info "Testing Apache configuration..."
+if apachectl configtest; then
+ success "Apache configuration is valid"
+else
+ error "Apache configuration has errors"
+fi
+
+# Start Apache
+info "Starting Apache..."
+systemctl enable apache2
+systemctl start apache2
+
+# Wait for Apache to start
+sleep 3
+
+# Check if Apache is running
+if systemctl is-active --quiet apache2; then
+ success "Apache is running"
+else
+ error "Apache failed to start"
+fi
+
+# Check listening ports
+info "Checking Apache listening ports..."
+if ss -tlnp | grep -q ":80.*apache"; then
+ success "Apache is listening on port 80"
+else
+ warning "Apache is not listening on port 80"
+fi
+
+if ss -tlnp | grep -q ":443.*apache"; then
+ success "Apache is listening on port 443"
+else
+ warning "Apache is not listening on port 443"
+fi
+
+# Show Apache status
+info "Apache status:"
+systemctl status apache2 --no-pager
+
+# Show enabled sites
+info "Enabled Apache sites:"
+a2ensite 2>&1 | grep "already enabled" || echo "No sites explicitly enabled"
+
+info "Apache configuration fix completed!"
+info "You can check Apache error logs with: journalctl -u apache2 -f"
+info "You can also check: /var/log/apache2/error.log"
diff --git a/fix-postfixadmin-site.sh b/fix-postfixadmin-site.sh
index 6983eaf..e69de29 100755
--- a/fix-postfixadmin-site.sh
+++ b/fix-postfixadmin-site.sh
@@ -1,118 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-
-# Colors
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-YELLOW='\033[1;33m'
-BLUE='\033[0;34m'
-NC='\033[0m'
-
-info() { echo -e "${BLUE}INFO: $1${NC}"; }
-success() { echo -e "${GREEN}SUCCESS: $1${NC}"; }
-warning() { echo -e "${YELLOW}WARNING: $1${NC}"; }
-error() { echo -e "${RED}ERROR: $1${NC}"; }
-
-HOSTNAME="mail.terrible.dev"
-
-info "Configuring Apache for PostfixAdmin..."
-
-# Check if PostfixAdmin directory exists
-if [[ ! -d "/var/www/postfixadmin" ]]; then
- error "PostfixAdmin directory not found at /var/www/postfixadmin"
- echo "This means the PostfixAdmin installation step was not completed."
- echo "You may need to run the resume-setup.sh script first."
- exit 1
-fi
-
-# Create PostfixAdmin Apache configuration
-info "Creating PostfixAdmin Apache site configuration..."
-sudo tee /etc/apache2/sites-available/postfixadmin.conf > /dev/null << EOF
-
- ServerName $HOSTNAME
- Redirect permanent / https://$HOSTNAME/
-
-
-
- ServerName $HOSTNAME
- DocumentRoot /var/www/postfixadmin/public
-
- SSLEngine on
- SSLCertificateFile /etc/letsencrypt/live/$HOSTNAME/fullchain.pem
- SSLCertificateKeyFile /etc/letsencrypt/live/$HOSTNAME/privkey.pem
-
- # Modern SSL configuration
- SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
- SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
- SSLHonorCipherOrder on
-
-
- Options -Indexes
- AllowOverride All
- Require all granted
-
-
- # Alternative document root if public folder doesn't exist
-
- Options -Indexes
- AllowOverride All
- Require all granted
-
-
- ErrorLog \${APACHE_LOG_DIR}/postfixadmin_error.log
- CustomLog \${APACHE_LOG_DIR}/postfixadmin_access.log combined
-
-EOF
-
-# Check if public directory exists, if not use main directory
-if [[ ! -d "/var/www/postfixadmin/public" ]]; then
- warning "PostfixAdmin public directory not found, using main directory"
- sudo sed -i 's|DocumentRoot /var/www/postfixadmin/public|DocumentRoot /var/www/postfixadmin|' /etc/apache2/sites-available/postfixadmin.conf
-fi
-
-# Disable default site and enable PostfixAdmin
-info "Enabling PostfixAdmin site..."
-sudo a2dissite 000-default 2>/dev/null || true
-sudo a2ensite postfixadmin
-
-# Test Apache configuration
-if sudo apache2ctl configtest; then
- success "Apache configuration is valid"
-else
- error "Apache configuration test failed"
- exit 1
-fi
-
-# Reload Apache
-sudo systemctl reload apache2
-
-# Test PostfixAdmin access
-info "Testing PostfixAdmin access..."
-sleep 2
-
-if curl -I -k https://$HOSTNAME/postfixadmin/ 2>/dev/null | grep -q "200\|302\|301"; then
- success "PostfixAdmin is accessible!"
- echo
- echo "🎉 PostfixAdmin URLs:"
- echo " Setup: https://$HOSTNAME/postfixadmin/setup.php"
- echo " Login: https://$HOSTNAME/postfixadmin/"
- echo
-elif curl -I -k https://$HOSTNAME/ 2>/dev/null | grep -q "200\|302\|301"; then
- warning "Site accessible but PostfixAdmin may need setup"
- echo
- echo "📋 Try these URLs:"
- echo " Main: https://$HOSTNAME/"
- echo " Setup: https://$HOSTNAME/setup.php"
- echo " Admin: https://$HOSTNAME/admin/"
-else
- error "PostfixAdmin not accessible"
- echo "Check Apache error logs:"
- echo "sudo tail -f /var/log/apache2/error.log"
-fi
-
-info "Current site status:"
-echo "Available sites:"
-sudo ls -la /etc/apache2/sites-available/ | grep postfixadmin || echo " No postfixadmin config found"
-echo "Enabled sites:"
-sudo ls -la /etc/apache2/sites-enabled/
diff --git a/setup-email-server.sh b/setup-email-server.sh
index e4d55a7..9db4258 100755
--- a/setup-email-server.sh
+++ b/setup-email-server.sh
@@ -4,7 +4,7 @@
# Components: Postfix, Dovecot, Amavis, SpamAssassin, OpenDKIM, PostgreSQL, PostfixAdmin
# SSL: Let's Encrypt (DNS-01 Challenge)
# Author: Email Server Setup Script
-# Date: $(date)
+# Date: Sun Aug 3 15:05:28 EDT 2025
set -euo pipefail
@@ -24,6 +24,7 @@ DB_USER="postfix"
DB_PASSWORD=""
POSTFIXADMIN_PASSWORD=""
WEBROOT="/var/www/postfixadmin"
+POSTFIXADMIN_VHOST_FILE="/etc/apache2/sites-available/postfixadmin.conf"
# Logging
LOG_FILE="/var/log/email-server-setup.log"
@@ -60,6 +61,46 @@ check_root() {
fi
}
+
+verify_email_storage() {
+ info "Verifying email storage at /mnt/MainEmail..."
+
+ # Check if directory exists
+ if [[ ! -d "/mnt/MainEmail" ]]; then
+ error "Email storage directory /mnt/MainEmail does not exist. Please run prepare-email-storage.sh first."
+ fi
+
+ # Check if vmail user exists
+ if ! getent passwd vmail >/dev/null; then
+ error "vmail user does not exist. Please run prepare-email-storage.sh first."
+ fi
+
+ # Check ownership
+ OWNER=$(stat -c '%U:%G' /mnt/MainEmail)
+ if [[ "$OWNER" != "vmail:vmail" ]]; then
+ warning "Incorrect ownership on /mnt/MainEmail. Expected vmail:vmail, got $OWNER"
+ info "Fixing ownership..."
+ chown vmail:vmail /mnt/MainEmail
+ fi
+
+ # Check write permissions
+ if ! sudo -u vmail test -w /mnt/MainEmail; then
+ error "vmail user cannot write to /mnt/MainEmail. Please run prepare-email-storage.sh first."
+ fi
+
+ # Check available space
+ AVAILABLE_SPACE=$(df --output=avail /mnt/MainEmail | tail -n1)
+ AVAILABLE_GB=$((AVAILABLE_SPACE / 1024 / 1024))
+
+ if [[ $AVAILABLE_GB -lt 5 ]]; then
+ warning "Low disk space: only ${AVAILABLE_GB}GB available in /mnt/MainEmail"
+ else
+ info "Email storage ready: ${AVAILABLE_GB}GB available"
+ fi
+
+ success "Email storage verification completed"
+}
+
# Get user input
get_configuration() {
echo -e "${BLUE}Email Server Configuration${NC}"
@@ -101,6 +142,33 @@ update_system() {
install_packages() {
info "Installing required packages..."
+ # Check for and stop Nginx if it's running to avoid port conflicts with Apache
+ if systemctl is-active --quiet nginx 2>/dev/null; then
+ warning "Nginx is running and will be stopped to allow Apache to run."
+ systemctl stop nginx
+ systemctl disable nginx
+ elif command -v nginx &> /dev/null; then
+ warning "Nginx is installed but not running as a service."
+ # Check if nginx is running manually and kill it
+ if pgrep nginx > /dev/null; then
+ warning "Found nginx processes, killing them..."
+ pkill nginx
+ fi
+ fi
+
+ # Also check if anything is listening on port 80 or 443
+ if ss -tlnp | grep -q ":80 "; then
+ warning "Something is already listening on port 80:"
+ ss -tlnp | grep ":80 "
+ echo "You may need to stop this service manually before Apache can start."
+ fi
+
+ if ss -tlnp | grep -q ":443 "; then
+ warning "Something is already listening on port 443:"
+ ss -tlnp | grep ":443 "
+ echo "You may need to stop this service manually before Apache can start."
+ fi
+
# Install basic packages
apt install -y \
curl \
@@ -109,7 +177,6 @@ install_packages() {
lsb-release \
software-properties-common \
certbot \
- nginx \
ufw
# Install PostgreSQL
@@ -303,7 +370,7 @@ mydestination = localhost
virtual_mailbox_domains = pgsql:/etc/postfix/pgsql-virtual-mailbox-domains.cf
virtual_mailbox_maps = pgsql:/etc/postfix/pgsql-virtual-mailbox-maps.cf
virtual_alias_maps = pgsql:/etc/postfix/pgsql-virtual-alias-maps.cf
-virtual_mailbox_base = /var/mail/vhosts
+virtual_mailbox_base = /mnt/MainEmail
virtual_minimum_uid = 100
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
@@ -427,10 +494,10 @@ smtp-amavis unix - - - - 2 smtp
EOF
# Create virtual mailbox directory
- mkdir -p /var/mail/vhosts
+ mkdir -p /mnt/MainEmail
groupadd -g 5000 vmail 2>/dev/null || true
- useradd -g vmail -u 5000 vmail -d /var/mail/vhosts -m 2>/dev/null || true
- chown -R vmail:vmail /var/mail/vhosts
+ useradd -g vmail -u 5000 vmail -d /mnt/MainEmail -m 2>/dev/null || true
+ chown -R vmail:vmail /mnt/MainEmail
success "Postfix configured"
}
@@ -452,7 +519,7 @@ EOF
# 10-mail.conf
cat > /etc/dovecot/conf.d/10-mail.conf << EOF
-mail_location = maildir:/var/mail/vhosts/%d/%n
+mail_location = maildir:/mnt/MainEmail/%d/%n
namespace inbox {
inbox = yes
}
@@ -480,7 +547,7 @@ passdb {
}
userdb {
driver = static
- args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
+ args = uid=vmail gid=vmail home=/mnt/MainEmail/%d/%n
}
EOF
@@ -722,7 +789,7 @@ get_ssl_certificates() {
success "SSL certificates obtained"
}
-# Install PostfixAdmin
+# Install PostfixAdmin and configure Apache
install_postfixadmin() {
info "Installing PostfixAdmin..."
@@ -769,7 +836,7 @@ function maildir_name_hook(\$domain, \$user) {
EOF
# Configure Apache virtual host
- cat > /etc/apache2/sites-available/postfixadmin.conf << EOF
+ cat > "$POSTFIXADMIN_VHOST_FILE" << EOF
ServerName $HOSTNAME
Redirect permanent / https://$HOSTNAME/
@@ -777,30 +844,61 @@ EOF
ServerName $HOSTNAME
- DocumentRoot $WEBROOT/public
+ DocumentRoot $WEBROOT
+ DirectoryIndex index.php index.html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/$HOSTNAME/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/$HOSTNAME/privkey.pem
+ SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
+ SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
+ SSLHonorCipherOrder on
-
+
Options -Indexes
AllowOverride All
Require all granted
+ # PHP configuration
+
+ SetHandler "proxy:unix:/run/php/php-fpm.sock|fcgi://localhost"
+
+
ErrorLog \${APACHE_LOG_DIR}/postfixadmin_error.log
CustomLog \${APACHE_LOG_DIR}/postfixadmin_access.log combined
EOF
- # Enable Apache modules and site
+ # Stop Apache before configuration changes
+ if systemctl is-active --quiet apache2; then
+ systemctl stop apache2
+ fi
+
+ # Enable required Apache modules
a2enmod ssl
a2enmod rewrite
+ a2enmod proxy
+ a2enmod proxy_fcgi
+ a2enmod setenvif
+
+ # Enable PHP-FPM configuration
+ a2enconf php*-fpm
+
+ # Enable PostfixAdmin site and disable default
a2ensite postfixadmin
a2dissite 000-default
- success "PostfixAdmin installed"
+ # Ensure PHP-FPM is running
+ systemctl enable php*-fpm
+ systemctl start php*-fpm
+
+ # Check Apache config before starting
+ if ! apachectl configtest; then
+ error "Apache configuration test failed. Please check $POSTFIXADMIN_VHOST_FILE"
+ fi
+
+ success "PostfixAdmin installed and Apache configured"
}
# Configure firewall
@@ -852,8 +950,28 @@ start_services() {
systemctl enable --now clamav-daemon
systemctl enable --now clamav-freshclam
systemctl enable --now opendkim
- systemctl enable --now apache2
+ # Start Apache2 and verify
+ info "Starting Apache2..."
+ systemctl enable apache2
+ systemctl restart apache2
+
+ # Wait a moment for Apache to start
+ sleep 2
+
+ if ! systemctl is-active --quiet apache2; then
+ error "Apache2 failed to start. Check 'journalctl -xeu apache2' for details."
+ fi
+
+ # Verify Apache is listening on both ports
+ if ! ss -tlnp | grep -q ":80 "; then
+ warning "Apache is not listening on port 80"
+ fi
+
+ if ! ss -tlnp | grep -q ":443 "; then
+ warning "Apache is not listening on port 443"
+ fi
+
success "All services started and enabled"
}
@@ -877,10 +995,10 @@ display_final_info() {
cat /etc/opendkim/keys/$DOMAIN/mail.txt
echo
echo -e "${YELLOW}=== Next Steps ===${NC}"
- echo "1. Add the DNS records shown above"
- echo "2. Visit https://$HOSTNAME/postfixadmin/setup.php to complete PostfixAdmin setup"
- echo "3. Create your first domain and mailbox in PostfixAdmin"
- echo "4. Test email sending and receiving"
+ echo "1. Add the DNS records shown above."
+ echo "2. Visit https://$HOSTNAME/postfixadmin/setup.php to complete PostfixAdmin setup."
+ echo "3. Create your first domain and mailbox in PostfixAdmin."
+ echo "4. Test email sending and receiving."
echo
echo -e "${BLUE}=== Multiple Domain Support ===${NC}"
echo "This server supports unlimited virtual domains!"
@@ -902,26 +1020,27 @@ display_final_info() {
echo -e "${GREEN}Setup completed successfully!${NC}"
}
-# Main execution
+# Main function to run all setup steps
main() {
- echo -e "${BLUE}Email Server Setup Script${NC}"
- echo "========================="
- echo
+ log "Starting email server setup script"
check_root
+ verify_email_storage
get_configuration
update_system
install_packages
configure_postgresql
- get_ssl_certificates
configure_postfix
configure_dovecot
configure_opendkim
configure_amavis
+ get_ssl_certificates
install_postfixadmin
configure_firewall
start_services
display_final_info
+
+ log "Email server setup completed successfully"
}
# Run main function
diff --git a/test-apache.sh b/test-apache.sh
new file mode 100755
index 0000000..3f1b811
--- /dev/null
+++ b/test-apache.sh
@@ -0,0 +1,134 @@
+#!/bin/bash
+
+# Test Apache and PostfixAdmin Setup
+# This script helps diagnose Apache and PostfixAdmin issues
+
+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
+
+info() {
+ echo -e "${BLUE}INFO: $1${NC}"
+}
+
+success() {
+ echo -e "${GREEN}SUCCESS: $1${NC}"
+}
+
+warning() {
+ echo -e "${YELLOW}WARNING: $1${NC}"
+}
+
+error() {
+ echo -e "${RED}ERROR: $1${NC}"
+}
+
+info "=== Apache and PostfixAdmin Diagnostic ==="
+
+# Check Apache status
+info "1. Checking Apache status..."
+if systemctl is-active --quiet apache2; then
+ success "Apache is running"
+else
+ error "Apache is not running"
+ echo "Try: systemctl start apache2"
+fi
+
+# Check listening ports
+info "2. Checking listening ports..."
+echo "Ports 80 and 443:"
+ss -tlnp | grep -E ":(80|443) " || warning "No services listening on ports 80 or 443"
+
+# Check Apache sites
+info "3. Checking Apache sites..."
+echo "Available sites:"
+ls -la /etc/apache2/sites-available/ 2>/dev/null || warning "No sites-available directory"
+
+echo "Enabled sites:"
+ls -la /etc/apache2/sites-enabled/ 2>/dev/null || warning "No sites-enabled directory"
+
+# Check PostfixAdmin directory
+info "4. Checking PostfixAdmin installation..."
+WEBROOT="/var/www/postfixadmin"
+if [[ -d "$WEBROOT" ]]; then
+ success "PostfixAdmin directory exists: $WEBROOT"
+ echo "Contents:"
+ ls -la "$WEBROOT" | head -10
+
+ # Check if index.php exists
+ if [[ -f "$WEBROOT/index.php" ]]; then
+ success "index.php found"
+ elif [[ -f "$WEBROOT/public/index.php" ]]; then
+ success "index.php found in public directory"
+ warning "You may need to update DocumentRoot to $WEBROOT/public"
+ else
+ warning "index.php not found"
+ fi
+
+ # Check permissions
+ echo "Permissions:"
+ ls -ld "$WEBROOT"
+else
+ error "PostfixAdmin directory not found: $WEBROOT"
+fi
+
+# Check PHP-FPM
+info "5. Checking PHP-FPM..."
+if systemctl is-active --quiet php*-fpm; then
+ success "PHP-FPM is running"
+else
+ warning "PHP-FPM may not be running"
+ echo "Try: systemctl status php*-fpm"
+fi
+
+# Check Apache configuration
+info "6. Testing Apache configuration..."
+if apachectl configtest 2>/dev/null; then
+ success "Apache configuration is valid"
+else
+ error "Apache configuration has errors:"
+ apachectl configtest
+fi
+
+# Check SSL certificates
+info "7. Checking SSL certificates..."
+HOSTNAME=$(hostname -f 2>/dev/null || hostname)
+if [[ -f "/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" ]]; then
+ success "SSL certificate found for $HOSTNAME"
+else
+ warning "SSL certificate not found for $HOSTNAME"
+ echo "Check: ls -la /etc/letsencrypt/live/"
+fi
+
+# Check Apache error log
+info "8. Recent Apache errors (last 10 lines):"
+if [[ -f "/var/log/apache2/error.log" ]]; then
+ tail -10 /var/log/apache2/error.log
+else
+ warning "Apache error log not found"
+fi
+
+# Test HTTP response
+info "9. Testing HTTP response..."
+if command -v curl &> /dev/null; then
+ echo "HTTP (port 80) response:"
+ curl -I -s http://localhost/ 2>/dev/null | head -5 || warning "No response on port 80"
+
+ echo "HTTPS (port 443) response:"
+ curl -I -s -k https://localhost/ 2>/dev/null | head -5 || warning "No response on port 443"
+else
+ warning "curl not installed, cannot test HTTP responses"
+fi
+
+info "=== Diagnostic completed ==="
+echo
+info "If Apache is not working:"
+echo "1. Check: journalctl -u apache2 -f"
+echo "2. Check: /var/log/apache2/error.log"
+echo "3. Try: systemctl restart apache2"
+echo "4. Run: ./fix-apache.sh"