This is an old revision of the document!
apachesurvival
This tutorial is for users of Debian GNU/Linux using the LAMP stack, wanting TLS encryption, multiple self-hosted websites and will cover:
The tutorial below creates two virtual hosts, for registered domain site1.com and site2.com, and this can be scaled to as many as you like and/or your host will serve properly:
sudo apt install apache2 php mariadb-server sudo mkdir -p /var/www/site1.com/public_html sudo mkdir -p /var/www/site2.com/public_html sudo chown -R $USER:$USER /var/www/site1.com/public_html sudo chown -R $USER:$USER /var/www/site2.com/public_html sudo chmod 755 /var/www
Okay, for the first website, create your index.html:
sudo nano /var/www/site1.com/public_html/index.html
Give it some simple html:
<html> <head> <title>site1</title> </head> <body> <h1>site1</h1> </body> </html>
Same for the second website, open the file:
sudo nano /var/www/site2.com/public_html/index.html
Give it some simple html to distinguish it:
<html> <head> <title>site2</title> </head> <body> <h1>site2</h1> </body> </html>
Now, copy the default virtual host configuration to a new .conf file for each site:
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site1.com.conf sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site2.com.conf
Open the first virtual host conf for the first website:
sudo nano /etc/apache2/sites-available/site1.com.conf
Adjust to something like this:
<VirtualHost *:80> ServerAdmin name@site1.com ServerName site1.com ServerAlias www.site1.com DocumentRoot /var/www/site1.com/public_html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Repeat the steps above for the second virtual host site2.com.conf. Ok, now time to enable the virtual hosts with the a2ensite command, and disable the default site since you won't need that any longer:
sudo a2ensite site1.com.conf sudo a2ensite site2.com.conf sudo cp -r /var/www/html /root/html-bak sudo rm -r /var/www/html sudo a2dissite 000-default.conf
Now, if you prefer put some local dns entries in /etc/hosts
sudo nano /etc/hosts
Append something like this to the bottom:
xxx.xxx.xxx.xxx site1.com xxx.xxx.xxx.xxx www.site1.com xxx.xxx.xxx.xxx site2.com xxx.xxx.xxx.xxx www.site2.com
Check your configurations up until now and then restart the service and check if it starts:
sudo apache2ctl configtest sudo systemctl restart apache2.service
Visit site1.com and site2.com and debug. Once both properly resolve, it is time to set up TLS. If this is a public IP on a VPS, then at a minimum, set up ufw to allow http/https and provide access for you to ssh:
sudo apt install ufw sudo ufw allow 22 sudo ufw allow 80 sudo ufw allow 443 sudo ufw enable
It is always a good idea to first create your own self-signed certificates for each virtual host:
sudo openssl req -x509 -nodes -days 7305 -newkey rsa:2048 -keyout /etc/ssl/private/site1.key -out /etc/ssl/certs/site1.crt sudo openssl req -x509 -nodes -days 7305 -newkey rsa:2048 -keyout /etc/ssl/private/site1.key -out /etc/ssl/certs/site1.crt
Answer the questions, and pay careful attention to the email parameter because when we switch to Let's Encrypt, it will harvest that email and use it to contact you. You should now configure a diffie-hellman key for secure key exchange:
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
You can simply add all of your TLS options to the default-ssl.conf, or you can create a snippet:
sudo nano /etc/apache2/conf-available/ssl-params.conf
Having thus created the snippet, here are some recommended configurations and sources that document them:
# from https://cipherli.st/ # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_Apache2.html SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH SSLProtocol All -SSLv2 -SSLv3 SSLHonorCipherOrder On # Disable preloading HSTS for now. You can use the commented out header line that includes # the "preload" directive if you understand the implications. Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains" #Nextcloud prefers this rule with the other Header rules below it for X, disabled: #Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" Header always set X-Frame-Options DENY Header always set X-Content-Type-Options nosniff # Requires Apache >= 2.4 SSLCompression off SSLSessionTickets Off SSLUseStapling on SSLStaplingCache "shmcb:logs/stapling-cache(150000)" SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"
Don't forget to enable this configuration:
sudo a2enconf ssl-params
Configure the TLS virtual hosts for each domain previously configured above. If you chose not to do the snippet approach above, then you will start here and skip the snippet portion (and merely add any configurations you need to the ssl virtual hosts directly):
sudo cp /etc/apache2/sites-available/default-ssl.conf /root/default-ssl.conf.bak sudo cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/site1.com-ssl.conf sudo cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/site2.com-ssl.conf
Open the first TLS virtual host configuration file:
sudo nano /etc/apache2/sites-available/site1.com-ssl.conf
Uncomment the legacy support at the end and enter the standard configurations at the top:
<IfModule mod_ssl.c> <VirtualHost _default_:443> ServerAdmin name@site1.com ServerName site1.com DocumentRoot /var/www/site1.com/public_html </Directory> BrowserMatch "MSIE [2-6]" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 </VirtualHost> </IfModule>
Repeat the steps above for the site2.com-ssl.conf virtual host. If you want to enter some modules, then do so after the “downgrade line” and before the </VirtualHost> line and start with <IfModules> and end with </IfModules>. Now, you can redirect the original sites-enabled to default to TLS (or, skip this, and let Let's Encrypt handle it - but do not do both). Open site1.com virtual host (non TLS) conf file:
sudo nano /etc/apache2/sites-available/site1.com.conf
At the top, just under the DocumentRoot, enter something like:
Redirect permanent "/" "https://site1.com/"
Repeat this for the site2.conf file. Now, check your configuration again and enable headers and mods:
sudo a2enmod ssl sudo a2enmod headers sudo a2enconf ssl-params sudo apache2ctl configtest
You may get a trivial error if you do not have your ServerName set to localhost in the global configuration file located at /etc/apache2/apache2.conf. Once that is done, and if everything looks good, enable the TLS virtual hosts:
sudo a2ensite site1.com-ssl.conf sudo a2ensite site2.com-ssl.conf
Visit both sites using Firefox, and ensure they resovle. Now, set up Let's Encrypt so that you have your TLS certificates managed by a proper authority. I have never been able to get the stock certbot instructions to work, so I found this on a certbot tech support git repo, and have used it every since
sudo apt install certbot letsencrypt python-certbot-apache sudo certbot --authenticator standalone --installer apache -d site1.com --pre-hook "systemctl stop apache2" --post-hook "systemctl start apache2"
Run the second command again, but adjust it for site2.com. Now, restart the service:
sudo systemctl restart apache2
You can optionally verify them with ACME:
https://www.ssllabs.com/ssltest/analyze.html?d=site1.com&latest https://www.ssllabs.com/ssltest/analyze.html?d=site2.com&latest
Let's Encrypt expires often, so you likely want a cron job to update everything for you when/if needed:
sudo crontab -e 30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log sudo systemctl restart cron.service sudo systemctl restart apache2
You can also manually check certificates by:
sudo certbot renew
I have some servers in production that seem to just stop apache for whatever reason, so to limit downtime after all this work, you can create a simple monitoring script called apache-restart.sh:
sudo touch /usr/local/bin/apache-restart.sh sudo chmod 750 /usr/local/bin/apache-restart.sh sudo chown $USER:$USER /usr/local/bin/apache-restart.sh sudo nano /usr/local/bin/apache-restart.sh
Ok, now that we created the script file and made it executable, paste in the contents below but adjust them to your needs:
#!/bin/bash #functions RESTART="/bin/systemctl restart apache2.service" SERVICE="apache2.service" LOGFILE="/home/username/Desktop/apache-restart.log" if systemctl status apache2.service | grep dead then echo "Sir, apache2 failed at $(date), so I restarted it for you." >> $LOGFILE else echo "Ms., apache2 was running as of $(date)" >> $LOGFILE #or leave the else empty if you prefer fi
Okay, now let's make sure your log files do not get too large. First create a new entry in the logrotate daemon directory:
sudo nano /etc/logrotate.d/apache-restart
In that file that you just opened, enter some common sense limits for the log file so your computer does not fill up with logs:
/home/user/Desktop/apache-restart.log { daily rotate 10 delaycompress compress notifempty missingok size 100000k }
Alright, no point in making an apache monitoring script unless it runs automatically, so let's create a cron job:
sudo crontab -e * * * * * /bin/bash /usr/local/bin/apache-restart.sh >> /home/user/Desktop/apache-restart.log sudo systemctl restart cron
Test it, by stopping the service, and then waiting a minute.
sudo systemctl stop apache2
Check the logfile to verify it is working:
cat /home/user/Desktop/apache-restart.log
Cool! You now have two websites that are TLS encrypted! Now, it is time to put some content on that site, so consider these tutorials:
Also, you probably want to keep this host up to date, and you may have others, so consider reading the tutorial below, which covers how to do remote upgrades easily:
I keep the scripts up to date on my repo, over here:
This tutorial is a designated “Invariant Section” of the “Technotronic” section of Haack's Wiki as described on the Start Page.
— oemb1905 2020/01/01 14:56