improved config
This commit is contained in:
parent
f3e1b1c784
commit
9ded453635
5 changed files with 195 additions and 27 deletions
|
@ -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
|
||||
|
|
65
add-site.sh
65
add-site.sh
|
@ -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
31
fail2ban.conf
Normal 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
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue