How to Install WordPress on Ubuntu + Apache


How to Install WordPress on Ubuntu + Apache Without Breaking Existing Sites

If you’re running multiple sites on a single Ubuntu server with Apache, you’ve probably run into the issue where a new site loads the wrong content — like your WHMCS showing up when you try to access your WordPress subdomain.

In this tutorial, we’ll go step-by-step through a proper WordPress installation on Ubuntu + Apache, ensuring each site is isolated, secure, and working on both HTTP and HTTPS from the start.


1. Prerequisites

Before we begin, make sure you have:

  • Ubuntu server with Apache installed
  • MySQL or MariaDB installed
  • PHP 7.4+ with required extensions: sudo apt install php php-mysql php-xml php-curl php-mbstring php-zip unzip
  • SSH access as a sudo user
  • DNS record pointing your domain/subdomain (e.g. tutorials.example.com) to your server IP

2. Create the Apache VirtualHost

We’ll create a dedicated vhost file so Apache knows exactly where to send requests.

sudo nano /etc/apache2/sites-available/tutorials.example.com.conf

Add:

<VirtualHost *:80>
    ServerName tutorials.example.com
    DocumentRoot /var/www/tutorials

    <Directory /var/www/tutorials>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/tutorials_error.log
    CustomLog ${APACHE_LOG_DIR}/tutorials_access.log combined
</VirtualHost>

Enable the site & reload Apache:

sudo mkdir -p /var/www/tutorials
sudo chown -R www-data:www-data /var/www/tutorials
sudo chmod -R 755 /var/www/tutorials

sudo a2ensite tutorials.example.com.conf
sudo a2enmod rewrite
sudo systemctl reload apache2

Lesson learned:
If you skip this and reuse your default vhost, Apache may serve the wrong DocumentRoot (like WHMCS).


3. Create a Separate MySQL Database & User

Using unique credentials prevents cross-access between applications.

sudo mysql -u root -p

Inside MySQL:

CREATE DATABASE tutorials_wp;
CREATE USER 'wp_user_tutorials'@'localhost' IDENTIFIED BY 'StrongP@ssw0rd!';
GRANT ALL PRIVILEGES ON tutorials_wp.* TO 'wp_user_tutorials'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Lesson learned:
Never reuse WHMCS’s database or user for WordPress.


4. Download & Configure WordPress

cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xvzf latest.tar.gz
sudo mv wordpress/* /var/www/tutorials/
sudo chown -R www-data:www-data /var/www/tutorials
sudo chmod -R 755 /var/www/tutorials

5. Configure wp-config.php

cd /var/www/tutorials
cp wp-config-sample.php wp-config.php
nano wp-config.php

Update with your credentials:

define( 'DB_NAME', 'tutorials_wp' );
define( 'DB_USER', 'wp_user_tutorials' );
define( 'DB_PASSWORD', 'StrongP@ssw0rd!' );
define( 'DB_HOST', 'localhost' );
$table_prefix = 'wpx9_'; // Random, secure prefix

Lesson learned:
Change the table prefix during installation to avoid predictable defaults.


6. Set Up HTTPS (Avoid the Wrong SSL Problem)

If you skip creating an SSL vhost, HTTPS requests may default to another site’s SSL config (like WHMCS).
We’ll use Certbot to handle it automatically:

sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d tutorials.example.com

Lesson learned:
Always create an SSL vhost for the new site immediately after enabling HTTP.


7. Complete the WordPress Installation

Visit:

https://tutorials.example.com
  • Choose language
  • Set site title, admin username, password (unique from WHMCS)
  • Log in and start building

8. Secure and Maintain

  • Install a firewall: sudo ufw allow 'Apache Full'
  • Keep packages updated: sudo apt update && sudo apt upgrade -y
  • Install a security plugin like Wordfence.

Final Thoughts

By giving WordPress its own VirtualHost, DocumentRoot, database, user, table prefix, and SSL config, you completely avoid the common pitfalls we faced when tutorials.lineserve.net kept loading WHMCS.

This setup ensures both sites run independently, securely, and without conflicts — no matter how many other apps you host on the same server.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *