How to Install WordPress into a VirtualHost on an Ubuntu LAMP Server

There are many tutorials on the internet explaining how to install WordPress on your LAMP server, however, these rarely go into detail on how to do it as a VirtualHost, for example if you have multiple websites on the same server, you will need to do this.


Before you can start following this guide, you need to ensure:

  • You have a linux user with ‘sudo’ capability
  • You have LAMP installed on your server
  • You have a provider such as cloudflare to host subdomains, SSL etc
  • You have a domain (e.g.

Step 1 – Creating a MySQL Database for WordPress

WordPress uses SQL to manage and store site and user information, so we need to create a database for it to store said information.

To get started, log in to MySQL with the following command:

mysql -u root -p

You will be prompted to enter the password that you setup when installing the software.

Now, to create the database you need to give it a name, I have chosen the name ‘wordpress’ but you can change it to whatever you want.

mysql> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Note: Every MySQL statement MUST end in a semi-colon. If you are running into any issues, please check that this is present.

Now you need to allow root to access your database:

mysql> GRANT ALL ON wordpress.* TO 'root'@'localhost' IDENTIFIED BY 'password';

‘password’ is the password you setup when installing the software, it is also the same one you used to login to the MySQL CLI interface.

Now you need to run the flush privileges command to refresh MySQL so it knows about the changes we just made:


Now exit out of MySQL by typing:

mysql> EXIT;

Step 2 – Add additional PHP functionality

For WordPress to function correctly, we need to install some extra PHP extensions:

sudo apt update
sudo apt install php-curl php-gd php-mbstring php-mcrypt php-xml php-xmlrpc

Now, restart Apache so it can take advantage of these new extensions:

sudo systemctl restart apache2

Step 3 – Allowing .htaccess overrides and rewrites

We need to make some adjustments to our Apache configuration so that WordPress can use all of its plugins correctly. To do this we need to enable the use of the .htaccess file.

Enable .htaccess overrides by running this command:

sudo nano /etc/apache2/apache2.conf

To allow the use of .htaccess files, we need to set the AllowOverride directive within a Directory block pointing to the document root. Towards the bottom of the file, add this block:

<Directory /var/www/html>
    AllowOverride All

When you are finished, save and exit nano.

Now, you need to enable .htaccess rewrites, to do this, run:

sudo a2enmod rewrite

Check the syntax of Apache2 by running:

sudo apache2ctl configtest

If it says ‘Syntax OK’ anywhere in the output, you’re good to go. Now, restart apache to implement the changes.

sudo systemctl restart apache2

Step 4 – Setting up the VirtualHost

You first need to create the folder that wordpress is going to go in. I will use the domain but you should use your actual domain as the top folder name. We are also going to add a public_html directory inside as this lets Apache know that our site should be public.

sudo mkdir -p /var/www/

Now we need to setup the user permissions so that we can copy the WordPress directories into this directory:

sudo chown -R $USER:$USER /var/www/

If you haven’t already, you should change the permission set on /var/www to 755:

sudo chmod -R 755 /var/www

Now, we need to create the VirtualHost configuration files, again, I am using, so my file will be but yours should be {YourDomain}.conf

sudo nano /etc/apache2/sites-available/

You can use the parameters below as a template, just remember to replace with your domain. If you are using a subdomain; e.g., then don’t include the second block with www in.

<VirtualHost *:80>
  ServerAlias localhost
  DocumentRoot "/var/www/"
  <Directory "/var/www/">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted

<VirtualHost *:80>
  ServerAlias localhost
  DocumentRoot "/var/www/"
  <Directory "/var/www/">
    Options +Indexes +Includes +FollowSymLinks +MultiViews
    AllowOverride All
    Require all granted

Now, ensure you have added your domain into CloudFlare, or other web provider.

Step 5 – Downloading and installing WordPress

Start by navigating to the tmp folder on your Ubuntu installation and downloading the latest version of WordPress.

cd /tmp
curl -O

Once you have done this, extract the file:

tar xzvf latest.tar.gz

Now you need to create and adjust the permissions for the .htaccess file

sudo touch /tmp/wordpress/.htaccess
sudo chmod 660 /tmp/wordpress/.htaccess

You also need to copy the sample config file to the proper wp-config.php:

sudo cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php

Now, you should create the upgrade directory, so that WordPress won’t run into permission issues when trying to do this on its own following an update to its software:

sudo mkdir /tmp/wordpress/wp-content/upgrade

Now, you need to copy WordPress to your VirtualHost folder. Mine is but you should substitute this for your domain name. This is simply just the directory that we created earlier.

sudo cp -a /tmp/wordpress/. /var/www/

Step 6 – Configuring the WordPress directory

You need to adjust the permissions on the directory so that both WordPress and your user can access the information.

My username on my box is ‘administrator’ but you should substitute administrator for your own username on your Ubuntu server. Again, you should substitute for your own domain.

sudo chown -R administrator:www-data /var/www/

Next, set the setgid bit on every directory by running this command. Ensure that is substituted for your own domain.

sudo find /var/www/ -type d -exec chmod g+s {} \;

You also need to set the permissions on the wp-content folder so that all your content can be accessed correctly by the software. Ensure is replaced by your own domain name.

sudo chmod g+w /var/www/

You also need to give the server write access to all of the content in these two directories. Do not use, instead, ensure that you use your own domain name:

sudo chmod -R g+w /var/www/
sudo chmod -R g+w /var/www/

Now, you need to setup the configuration file, firstly run this command:

curl -s

You’ll get an output like this:

Warning! It is important that you request unique values each time. Do NOT copy the values shown below!
define('AUTH_KEY',         '1jl/vqfs<XhdXoAPz9 DO NOT COPY THESE VALUES c_j{iwqD^<+c9.k<J@4H');
define('SECURE_AUTH_KEY',  'E2N-h2]Dcvp+aS/p7X DO NOT COPY THESE VALUES {Ka(f;rv?Pxf})CgLi-3');
define('LOGGED_IN_KEY',    'W(50,{W^,OPB%PB<JF DO NOT COPY THESE VALUES 2;y&,2m%3]R6DUth[;88');
define('NONCE_KEY',        'll,4UC)7ua+8<!4VM+ DO NOT COPY THESE VALUES #`DXF+[$atzM7 o^-C7g');
define('AUTH_SALT',        'koMrurzOA+|L_lG}kf DO NOT COPY THESE VALUES  07VC*Lj*lD&?3w!BT#-');
define('SECURE_AUTH_SALT', 'p32*p,]z%LZ+pAu:VY DO NOT COPY THESE VALUES C-?y+K0DK_+F|0h{!_xY');
define('LOGGED_IN_SALT',   'i^/G2W7!-1H2OQ+t$3 DO NOT COPY THESE VALUES t6**bRVFSD[Hi])-qS`|');
define('NONCE_SALT',       'Q6]U:K?j4L%Z]}h^q7 DO NOT COPY THESE VALUES 1% ^qUswWgn+6&xqHN&%');
Again, Do NOT copy the values above, generate your own using the curl command above!

Now open the wp-config.php file in nano, like so. Ensure that is substituted for your own domain name:

sudo nano /var/www/

Find the section that contains the dummy values for the settings you copied before, it’ll look something like this:

. . .

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

. . .

Then, copy your values that you generated from the curl command:

. . .

define('AUTH_KEY',         'VALUES COPIED FROM CLI');

. . .

Now remember those values we setup in step 1 for the MySQL database, we need them now. I called my database ‘wordpress’ but you should substitute that for whatever you called yours, you should also substitute ‘password’ for the password you setup when installing the software.

Below this, you should also add define( ‘FS_METHOD’, ‘direct’); as this will allow you to install plugins and themes.

. . .

define('DB_NAME', 'wordpress');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'password');

. . .

define('FS_METHOD', 'direct');

Save and close nano when you have done this.

Step 7 – HTTPS and final permission configuration

There are a few more commands that you need to run to allow the installation of plugins and themes. Replace with your domain:

cd /var/www/
sudo chown -R www-data:www-data wp-content
sudo chmod -R 755 wp-content 

You also need to add this block of code to the wp-config.php file, right at the top, on Line 2, underneath <?php. It’ll look something like this, make sure is replaced with your own domain.

sudo nano /var/www/

This is the code you need to add:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)

It’ll look something like this when done:

if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false)

. . .

Step 8 – Finish through the web interface

Go into a web browser and navigate to your domain, for me, You’ll be greeted with a graphical setup page, just simply follow it through!

Once you’re in the admin page, you might need to adjust http to https. To do this, follow these instructions, this will ensure that your page is fully encrypted:

Click on the Settings button.
Change http to https, as above.

That’s it, you now have a fully working WordPress installation, inside a VirtualHost on Apache! If you have any questions, please use the form on the Contact page. 🙂


Leave a Reply

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