Turning a bunch of stale sourdough bread into croutons.

Posted on February 5, 2020

Read More


A few years ago, I wrote a blog post documenting how I installed a LAMP stack on a Linode VPS running CentOS 7. This set up has been serving me well in the intervening years, but recently CentOS released version 8 of their Linux distribution, so I wanted to investigate what the set up of a similar LAMP stack would look like on CentOS 8.

The good news is that setting up a modern stack is a lot easier on CentOS 8 than it was on CentOS 7. For one thing, many of the defaults on CentOS 8 are better than they were on CentOS 7. For example, Apache on Centos 8 now ships with the Event MPM as the default rather than the Prefork MPM. Additionally, CentOS 8’s new system of module streams makes it much easier to upgrade packages to newer versions. (I’m looking at you PHP!)

So in the hope that this might be helpful to others, below are the steps I followed to install a LAMP stack on a VPS running CentOS 8 and hosted by Linode. Just like last time, I’m not going to fully document each step. Instead, I’m going to link to the different pieces of documentation I used as reference during my setup and include additional notes to clarify what’s important and what you can safely ignore. I also hope to fill in a few gaps that I found in Linode’s documentation, so that you can benefit from the time I spent researching solutions to problems.

Note: CentOS 8 is based on Red Hat Enterprise Linux (RHEL) 8 which is based in turn on Fedora 28. Follow the appropriate instructions in the links below accordingly.

Provisioning

Provision your Linode using the instructions in Getting Started with Linode.

  1. Turn on Linode’s backup service and set a time for backups to occur in Linode Manager.
  2. Add a private IP address to the Linode, if needed, using the instructions found in the “Adding Private IP Addresses” section of Linode’s Remote Access documentation. (Private IP addresses are most useful if your Linode will be commumunicating with other Linodes [e.g. a database or redis server] in the same data center.)
  3. Add private IP addresses of other Linodes to /etc/hosts, if needed.

Domain Name Service (DNS)

  1. Set up DNS records for your new Linode at your DNS host or domain registrar.
  2. Set up Reverse DNS using the instructions found in Configure Your Linode for Reverse DNS (rDNS)

EPEL Repository

Install the EPEL repository, which includes extra useful packages not distributed with Centos 8:

sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y

Security

Secure your Linode using the instructions found in How to Secure Your Server.

  1. Set up your server to automatically install security updates using the instructions found in Automatic Security Updates with DNF.
    • Note: in /etc/dnf/automatic.conf, set:

      upgrade_type = security
      download_updates = yes
      apply_updates = yes

  2. SSH Daemon Options:
    • Create .ssh directory and copy public keys to server
    • Disable SSH password authentication
    • Permit SSH login on both IP4 and IP6 networks
  3. fail2ban is a software package that monitors your server for signs of possibly malicious access attempts and locks out IP addresses associated with these attempts. Install fail2ban using the instructions found in A Tutorial for Using Fail2ban to Secure Your Server and How to Install Fail2Ban to Protect SSH on CentOS/RHEL 8.
  4. Configure FirewallD to act as the firewall for your new server using the instructions found in Introduction to FirewallD on CentOS.
    • Commands:
      sudo firewall-cmd --zone=public --permanent --add-service=http
      sudo firewall-cmd --zone=public --permanent --add-service=https
    • Reboot the Linode to activate new permanent firewall rules.

Email Configuration

I don’t run my own email server, and you probably shouldn’t either. It’s just way too easy to misconfigure something and accidentally cause a security vulnerability. As a result, I configure my servers to send necessary email through SendGrid.

  1. Create a free account with SendGrid, if needed.
  2. Install Postfix:

    sudo dnf install postfix
    sudo dnf start postfix
    sudo dnf enable postfix

  3. Install mailx:

    sudo dnf install mailx

  4. Install SASL dependencies needed for Postfix/SendGrid connection:

    sudo dnf install cyrus-sasl-plain

  5. Log into SendGrid and create a “Full Access” API Key using the instructions in SendGrid API Keys.
  6. Configure Postfix for SendGrid using the instructions found in SendGrid Postfix.
  7. Send a test email to make sure email is configured correctly, replacing the email address with your own email address:

    echo "Test mail from Postfix" | mail -s "Test Postfix" you@domain.com

Apache Web Server

  1. Install Apache:

    sudo dnf module install httpd
    sudo systemctl enable httpd
    sudo systemctl start httpd

  2. Enable SELinux booleans needed to enable necessary features for Apache:

    sudo setsebool -P httpd_can_network_connect on
    sudo setsebool -P httpd_can_network_connect_db on
    sudo setsebool -P httpd_can_sendmail on
    sudo setsebool -P httpd_unified on

  3. Test Apache by visiting your server in a web browser. It should return the welcome page.

PHP

  1. Install the “remi” repository, which contains the newest versions of PHP for CentOS 8:

    sudo dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

  2. Install PHP 7.4:

    sudo dnf module install php:remi-7.4
    sudo dnf install php-sodium
    sudo systemctl enable php-fpm
    sudo systemctl start php-fpm

  3. Restart Apache so that it uses the newly installed php-fpm:

    sudo systemctl restart httpd

Test Apache with PHP-FPM

  1. Create file /var/www/html/info.php that contains only the single line:

    <?php phpinfo(); ?>

  2. In a web browser visit http://hostname.domain.com/info.php, replacing “hostname” and “domain” as needed. A PHP info page should be displayed that includes “FPM/FastCGI” as the “Server API”.
  3. Delete /var/www/html/info.php since it is no longer needed.

SSL Certificates

  1. In your DNS host or domain registrar, create a DNS record for a host named “centos8”, assigning it the IP address of your new server.
  2. Set up a virtual host for testing:
    • Create /etc/httpd/centos8.conf containing the following lines. Replace “email” and “domain.com” as needed.

      <VirtualHost *:80>
      ServerAdmin email@domain.com
      ServerName centos8.domain.com
      DocumentRoot /var/www/centos8/public_html/
      ErrorLog /var/www/centos8/logs/error.log
      CustomLog /var/www/centos8/logs/access.log combined

      <Directory "/var/www/centos8/public_html">
      Options FollowSymLinks
      AllowOverride All

      Order allow,deny
      Allow from all
      </Directory>

      </VirtualHost>

    • Create and configure the directories referenced in virtual host config file:

      sudo mkdir -p /var/www/centos8/public_html
      sudo mkdir -p /var/www/centos8/logs
      sudo chown -R apache:apache /var/www/centos8/
      sudo chmod -R 755 /var/www/centos8/

    • Reload Apache config files to start virtual host:

      sudo systemctl reload httpd

    • Create the file /var/www/centos8/public_html with the following contents:

      <html>
      <body>
      <h1>Hello World: CentOS 8</h1>
      </body>
      </html>

    • Visit http://centos8.domain.com (replacing “domain.com” as needed) in a web browser to test your new virtual host. (Note: this is regular HTTP.)
  3. Install wget (needed for Certbot installation below):

    sudo dnf install wget

  4. Certbot is a project of the EFF that aims to make it simple to install the free SSL certificates issued by Let’s Encrypt. Install Certbot by following the instructions on the Certbot website.
  5. Install an SSL certificate for centos8.domain.com, replacing “domain.com” as needed:

    sudo /usr/local/bin/certbot-auto --apache -d centos8.domain.com

  6. The IETF no longer recommends the use of TLS 1.0 and TLS 1.1, and the maintainers of major web browsers are removing support for these protocols. However, Certbot still installs support for TLS 1.0 and TSL 1.1. To correct this, the permitted cipher protocols used by Apache should be modified.
    • Open /etc/letsencrypt/option-ssl-apache.conf in an editor.
    • Find the line that includes “SSLProtocol” and change it to:

      SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

    • Restart Apache:

      sudo systemctl restart httpd

  7. Visit https://centos8.domain.com (replacing “domain.com” as needed) in a web browser to test the new SSL certificate.
  8. Use the SSL Labs SSL Server Test to test the SSL configuration.

MariaDB/MySQL

  1. Install mariadb module:

    sudo dnf module install mariadb

  2. Install and start the mariadb service:

    sudo systemctl enable mariadb
    sudo systemctl start mariadb

  3. Initialize and secure MariaDB:

    sudo mysql_secure_installation

Conclusion

I hope that these instructions are helpful and save your from having to perform some of the research that I had to do when setting this up for the first time. If you have any suggestions or corrections, please let me know.

Posted on February 5, 2020

Read More


Just completed spinning up my first server based on Centos 8. LAMP stack installed, secured, and (most importantly) documented.

Posted on February 3, 2020

Read More


? You know, all these permission denied errors could just go away. All it would take is disabling SELinux.

? Now you know that’s not the right answer. You’d solve your problem today, but security would be compromised forever.

? But at least the problem would be solved!

⚖️?

Posted on February 1, 2020

Read More


Impeachment trial drinking game: Every time someone cites Alexander Hamilton, burst into song.

? Alexander Hamilton. My name is Alexander Hamilton. And there’s a million things I haven’t done, but just you wait, just you wait… ?

Posted on January 29, 2020

Read More


I’m on a baking spree this weekend, trying to work on my shaping skills. (I have a tendency to degas the dough too much when forming loaves.) I shaped 3 yesterday and will do 3 more today. That’s 9 lbs (4 kg) of dough. I’ve got bread coming out of my ears!

Posted on January 19, 2020

Read More


Every time I get an email from Stripe confirming a customer’s credit card has been charged, I think, “I should really turn those off. They just clutter my inbox.”

But that’s really the only email I actually *enjoy* receiving. So maybe I’ll leave them on for just a bit longer.

Posted on January 7, 2020

Read More


…and two more loaves to bake tomorrow!

Posted on January 5, 2020

Read More