Tania Rascia

Skip Navigation
How to Install Apache, PHP 7.1, and MySQL on Ubuntu with Vagrant

How to Install Apache, PHP 7.1, and MySQL on Ubuntu with Vagrant

 /  50 responses

In order to run a server locally, we need to set up an environment for the stack, or server, database, and language, to run in. An easy way for beginners to do that is to set up MAMP on Mac or Windows, which sets up the environment for you.

As you become a more advanced developer, you might need to create a local environment that matches your production server more closely. If you’re working locally on Windows or Mac, and your server is on a Linux distribution, you may encounter bugs and errors that are specific to the operating system the server is running and you won’t be able to troubleshoot them properly.

Fortunately, we have tools like Vagrant and VirtualBox that allow us to set up a virtual machine locally that can match the production environment. In this tutorial, we’ll take an Ubuntu Server operating system that has been set up on Vagrant and install a LAMP stack on it.


There are two prerequisites to complete before reading this tutorial.


In this tutorial, we’re going to accomplish the following:

  • Install LAMP (Apache, PHP 7.1, MySQL) on an Ubuntu Server 14.04 virtual machine
  • View the server in a browser via IP address and custom domain name
  • Link your local files with the virtual machine to be able to develop on the Vagrant environment from your local computer
  • Connect to MySQL via SequelPro (or any database program)

Step 1 – Install Apache

The examples in this article use the .dev suffix for custom domains. This suffix is no longer allowed. You can use .test in place of .dev throughout this article.

We’re beginning this article where the last one left off – with a brand new Ubuntu virtual machine set up. Navigate to the directory you have your Ubuntu set up in, and ssh into the machine.

vagrant ssh

apt-get is command line software for installing packages on Ubuntu. Let’s run the commands to update and upgrade the package manager and make sure everything is up to date.

sudo apt-get update && sudo apt-get upgrade

Now we’re going to install the latest version of Apache, which is 2.4.7 at the time of this writing.

sudo apt-get install apache2 -y

After installing it you’ll get this warning.

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using Set the 'ServerName' directive globally to suppress this message

Easily fixed. We’re just going to set the ServerName to localhost. Use nano (or vi, or whatever you feel comfortable with) to edit the apache2 configuration file.

sudo nano /etc/apache2/apache2.conf

If you’re not familiar with nano, or editing files through the Terminal, please review the command line article.

Navigate all the way to the end of the file, and insert this line at the bottom.

ServerName localhost

Save and close nano (cntl + o, cntl + x), then restart Apache to apply the changes.

sudo service apache2 restart
* Restarting web server apache2 [ OK ]

You can check to make sure the ServerName is correct with the following command.

sudo apache2ctl configtest
Syntax OK

I always like to check the version number to see exactly what I’m running.

apache2 -v
Server version: Apache/2.4.7 (Ubuntu) Server built: Jun 26 2017 13:53:34

Great, Apache is up and running properly! But now we want confirmation of this.

Step 2 – Map a local domain to the IP and view the server

Now, usually when you set up a production server, you can navigate to the IP address or domain name of the server in your browser and see either the “New Linux installation” page, or your website, if you’ve already added it. We’re going to do the same thing right now, except instead of connecting to a public facing server, we’re connecting to our own local virtual machine.

I’m running my virtual machine in the following directory.


Within this directory, you’ll see two files – .vagrant, and Vagrantfile. Open your Vagrantfile, as this is the local configuration file we’ll need to edit to make any changes.

Find the “private_network” configuration line, which should look like this.

# config.vm.network "private_network", ip: ""

And uncomment it.

config.vm.network "private_network", ip: ""

Reboot Ubuntu to make sure the Vagrantfile changes take effect. Run the reload command from back in your local computer’s terminal.

vagrant reload

We’re going to make a custom domain to access this address and view it in our browser. Still in your local computer, edit your local hosts file.

sudo nano /etc/hosts

Add a new domain to the bottom with the IP address we were given. I’m calling it trusty.dev.  trusty.dev

Save and exit nano. Now in Google Chrome or whatever browser you’re using, go to trusty.dev. Now you should see the default Linux success page. It works!

You can also navigate to in the browser now, and it will work as well.

Step 3 – Install PHP 7.1

At this point, we’re going to install PHP 7.1. Since 7.1 is new and cutting edge, it is not available in the regular apt repository. We’re going to use a PPA (Personal Package Archive) to install this non-standard software.

Add the Onrej PPA to your machine.

sudo apt-add-repository ppa:ondrej/php

Update apt-get with the software from the new repository.

sudo apt-get update

Now you will be able to install PHP 7.1.

sudo apt-get install php7.1

Confirm successful installation of PHP by checking the version.

php -v
PHP 7.1.6-2~ubuntu14.04.1+deb.sury.org+1 (cli) (built: Jun 14 2017 05:58:40) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.1.6-2~ubuntu14.04.1+deb.sury.org+1, Copyright (c) 1999-2017, by Zend Technologies

Step 4 – Link a local folder with the virtual machine

Okay, using nano or vi to edit files is going to start getting tedious. I want to be able to edit the files within the virtual machine from within the comfort of my own computer’s environment (currently using Visual Studio Code as a text editor).

In order to do this, we’re going to need to link a folder on our local computer to one on the virtual machine.

Right now, the Ubuntu default page exists on /var/www/html, the public facing folder on an Apache server. Back in our local (Windows or Mac) computer, let’s create a www folder in the root directory, and create two files: connect.php and test.php, which we’ll use to test MySQL and PHP in a moment.

Here is how our local directory structure should be set up:

Let’s go back to our Vagrantfile. We’re going to set up a synced folder, first inputting our local path, then inputting our virtual machine’s path.

config.vm.synced_folder "LOCAL", "VIRTUAL"

We’ll set the www folder we just made as the local folder, and the public server directory for Ubuntu.

config.vm.synced_folder "www/", "/var/www/html"

Now vagrant reload, or vagrant halt and vagrant up to restart Ubuntu. Now when you go to your server you should see this.

Success! Your local folder has now synced with the Ubuntu server, and every change you make there will be reflected in the server.

Step 5 – Install MySQL

Finally, we’re going to install MySQL for database access.

Installation within Ubuntu

sudo apt-get install mysql-server php7.1-mysql

You can also set up the mysql secure installation. Follow the instructions on the page. Since we’re doing a local environment, it doesn’t need to be as secure as a production environment. You can leave the ports open for us to access later.

sudo mysql_secure_installation

As far as I can tell, that’s a lie. When it came to this point, I just put “root” as the password.

I found some good directions on configuring MySQL with Vagrant here. Edit your MySQL configuration file.

sudo nano /etc/mysql/my.cnf

Find skip-external-locking and bind-address and comment them out.

# skip-external-locking
# bind-address

Once that’s all done, I restart Apache and MySQL.

sudo service apache2 restart
sudo service mysql restart

At this point, you should be able to login to MySQL with root, using password root.

mysql -u root -p

I found the easiest way to setup MySQL to allow entry via SequelPro or another 3rd party is to set up a new user. I encountered issues connecting with root, and found some solutions on Stack Overflow.

While inside the command line mysql, create a new user and password. I literally used “user” and “password” for those fields.

CREATE USER 'user'@'%' IDENTIFIED BY 'password';

Granted all privileges to the new user.


And flushed privileges.


Now to restart Apache and MySQL once again.

sudo service apache2 restart
sudo service mysql restart

Local setup to access MySQL

Everything should be set from the Ubuntu side for MySQL setup. We’re going to need to do a few things to connect to MySQL via SequelPro now.

First, edit the VagrantFile and add this line to recognize the MySQL port, 3306.

config.vm.network "forwarded_port", guest: 3306, host: 3306 

You’ll need to restart Vagrant for this to take effect.

vagrant reload

Now open up SequelPro, or your database program (SQLYog for Windows) to connect.

We’ll need to use the SSH tab of the connection. There are two connections we’ll need to make – MySQL and SSH.

For MySQL, the credentials will be:

Username: user
Password: password
Port: 3306

For SSH, they will be:

User: vagrant
Key: ~/.vagrant.d/insecure_private_key
Port: 2222

In your home folder, there will be a hidden directory called .vagrant.d. Inside is a file called insecure_private_key, which is the key the vagrant ssh command uses to connect.

Running vagrant ssh is the same as running the following:

ssh -i ~/.vagrant.d/insecure_private_key [email protected]

Inputting all the following credentials, we will be prompted for a password.

The password is “vagrant”

Update 3/5/2018: This key may not work in newer versions of Ubuntu. Instead, you will run vagrant ssh-config from your local computer, and follow the file path for IdentityFile. Mine was /Users/my_path/ubuntu/.vagrant/machines/default/virtualbox/private_key. Use this instead of ~/.vagrant.d/insecure_private_key.

Now if everything went well, we’ll be in! If you had any issues up to this point, please let me know and I’ll see if I can make it more clear.

Since I’m in, I’m just going to create a database called test and a table called table1 so I can test MySQL via PHP.

Step 6 – Testing PHP and MySQL

Using the connect.php and test.php files we made in /var/www/html before, let’s test PHP and MySQL from the browser.

In test.php, we’ll use the phpinfo() function to test PHP.

<?php phpinfo();

In connect.php, I used a quick MySQL test script to make sure everything is connecting.


$dbname = 'test';
$dbuser = 'user';
$dbpass = 'password';
$dbhost = '';

$link = mysqli_connect($dbhost, $dbuser, $dbpass) or die("Unable to Connect to '$dbhost'");
mysqli_select_db($link, $dbname) or die("Could not open the db '$dbname'");

$test_query = "SHOW TABLES FROM $dbname";
$result = mysqli_query($link, $test_query);
$tblCnt = 0;

while($tbl = mysqli_fetch_array($result)) {

if (!$tblCnt) {
  echo "There are no tables<br />\n";
} else {
  echo "There are $tblCnt tables<br />\n";

And I can see that MySQL is connecting properly.


We went over a lot in this article. Creating a production environment, installing a LAMP server, accessing a virtual machine server and database from your local computer, and syncing folders between local and virtual machine. Now we have a complete local Ubuntu environment that can match a production environment we might be working on.


Get updated when I create new content.
Unsubscribe whenever. Never any spam.


I'm Tania. I turn down every ad, affiliate, and sponsor request I get. I write free resources that help thousands of people successfully become devs. If you enjoy my content, please consider supporting what I do.

Support my work

Write a response

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

All code will be displayed literally.


  • john says:

    Hi Tania, I am having an issue with my accessing the vm from my browser via domain name. I uncommented the static ip line in the Vagrantfile and updated my /etc/hosts file to with the static ip and trusty.dev. The strange part is that the ip address gets me to the apache page in chrome but the domain refuses connection. Ping even works for trusty.dev and lists the correct static ip. Any suggestions for getting chrome to connect with using the host domain?

  • Jonathan Ornstein says:

    Hi Tania, you saved me hours of searching and frustration by your concise, easy to understand and accurate tutorials. Really grateful! One thing: I managed to log in perfectly OK from Workbench used Win10, using the 192.168.etc ip address and the SSH info (C:\Users\moi\devt\virtualmachines\xenial\.vagrant\machines\default\virtualbox\private_key works like a charm). However, I was not allowed to log in to my MySQL database from PHP using 192.168.etc IP address using the address in connect.php. I was wondering if I overlooked how to pass the SSH info to PHP? Thanks!! Jonathan

  • Jean Levasseur says:

    What an amazing guide!! Thank you so much! I'm very new to web development and this gives me a good sandbox to play with!

    I just did installed the most recent Vagrant Ubuntu box (ubuntu/bionic64), which seemed logical since it is a LTS release. Here are some little hiccups I came through:

    1. I didn't need to install any PPA, since PHP7.2 is now in the ubuntu repos (called 'php')
    2. I had to install 'libapache2-mod-php' to make php work. It didn't install by default.
    3. The mysql conf file now resides at '/etc/mysql/mysql.conf.d/mysql.cnf'
    4. The mysql config is somewhat different. For some reason, I had to first login using sudo to do all the manipulations you described. Not sure exactly why.

    Thanks for the great guides!

  • Matheus says:

    This helped me out a lot, thanks Tania!

  • Ayyappa boligala says:

    Good document for Tania!

  • Daniel Pacheco Yarleque says:

    Hazlo con el provision!!!

  • nbr says:

    Great! Thank you

  • JD says:

    Muy buena aportación, me ayudó bastante, muchas gracias. Es el mejor tutorial 🙂

  • Abdul Gaffar says:

    You are really master. You saved my life.
    Thanks very much everything works fine except mysql connect to Sequel Pro.
    But I have installed adminer and everything works fine

  • Hanhan says:

    I had to uncomment this line of code

    config.vm.network :forwarded_port, guest: 80, host: 80

    for the host and the guest to make connection

  • Oliver Russell says:

    Manually install PHP 7.1 and MySQL with Apache web server on a hosting is quite a difficult task. For example, setting up AWS server is quite difficult and time taking. So instead of doing it manually, it is better to use Cloudways PHP MySQL hosting (https://www.cloudways.com/en/php-cloud-hosting.php ) platform that automatically setups OS and stack on the server.

  • Rick says:

    Great tutorials. Any tips on getting mod_rewrite working with this virtual server?

    I have it enabled with “sudo a2enmod rewrite”, but I think there is an “AllowOverride All” directive I need to make in an apache file. No luck with my trial and error finding it yet.


    • Rick says:

      Nevermind. It finally worked. Here is what I did…

      1. ssh in
      2. edit apache2.conf
      3. for Directory var>www, change AllowOverride None to AllowOverride All
      4. restart apache

  • Tavo Santiago says:

    Great tutorial, it was amazing. I’m having trouble with being able to see “there are 1 tables” when I do trusty.dev/connect.php it just downloads the file, anyone experiencing the same?

  • Anonymous says:

    The best!

  • Derek Bell says:

    Hi Tania,

    Thankyou so much for your clearly written guide. It all worked perfectly.

    The only hitch I got was Mysql port 3306 colliding with my local installation. That was easily fixed by changing to port 3307.


  • Susan says:

    Thanks a lot, this is really helpful. I am at the point where I am loading the Linux success page. For some reason, works while trusty.dev does not. I’m not sure why…do you know?

    I get this error message on Google Chrome:

    This site can’t be reached
    trusty.dev refused to connect.

    Checking the connection
    Checking the proxy and the firewall

    • Tania says:

      Hi Susan,

      You can no longer use .dev extensions for local setups on Chrome. I’ll leave a note. I use .test now.

      • Anonymous says:

        I have the same problem, and using trusty.test instead of trusty.dev doesn’t help (in Chrome) and in any case the same problem presents using Firefox. That is (for absolute clarity!), the ip address returns the Apache2 Ubuntu page, but http://trusty.dev (or .test, or anything else) is not found. I’ve followed your instructions to the letter, so it’s puzzling. Any thoughts?

      • Lou B. says:

        Neither .dev nor .test work for me in either browser. I’ve read somewhere that now chrome 63+ forces .dev domains to https.

    • Walter says:

      Just installed failed on Mozilla works OK on Chromium

  • Jun Liu says:

    Thank you so much!

    This is to test connection on the MySQL from SequalPro:

    “Now if everything went well, we’ll be in! If you had any issues up to this point, please let me know and I’ll see if I can make it more clear.”

    I got the following popup window at this point:

    SSH port forwarding failed

    Unable to connect to host because the port connection via SSH was refused.

    Please ensure that your MySQL host is set up to allow TCP/IP connections (no –skip-networking) and is configured to allow connections from the host you are tunnelling via.

    You may also want to check the port is correct and that you have the necessary privileges.

    Checking the error detail will show the SSH debug log which may provide more details.

    MySQL said: Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0

    • Jun Liu says:

      My bad, did not follow this in the instruction:


      Find skip-external-locking and bind-address and comment them out.

  • Tom says:

    Hi, I have a little problem here. I’m running windows so I had to install SQLYog. However SQLYog free version doesn’t support ssh connection. So I’ve tried looking for some alternatives, bunched into MySQL workbench but that’s just really confusing and I’ve failed to connect multiple times. (It somehows require to combine the 2 separate connections into one, “TCP/IP over SSH”).
    Could you help me out somehow? Maybe point me to something different?

    • Matt says:

      Tom, I would use HeidiSQL as it is free and comes with an SSH Tunneling Option. A tip when using it is to not make your .ppk file passphrase protected as HeidiSQL does not support that

  • Stas says:

    I highly recommend Codelobster IDE to work with PHP on Ubuntu: http://www.codelobsteride.com

  • Francisco Quintero says:

    Nice tuto 🙂

    You should consider to mention installing libapache2-mod-php7.1 for PHP-7.1 to work correctly with Apache 2.

  • Toudi says:

    Hi, first of all thx for a great tutorial, however I am stacked with ERR_ICANN_NAME_COLLISION trying to access my trusty.dev. Any suggestions highly appreciated 🙂

  • Mudassar says:

    Thanks a lot, wonderfull article that clears my concepts for Vagrant and virtualbox..

  • Srikanth says:

    thanks alot..lot of time save..

  • Ryadh says:

    I have just discovered your wonderful website!
    I am having trouble to use SSH to connect on SequelPro. Here is the error message:

    Used command: /usr/bin/ssh -v -N -S none -o ControlMaster=no -o ExitOnForwardFailure=yes -o ConnectTimeout=10 -o NumberOfPasswordPrompts=3 -o TCPKeepAlive=no -o ServerAliveInterval=60 -o ServerAliveCountMax=1 -p 2222 [email protected] -L 56037:

    OpenSSH_6.9p1, LibreSSL 2.1.8
    debug1: Reading configuration data /etc/ssh/ssh_config
    debug1: /etc/ssh/ssh_config line 21: Applying options for *
    debug1: Control socket ” none” does not exist
    debug1: Connecting to [] port 2222.
    debug1: fd 3 clearing O_NONBLOCK
    debug1: Connection established.
    debug1: key_load_public: No such file or directory
    debug1: identity file /Users/rr/.ssh/id_rsa type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /Users/rr/.ssh/id_rsa-cert type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /Users/rr/.ssh/id_dsa type -1
    debug1: key_load_public: No such file or directory
    debug1: identity file /Users/rr/.ssh/id_dsa-cert type -1
    debug1: key_load_public: No such file or directory

    Could you please advise?
    Thank you

  • Aze says:

    Very well written. Thanks a lot.

  • Cristian says:

    This is a wonderful tutorial which has just introduced me to Vagrant and who knows where else.

    I’m on a Mac and I have created exactly the same local folder www as you did to store the webpage files. Regretfully, I’m having issues with the subfolders permissions as they all inherit read only for the everyone group. Then, when my webpage tries to write to some file in the server, it has no access.

    I tried to implement the ACL solution for the permissions inheritance but I’m not able to make it work properly. Do you have any suggestions?

    Thanks a lot and warmest regards.

    • Cristian says:


      I have just fond my answer and I’m so happy. I do not need to mess with folder permissions in the Mac but only add some little options when mounting the synced folder in the Vagrantfile:

      config.vm.synced_folder “www/”, “/var/www/html”, :mount_options => [“dmode=777”, “fmode=666”]

      To be honest, I have not found what dmode and smode do stand for, but it is definitely related to permissions and giving a 7 to the everyone group is solving my issues.

      Best regards.

  • Anon says:

    Excellent summary. Question:

    Everything works fine using the same base box until I get to connecting SequelPro.

    SqlPro either keeps asking me for a password or it doesn’t allow me to connect at all. Standard connection to works but ssh to doesn’t. Any ideas?

    Also note that if one is using a newer ubuntu base box e.g. 16.04, the config file seems to be located at /etc/mysql/mysql.conf.d/mysqld.cnf

    • Cristian says:

      Hi Anon.

      I have upgraded to Ubuntu 16 and I had the same problem as you. The solution is to change the SSH Key file for the same one used by vagrant.

      At your terminal, type:
      vagrant ssh-config

      And look for the IdentityFile. Mine was /Users/myuser/VirtualBox VMs/ubuntu/.vagrant/machines/default/virtualbox/private_key

      You just have to use that file as the SSH Key in Sequel Pro.

      Hope it works. Best regards.

    • Ian P says:

      Lifesaver, Anon.

  • Markus Birner says:

    Hi Tania,

    again two absolutely great tutorials. I was able to reproduce every step without any problem or unclarity. Thanks for such great work!

    Best regards

  • david says:

    thanks for this very good info. everything went well for me until when I need to confi.vm.synced_folder. then my vm just won’t reload and won’t shut down. my php is also stuck at version 5 because i was not able to use “sudo add-apt-repository ppa:ondrej/php” kept getting “sudo: apt-get: command not found”

    I got around this with “sudo apt-get install software-properties-common” followed by “sudo add-apt-repository ppa:ondrej/php” then the update and finally installed 7.1

    but still unable to do a vagrant reload. any ideas?

  • chris says:

    Thank you very much for writing these awesome tutorials!
    Everything worked for me up until the part where I add this line to the VagrantFile:

    config.vm.network “forwarded_port”, guest: 3306, host: 3306

    when I try to ‘vagrant reload’, the following error message appears:

    “Vagrant cannot forward the specified ports on this VM, since they
    would collide with some other application that is already listening
    on these ports. The forwarded port to 3306 is already in use
    on the host machine.

    To fix this, modify your current project’s Vagrantfile to use another
    port. Example, where ‘1234’ would be replaced by a unique host port:

    config.vm.network :forwarded_port, guest: 3306, host: 1234

    (…) ”

    Any ideas what could be the problem?

    Thank you so much!

    • Tania says:

      Hi! Are you running MAMP/WAMP/XAMPP currently? If you have any currently running MySQL processes, I’m guessing you’d have to shut them down before setting up this process. The only other thing I might suggest is changing all the ports to 3307 (or something) for this installation, so it doesn’t interfere with the one you already have running.

    • Anon says:

      You get this error whenever there is a port collision with other Vagrant machines on your system.
      Type vagrant global-status
      Note the id (first column) in the output.
      Type vagrant port [id] for each id and see which ports are being mapped to 3306 and remap them to something else, like 1234 or 4321.

      If you have many unwanted machines just run vagrant destroy [id] -f . WARNING: This command will remove the VM from your machine.

      Hope this helps.

      Also great tutorial!

      • chris says:

        Yes! Thank you both for your answers.

        Tried the 3307 port and it works now.