improved config

This commit is contained in:
Joby 2024-10-14 16:59:19 -06:00
parent f3e1b1c784
commit 9ded453635
5 changed files with 195 additions and 27 deletions

View file

@ -13,3 +13,10 @@ It is adviseable to review the contents of `quickstart.sh` before running it, as
```bash
curl -sSL https://raw.githubusercontent.com/joby-lol/webserver-config/refs/heads/main/quickstart.sh | bash
```
## Adding a site
To set up a site, run `add-site.sh` and it will prompt you for all the data necessary. What you will need before running it is:
* A domain name using Cloudflare's DNS, with both @ and * subdomains pointing at your server
* If you want to use their proxy, you need to turn on the SSL/TLS encryption mode of Full, Full(Strict), or Strict(SSL-Only Origin Pull). Flexible or Off will not work.
* A Cloudflare API key capable of editing the DNS for that domain

View file

@ -1,13 +1,33 @@
#!/bin/bash
# Script to add a site to the server
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or with sudo"
exit
fi
# Prompt for user input
read -p "Enter the desired username: " username
read -sp "Enter the password for $username: " password
echo
read -p "Enter the domain name (e.g., example.com): " domain
read -p "Enter the email address to be used for this account: " email
read -sp "Enter your Cloudflare API key: " cf_api_key
echo
# Generated passwords
password=$(openssl rand -base64 12)
mysql_password=$(openssl rand -base64 12)
# Get hostname or IP
hostname=$(hostname -f)
if [ $? -ne 0 ] || [ -z "$hostname" ] || [[ "$hostname" != *"."* ]]; then
echo "Failed to get a valid hostname. Falling back to IP address."
hostname=$(curl -s -4 icanhazip.com || curl -s -4 ifconfig.me || ip addr show | grep 'inet ' | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 | head -n 1)
if [ -z "$hostname" ]; then
echo "Failed to determine IP address. Using 'localhost' as fallback."
hostname="localhost"
fi
fi
# Create the user and add to www-data group
sudo useradd -m -s /bin/bash -G www-data $username
echo "$username:$password" | sudo chpasswd
@ -31,19 +51,53 @@ sudo bash -c "echo '
umask 022
' >> /etc/nginx/nginx.conf"
# Create MySQL user and grant permissions
sudo mysql <<EOF
CREATE USER '${username}'@'localhost' IDENTIFIED BY '${mysql_password}';
CREATE USER '${username}'@'%' IDENTIFIED BY '${mysql_password}';
GRANT ALL PRIVILEGES ON \`${username}_%\`.* TO '${username}'@'localhost';
GRANT ALL PRIVILEGES ON \`${username}_%\`.* TO '${username}'@'%';
GRANT CREATE USER ON *.* TO '${username}'@'localhost' WITH GRANT OPTION;
GRANT CREATE USER ON *.* TO '${username}'@'%' WITH GRANT OPTION;
GRANT ROLE_ADMIN ON *.* TO '${username}'@'localhost';
GRANT ROLE_ADMIN ON *.* TO '${username}'@'%';
FLUSH PRIVILEGES;
EOF
# Create site info file
info_file="$main_web_root/site_info.txt"
sudo bash -c "cat > $info_file << EOL
Domain: $domain
Email: $email
SFTP Host: $hostname
Username: $username
Password: $password
MySQL Username: $username
MySQL Password: $mysql_password
MySQL Host: $hostname
EOL"
sudo chown $username:www-data $info_file
sudo chmod 600 $info_file
# Create Cloudflare credentials file
cf_credentials="/root/.cloudflare/$domain.ini"
sudo mkdir -p /root/.cloudflare
cf_credentials="$main_web_root/cloudflare.ini"
sudo bash -c "cat > $cf_credentials << EOL
dns_cloudflare_api_token = $cf_api_key
EOL"
# note that cloudflare credentials are only even readable by root, to make it
# harder for attackers to get them, since they would allow lateral movement
sudo chown root:root $cf_credentials
sudo chmod 600 $cf_credentials
# Request wildcard certificate using Cloudflare DNS challenge
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials $cf_credentials \
-d $domain -d *.$domain \
--non-interactive
--non-interactive \
--agree-tos \
--email $email
# Create Nginx configuration
nginx_config="/etc/nginx/sites-available/$domain"
@ -132,5 +186,6 @@ echo "Setup complete for $domain"
echo "Main website files should be placed in: $main_web_root/_main/www"
echo "Subdomain files should be placed in: $main_web_root/subdomains/[subdomain]/www"
echo "Logs will be stored in: $main_web_root/logs"
echo "Site information (including MySQL credentials) is stored in: $info_file"
echo "Cloudflare credentials for this domain are stored in: $cf_credentials"
echo "Remember to log out and log back in for group changes to take effect."

31
fail2ban.conf Normal file
View file

@ -0,0 +1,31 @@
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
[nginx-http-auth]
enabled = true
filter = nginx-http-auth
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
[mysqld-auth]
enabled = true
filter = mysqld-auth
port = 3306
logpath = /var/log/mysql/error.log
maxretry = 5
bantime = 3600
[phpmyadmin]
enabled = true
port = http,https
filter = phpmyadmin
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600

View file

@ -1,24 +1,20 @@
#!/bin/bash
# Core Setup Script for Web Server
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or with sudo"
exit
fi
# Update and upgrade packages
sudo apt update
sudo apt upgrade -y
# Install Nginx and UFW
sudo apt install nginx ufw -y
# Install Nginx, UFW, MySQL, and fail2ban
sudo apt install nginx ufw mysql-server fail2ban -y
# Install PHP and necessary modules
sudo apt install php-fpm php-curl php-gd php-mbstring php-xml php-zip php-pdo php-sqlite3 -y
# Start and enable PHP-FPM service
sudo systemctl start php-fpm
sudo systemctl enable php-fpm
# Ensure Nginx is started and enabled
sudo systemctl start nginx
sudo systemctl enable nginx
sudo apt install php-fpm php-curl php-gd php-mbstring php-xml php-zip php-pdo php-mysql php-sqlite3 -y
# UFW Setup
sudo ufw default deny incoming
@ -43,12 +39,6 @@ sudo sysctl -p
# Install Certbot and Cloudflare plugin
sudo apt install certbot python3-certbot-dns-cloudflare -y
# Prompt user for email address
read -p "Enter your email address for Certbot registration: " email_address
# Register with Certbot
sudo certbot register --email "$email_address" --agree-tos --no-eff-email
# Create post-renewal hook for Nginx reload
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
sudo bash -c "cat > /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh << EOL
@ -57,13 +47,90 @@ systemctl reload nginx
EOL"
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
# Verify auto-renewal configuration
echo "Verifying Certbot auto-renewal configuration..."
sudo certbot renew --dry-run
# Configure MySQL for Unix socket authentication
sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH auth_socket;"
sudo mysql -e "DELETE FROM mysql.user WHERE User='';"
sudo mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
sudo mysql -e "DROP DATABASE IF EXISTS test;"
sudo mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Enable MySQL error logging
sudo sed -i '/^\[mysqld\]/a log_error = /var/log/mysql/error.log' /etc/mysql/mysql.conf.d/mysqld.cnf
sudo systemctl restart mysql
# Configure fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Copy custom fail2ban configuration
sudo cp fail2ban.conf /etc/fail2ban/jail.d/custom.conf
# Ensure fail2ban can read the MySQL log
sudo usermod -a -G adm fail2ban
# Create MySQL auth filter for fail2ban
sudo bash -c "cat > /etc/fail2ban/filter.d/mysqld-auth.conf << EOL
[Definition]
failregex = ^%(__prefix_line)s[0-9]+ \[Warning\] Access denied for user '\w+'@'<HOST>'
ignoreregex =
EOL"
# Create phpMyAdmin filter for fail2ban
sudo bash -c "cat > /etc/fail2ban/filter.d/phpmyadmin.conf << EOL
[Definition]
failregex = ^<HOST> .* \"(GET|POST) /phpmyadmin/index\.php HTTP/.*\" 403
^<HOST> .* \"(GET|POST) /phpmyadmin/.* HTTP/.*\" 404
ignoreregex =
EOL"
# Install phpMyAdmin
sudo apt install phpmyadmin -y
# Configure phpMyAdmin with Nginx
sudo bash -c "cat > /etc/nginx/conf.d/phpmyadmin.conf << EOL
location /phpmyadmin {
root /usr/share/;
index index.php index.html index.htm;
location ~ ^/phpmyadmin/(.+\.php)$ {
try_files \$uri =404;
root /usr/share/;
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
access_log /var/log/nginx/phpmyadmin_access.log;
}
location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
root /usr/share/;
}
}
EOL"
# Start and enable MySQL
sudo systemctl start mysql
sudo systemctl enable mysql
# Start and enable PHP-FPM service
sudo systemctl start php-fpm
sudo systemctl enable php-fpm
# Start and enable Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Start and enable fail2ban
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
# Output completion messages
echo "Core setup completed successfully!"
echo "Certbot has been registered with the provided email address"
echo "Nginx, PHP, MySQL, fail2ban, and phpMyAdmin have been installed and configured"
echo "Certbot and its Cloudflare plugin have been installed"
echo "A post-renewal hook has been added to reload Nginx after certificate renewal"
echo "Auto-renewal has been verified. If you saw no errors, it's correctly set up."
echo "UFW has been configured and enabled"
echo "A 2GB swap file has been set up and configured"
echo "MySQL has been configured for Unix socket authentication (no password, command-line only for root)"
echo "fail2ban has been configured to protect SSH, Nginx HTTP authentication, and MySQL"
echo "phpMyAdmin has been installed and configured with Nginx"
echo "You can access phpMyAdmin at http://your_server_ip/phpmyadmin"
echo "You can now use 'sudo bash add_site.sh' to add new sites and configure SSL for each"

View file

@ -1,5 +1,13 @@
#!/bin/bash
# Script to quickly set up a new server
# Download and install by running:
# curl -sSL https://raw.githubusercontent.com/joby-lol/webserver-config/refs/heads/main/quickstart.sh | bash
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or with sudo"
exit
fi
# Update package list
sudo apt update