Hi, on this blog post I'll will try to show you how to set up a Drupal development environment under VirtualBox which is a virtualization tool that allows us to create Virtual Machines or in our case Virtual Private Servers (VPS).
I'm writing this post so developers can have a different alternative to the current dockerized solutions such as Lando, Docksal or DDEV since I have found, during the time these tools are out, developers struggling a lot with their configuration, performance and set up of Drupal projects. Even though I agree they can save us sometime with some processes once a project is set up or updated and they might be good to cover up for some Non-Linux users so they don't have to deal with Linux commands I think having a bit of knowledge of Linux is key when it comes to working with LAMP applications. Using a Virtualized component or a virtual machine to set up your Drupal/PHP projects will not only help you understand a new technology besides Docker, but feel the impact on performance, learn how to install a Linux server and configure step by step your LAMP stack, keep in mind that mimicking you production environment will reduce the chance of errors in a big percentage when a deploy is performed.
Well, let's begin. Go to the VirtualBox page and download the package depending on your Operative System, I'm going to be using a Mac so I'll be downloading the .dmg image. At the time of this post VirtualBox current version is 7.0.10. Next, run the install process:
Installing VirtualBox is a pretty straightforward procedure so I usually use the defaults so click on "Continue" until the installation process finishes. If all went well you should get a window like the following:
Once installed, open up a terminal window and run:
## Add your user to the vboxusers group.
$ sudo usermod -a -G vboxusers $USER
Then, just look in your Operative System for the VirtualBox launcher and launch the application, the screen you should get must look like this:
Now, let the fun begin! First, we need to grab a new Ubuntu Server .ISO image from the Ubuntu website, you can try a different Linux flavor of your preference if you'd like but this post is going to be focused on Ubuntu 22.04 LTS, here the direct link to download Ubuntu Server 22.04 LTS - download ubuntu server
Why 22.04, because it comes bundled with PHP 8.1.2 in the repositories which is a requirement for Drupal 9.5+ and Drupal 10.
Once done downloading the .ISO file go to VirtualBox and click on the NEW button on the top of the screen, the New Screen will show up looking like this:
Give it a name, for example, Ubuntu Server.
And Select the .ISO file you just downloaded on the ISO select box.
Type: usually is automatic but make sure its set to Ubuntu.
Version: make sure is set to 64 bits.
Check the Box that says "Skip Unattended installation". We will performing a manual installation Then hit Next
Once you added you user information, the next step has to do with the resources you'll give to your Virtual Machine, these depend on your hardware pretty much, so be smart do your match depending on you host OS capabilities, so for example I have a 8 core CPU processor with 16 GB of RAM so I usually give my VM's 4GBs of RAM and 4 CPU's but again that depends on your hardware, what I'm proposing here is more than enough to run big processes inside you virtual machine such as content migration or tough batch processes:
Hit Next.
On this new screen you be able to set up your hard drive disk space, again do your math based on how many projects you'll be going to handle since this is a new brand computer if you will you'll be limited to that disk space you give to your Virtual Machine, I usually go with 100GB since projects come and others can be deleted so you can play around with it. Keep in mind that you can always increase the virtual disk size using the tools provided by VirtualBox if necessary.
Hit Next.
Once done with these few steps, you'll get the Summary screen for your new Virtual Machine, just hit finish so we can start with the Ubuntu installation.
Hit Finish.
Once done, your newly create machine will show up on the left menu of the screen.
Click on the Start Button to start the installation, this will open up a new window.
NOTE: From down bellow the instructions provided will also work if you prefer to have a Native installation on your Laptop/Desktop using Ubuntu 22.04 as the Operative System.
Select *Try or Install Ubuntu:
First screen you'll see is the language for your new installation, choose as you will, I'm going to go with English:
One important thing to notice here once that installation screen is shown VirtualBox will capture your keyboard and mouse inside so in order to un-capture, look at the bottom right of the screen ad it will tell you what key will release your keyboard and mouse so you can navigate to your host. For example in my case it says "Left Command Key" That might vary depending on your Host OS.
Installing Linux server is as well a pretty straight forward installation I mostly go with the defaults. But if you want to change something like the keyboard layout for example just navigate using the Tab key and the Arrows keys and Enter key.
Second Screen will ask if you want to update the installer, just go with "Continue without updating" as shown below:
Keyboard configuration screen, choose as preferred:
Type of installation screen, leave default as Ubuntu Server:
Network connections screen, leave defaults, we will be using NAT (If going with Native installation leave as defaults as well):
Proxy screen, leave empty, just hit Done:
Mirror Screen, use defaults, just hit Done:
Guided storage Configuration, make sure to Uncheck the box "Set up this disk as an LVM group":
Storage configuration screen, go with defaults, just choose Done:
When prompted to "Complete Destructive Action", select Continue:
Profile Setup Screen, Enter your credentials, your name a username and a password, this username will be the SUDO user so keep that in mind. As for server name give it a cool name! (no white spaces are allowed):
Enable Ubuntu Pro Screen, leave defaults -> Skip for now:
Install OpenSSH Server screen, ENABLE the option so you can SSH your server after it is installed:
Feature Server Snaps Screen, don't choose anything go with the defaults:
After this step the installation will begin, Once the installation is complete you'll get and screenshot just like this, select Reboot Now:
If promoted to remove the installation Media, just hit the Enter key twice and the system will restart automatically, if for some reason it stills give you errors just go to you VirtualBox console, Under -> Settings of your virtual Machine select STORAGE tab and just detach the .ISO file from the CDROM (Controller IDE).
Once the restart process is done you can login to your new VM by adding you user name and password:
Now let's do some tune up, with your virtual machine all shutdown go to the VirtualBox Console and click on Settings -> System and Under Acceleration choose KVM
Under Network you'll see NAT is already chosen, if not select it, and then click on Advanced, let's add some port forwarding so you can access you Drupal/PHP apps and also SSH to your guest machine. Click on Port Forwarding and add as follows:
With this configuration you'll make sure that all connections on port 8080 will reroute to the guest on port 80 (HTTP), 4433 to 443 (HTTPS) and 2222 to 22 (SSH).
Remember that for every virtual machine you create, a new set of NAT rules should have to be created with different ports forwarding.
Note: I'm using NAT because ideally you'll might be using your Host computer without LAN or WIFI connected so the Bridge mode won't be available but if you want to use the Bridge option which will request an IP from your Router for your VM, then consider that on *NIX based systems such as Linux or Mac there is an admin rule so ports below 1024 won't be opened to any users unless you are a super admin, in my case since I use my Mac/Linux computers as hosts only with VirtualBox, it's safe to run VirtualBox as SUDO meaning $ sudo virtualbox and run this above process as such so you can avoid the NAT config and access your sites as usual without creating NAT rules (http://YOUR_VM_IP). I'm documenting this so you can have your Mac/Linux/Windows running with the VM IP Address, meaning your VM will have ports 80, 443 etc opened. For SSH, remember that on Windows you'll have to use Putty to SSH your virtual machines.
Now let's SSH to our newly created machine, you can use any terminal or Putty now just for simplicity and leave the virtual machine in the dock:
$ ssh andres@127.0.0.1 -p2222 ## Make sure you use your username instead of andres
You'll get a screenshot like this:
Once logged in, let's update our newly created Ubuntu by running the following commands:
$ sudo apt update && sudo apt upgrade -y
Once that process is done reboot your Virtual Machine:
$ sudo reboot
Wait until the Virtual Machine boots up again, log back in as described before and now we can start with the PHP/LAMP configuration:
In an past blog I wrote how to set up a LAMP stack for Drupal 8/9 but I'm going to be updating it here so it matches Drupal 9.5+ and Drupal 10.
This post is targeted for Apache Server only, which I think is the most robust Web Server for Drupal but overall the best option to run PHP applications natively. You can read more on the following links how to configure Drupal for other web servers or configurations such as Nginx if you are interested.
Let's start by getting the required packages, you can just go ahead and copy & paste:
$ sudo apt install php-fpm apache2 libapache2-mod-fcgid mysql-server mysql-client memcached build-essential autoconf php-mysql php-bz2 php-zip php-soap php-memcache php-apcu php-gd php-mbstring php-curl php-cli php-json php-mbstring php-xml php-xdebug git unzip zip curl nodejs npm default-jre dkms -y
Once the installation process is finished, reboot your Virtual Machine:
$ sudo reboot
The command above will download and install all the essential modules in Ubuntu required by Drupal and any other PHP apps. These include PHP extensions for MySql connections, debugging with X-Debug, Memcache and APC support, image manipulation, compression, etc. It will also add Apache 2 Server and required libraries to run php-fpm, nodejs and openjdk to run Java apps such as Solr.
Log back in and let's begin with some Apache configuration by enabling the following modules, again just copy and paste:
$ sudo a2enmod alias rewrite proxy_fcgi setenvif expires headers remoteip ssl actions
these are basic Apache modules required by for Drupal or any other PHP app, alias for url aliasing, rewrite for url rewriting, proxy_fcgi is the Apache handler for php-fpm, expires for sessions, headers for requests manipulation, remoteip if you want to test your site behind a proxy, ssl to activate HTTPS support for your sites.
You can now see your Web Server responding or listening on port 8080 as we configured before on VirtualBox NAT Section, http://localhost:8080
Now, enable the default php8.1 fpm config file provided by Ubuntu:
$ sudo a2enconf php8.1-fpm
Once enabled, restart the Apache service:
$ sudo systemctl restart apache2
Done, you have configured Apache to use php-fpm to run you PHP applications, but there is still one more step, it is recommended that on every site, meaning every virtual host you create you need to always add the following directive:
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost/"
</FilesMatch>
So let's add it to the default virtual host:
$ sudo nano /etc/apache2/sites-available/000-default.conf
File should look like this:
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
# Enable php-fpm support for this host:
<FilesMatch \.php$>
SetHandler "proxy:unix:/var/run/php/php8.1-fpm.sock|fcgi://localhost/"
</FilesMatch>
</VirtualHost>
Or you could just comment out the "Require all denied" rule so the change applies globally, I personally prefer this method since it helps when testing PHP apps running Apache with libapache2-mod-php so I don't have to worry about adding or removing the rule per virtual host, find the section FilesMatch and comment out # Require all denied.
$ sudo nano /etc/apache2/conf-available/php8.1-fpm.conf
File section should look like this:
<FilesMatch ".+\.phps$">
# Deny access to raw php sources by default
# To re-enable it's recommended to enable access to the files
# only in specific virtual host or directory
#Require all denied ## Line to be commented out.
</FilesMatch>
Save and Exit. Restart PHP so changes can take place:
$ sudo systemctl restart php8.1-fpm
And there we go! We have configured Apache and PHP using php-fpm which is considered to perform faster on big or small environments.
In order to test, create a simple PHP file on the default Apache www/ folder where the default virtual host points to:
$ sudo nano /var/www/html/index.php
and paste the following PHP code:
<?php
echo phpinfo();
?>
Save the file and open up a browser window and go to: http://localhost:8080/index.php and you should see an output similar as the next screenshot:
Now we need to tune up a little PHP, let's edit the following values on the loaded configuration file:
$ sudo nano /etc/php/8.1/fpm/php.ini
look for the following directives and update:
max_execution_time = 30 # Set it to 60
max_input_vars = 1000 # Set it to at least 3000
memory_limit = 128M # Set to 256M more it not recommended, better check your code.
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT # Set it to E_ALL on dev we want all errors to be shown.
display_errors = Off # Set it to On
display_startup_errors = Off # Set it to On
post_max_size = 8M # Set it to 512M
upload_max_filesize = 2M # Set to 512M
soap.wsdl_cache_enabled=1 # Set it to 0 on development we don't want to cache soap calls.
Save the file and restart the service:
$ sudo systemctl restart php8.1-fpm.service
Alright, we are finished setting up our Virtual Machine so let's prepare the steps to store and manage our Drupal projects. I usually prefer to store my projects on a folder under my HOME/ folder in order to avoid file permissions issues and/or have to deal with sudo commands. Follow the next steps to keep your installations as neat as possible:
## Move to your HOME/ folder.
$ cd ~/
## Let's add the www-data user to your USER group.
$ sudo adduser www-data YOUR_GROUP ## i.e www-data andres, normally you user-name and group are named the same.
## Create a new folder to hold your projects.
$ mkdir www/
IMPORTANT: Use the following commands every time you add a new project or if you ever find file permissions issues, like access denied errors, in order to keep your file permissions and ownership clean:
## New projects added or for troubleshooting:
## 1) Change www/ and subfolders access permissions:
$ sudo chmod -R 0777 www/
## 2) Change www/ and subfolders ownership to your user and the Apache group:
$ sudo chown -R YOUR_USERNAME:www-data www/ ## i.e andres:www-data (user:www-data)
Now that we have Apache and PHP configured and our storage folder, let's continue with the default tools required by Drupal. First we need to install Composer, the package manager that allows to handle multiple tasks and install Drupal necessary libraries, I recommend to install Composer globally on Ubuntu for easy handling, follow the next steps to have Composer running:
# Download Composer from https://getcomposer.org/download/
# Choose the version you prefer based on your Drupal installations.
# You can have multiple Composer version running.
# In our case we will installing the latest Composer 2 version available as of the publication of this post.
## Move to your HOME/ folder.
$ cd ~/
## Grab the desired Composer version.
$ wget https://getcomposer.org/download/2.6.6/composer.phar
## Give Composer executable permissions.
$ chmod +x composer.phar
## Move Composer executable to your system bin folder to make it globally available.
$ sudo mv composer.phar /usr/local/bin/composer
To test Composer just run in your terminal the following command:
$ composer --version
and you should see the following output:
NOTE: You can switch to other Composer versions by following the steps above, just need to change the executable name when moving it to the system bin/ folder, for example you can download any Compose 1 version if needed and just replace mv composer.phar /user/local/bin/composer1 and run it as composer1 --version. Same works when you want to update to newer versions.
Sweet! We are now ready to create our first Drupal 10 installation! First let's download Drupal 10 with Composer, configure the Apache Virtualhost definition and then configure a database on Mysql.
Download Drupal 10 using composer. The recommended way is pretty well documented on the Drupal.org site you can find the whole documentation on this link if you need to dig deeper on other methods of installation. I'm providing the steps for Drupal 10:
## Move to your HOME/www folder we created.
$ cd ~/www
## Run the following command to get all the files required. Composer will automatically run composer install too so all the
## dependencies required will be downloaded as well. Replace "my_site_name" with a name of your liking, this will create a
## new folder with that name under the www/ folder.
$ composer create-project drupal/recommended-project my_site_name
Ok, we have downloaded Drupal 10 on our www/ folder container, let's move with the Apache VirtualHost configuration:
## Create a new file definition for your VirtualHost
## Replace drupal10.antrecu.com.conf with a name that identifies your project. Don't forget to add the ".conf" at the end of
## the file
$ sudo nano /etc/apache2/sites-available/drupal10.antrecu.com.conf
## Paste the following and replace values as necessary, by default Composer will wrap the bootstrap files into the web/
## folder, so it's mandatory to point the DocumentRoot to to that folder same as the Directory.
<VirtualHost *:80>
DocumentRoot /home/YOUR_USER_NAME/www/drupal10/web
ServerName drupal10.antrecu.com
<Directory /home/YOUR_USER_NAME/www/drupal10/web>
Options Indexes MultiViews FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
## Uncomment the following if you want to protect your site with .htaccess
## Make sure to properly configure the .httpasswd
#<Directory /home/YOUR_USER_NAME/www/drupal10/www>
## Protect Directory
# AuthType Basic
# AuthName "Restricted Content"
# AuthUserFile /etc/apache2/.htpasswd
# Require valid-user
#</Directory>
## Error Logs.
## Replace drupal10.antrecu.com with the name of your project for easy identify logs.
ErrorLog /var/log/apache2/drupal10.antrecu.com-error.log
CustomLog /var/log/apache2/drupal10.antrecu.com-access.log combined
</VirtualHost>
Once the file it's saved, we need to enable the site and restart the Apache2 service:
## Enable a site VirtualHost
## Replace drupal10.antrecu.com.conf with the name of your project .conf
$ sudo a2ensite drupal10.antrecu.com.conf
## Restart the Apache2 service on Ubuntu
$ sudo systemctl restart apache2.service
Now, for local development we need to tell our HOST machine where to point the URL so we can access the site using a Web Browser, to do so we need to edit the hosts file of our operative system and add a new entry for our project ServerName we provided on our VirtualHost definition, on Mac and Ubuntu the file is located in /etc/hosts on Windows is located in C:\Windows\System32\drivers\etc folder.
## Edit hosts file on Mac or Linux
$ sudo nano /etc/hosts
Once the file opens for editing follow this quick guide:
## Here the sample of a hosts file, you can add entries based on how many projects you are going to run locally.
## Lines added by system:
127.0.0.1 localhost
127.0.1.1 lucifer
## End lines added by system
## Here you can manage all your targets.
## For VirtualBox Virtual Machines or native development. Replace drupal10.antrecu.com with the ServerName provided on
## your Apache2 VirtualHost definition.
127.0.0.1 drupal10.antrecu.com
## For external development on other machines meaning different IP addresses. Replace REMOTE_MACHINE_IP with the
## current IP your are pointing to, i.e 192.168.60.45
REMOTE_MACHINE_IP drupal10.antrecu.com
## End targets
## Lines added by system:
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
## End lines added by system
Save and Exit. We are almost there! Let's move with the Mysql database, creating a database on Mysql on Ubuntu 22.04 it's pretty straight forward for development environments, in order to create our first database on a newly Ubuntu/Mysql set up, we need to also create a user for the first time and then you just can reuse that user for new databases for other projects. Follow this quick steps in order to login to Mysql as the root user, create a user, create a database and grant permission to that user over the databases:
## Login to Mysql as root
$ sudo mysql
## Once logged in into the Mysql Server console, run:
## Create a new User for all your projects.
CREATE USER drupal@'localhost' IDENTIFIED BY "Drupal#123";
## Create a new database, replace drupal10 with a desired database name:
CREATE DATABASE drupal10;
## Grant all permissions to the new user to a database, replace drupal10 with the desired database name
GRANT ALL ON drupal10.* to drupal@'localhost';
## Grant process to user
GRANT PROCESS ON *.* to drupal@'localhost';
## If no errors are thrown, just exit the console: by typing:
exit;
Pretty simple, right? in order to test your new user credentials, from your command line run:
## Replace user and pass accordingly and in your terminal run:
$ mysql -u drupal -p"Drupal#123"
If all went ok you will get access to Mysql and see all the databases your user has permissions to access as shown in the next screenshot:
Type exit; on the mysql console and that is all with Mysql.
Now we can proceed with the Drupal installation process through your web browser by accessing the URL provided on your VirtualHost definition/system hosts file i.e http://drupal10.antrecu.com:8080 for your Virtual machine or just http://drupal10.antrecu.com if native development or remote server, Drupal install will start automatically. Follow the wizard as usual, provide the credentials for Mysql you previously created and Drupal install will do the settings.php file updates. Make sure you create a settings.php file based on the default.settings.php template available under web/sites/default
## Create settings.php
## Move to your sites/default directory of your project
$cd ~/www/drupal10/web/sites/default
## Copy the default and create the settings file
$ cp default.settings.php settings.php
After the installation process is done you'll be redirected to the homepage of your new site.
NOTE: Under the Reports page you might find a warning saying that the Ubuntu 22.04 PHP 8.1.2-1ubuntu2.14 package has an OPcache issue but Ubuntu has already fixed it and backported to their repositories so the warning can be ignored it is also also reported by Drupal in this issue https://www.drupal.org/project/drupal/issues/3307248 for more info.
Perfect! so far so good, now it is Drush time! Drupal 10+ requires Drush 12 and since Drupal 9 it is mandatory that Drush is installed as a Composer dependency on a per project basis.
NOTE: As per the documentation on Drush execution, you MUST run drush from the document root of your project! More info here: https://www.drush.org/12.4.3/install/
Drush 12 steps from terminal:
## Move to your Home and project folder document root.
$ cd ~/www/drupal10
$ composer require drush/drush
Save and Exit. Make Drush available as the drush command for easy handling:
# Move to your HOME folder:
$ cd ~/
## Edit your .bashrc file in order to add Drush executable for all your projects.
$ nano ./bashrc
## Copy & paste the following line at the end of the file:
export PATH="$PATH:./vendor/bin/"
Save and Exit. In order to test drush, move to your project docroot as described before and run drush status as shown in the next screenshot:
Last but not least, on previous versions of Drush (drush 8/9) there was a nice command called drush init or drush core-init that provided a nice interface to your terminal showing you mostly the Git behavior based on your current branch or tag, etc. Unfortunately the command was removed in newer version of Drush but don't fear, with the next lines you'll be able to have the same functionality just by updating your .bashrc file. Tested on Ubuntu 22.04.
## Move to HOME/
$ cd ~/
## Open file for editing:
$ nano .bashrc
Save and Exit. Once you opened the file for editing add the following at the end of the file:
##### COLOR FOR GIT IN BASH #####
export GIT_PS1_SHOWDIRTYSTATE=true
export GIT_PS1_SHOWUNTRACKEDFILES=true
export PS1='\[\033[32m\]\u@\h\[\033[00m\]:\[\033[34m\]\w\[\033[31m\]$(__git_ps1)\[\033[00m\]\$ '
##### END COLOR FOR GIT #####
Save and Exit. More info about this can be found in this link
Alright, we are done with this tutorial, is worth to mention that for any IDE you use for development you just need to enable any SSH plugin/extension available for it so you can connect to your Virtual Machine/Remote Server and access your Drupal files, for example I use Visual Studio code and the basic plugins I use are shown in the next screenshot:
Hope you enjoyed this post, I understand it's quite a long process for setting up your first LAMP Stack on Ubuntu/Linux/Mac but once it's done the process will require small effort in terms of configuring existing or new projects since is just a matter of getting the project files, set up a database a virtual host and voila! But overall you have learned more about what's under the hood of Dockerized Dev solutions, how to properly set up a LAMP stack from scratch and understand the Linux steps to host a PHP/Drupal application and of course improve performance.
Please share your thoughts, I'll be happy to help on any questions that might arise!
Oh by the way, want Solr? Check out this link on how to configure Solr for your Drupal 10 projects!