In this article we will use terraform to provision a lemp stack for a laravel application with all its configurations (database, php, nginx, firewall, ssl, etc) using terraform-php-stack.
PHP Stack Provisioning
Every PHP project you worked on has that phase when you need to deploy it to a desired environment that match the application requirement usually its a LEMP or a LAMP stack.
That may require you to install and configure all these applications on the server every time manually, which can be boring, time consuming and redundant.
Is a terraform project that i was working on to solve my PHP stack provisioning and configurations.
if you are dealing with that manually this will speed up your applications deployments. It can also help if you are migrating to a new server.
The good part is that you can also test it locally before deciding to run it on a production server.
I tried to make the project as user-friendly as possible, so you don't need to know Terraform to use it.
However, I will still provide a step-by-step explanation:
Setup Target machine
1. Installing Terraform
In fact terraform installation is very simple, i will only cover ubuntu/debian installation for other OS, you can check the official documentation (=>).
wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list sudo apt update && sudo apt install terraform
2. Setup Target machine
You can use this terraform project against a fresh linux instance (vps) or a local virtual machine which is cool to test stuff before a real deployment.
I used it for both cases, and things went very well👌😎 .
For local testing i use vagrant & VirtualBox, you can use any other hypervisor.
This is my Vagrantfile :
Vagrant.configure("2") do |config| config.vm.box = "ubuntu/jammy64" config.vm.hostname = "kbouzidi" config.vm.provision "shell", inline: <<-SHELL apt update && hostname -I SHELL config.vm.network "private_network", type: "dhcp" config.vm.provider "virtualbox" do |vb| end end
COPY SSH KEY
You need to copy your public ssh key to your target server.
🚨 if you skip this probably you will be lost into a desert 🏜️
Well only if you will use vagrant with its own private key.
3. Configure terraform-php-stack
In this part, I will walk you through how I used this for a Laravel 10 project, and don't worry, you don't need to know Terraform at all.
First, you need to clone the project
git clone firstname.lastname@example.org:Safemood/terraform-php-stack.git
To start, you need to copy the example files to create your own configurations.
cd terraform-php-stack cp terraform.tfvars.example terraform.tfvars
As you can see, this is the folder structure :
├── main.tf ├── modules │ ├── install_dependencies │ │ ├── configure.sh │ │ ├── main.tf │ │ └── variables.tf │ ├── install_node │ │ ├── main.tf │ │ └── variables.tf │ ├── install_mysql │ │ ├── create_db.sh │ │ ├── main.tf │ │ └── variables.tf │ ├── install_nginx │ │ ├── default.tftpl │ │ ├── main.tf │ │ └── variables.tf │ ├── install_php │ │ ├── main.tf │ │ ├── php.ini │ │ ├── setup.sh │ │ └── variables.tf │ └── setup_app │ ├── main.tf │ ├── .env.tftpl │ └── variables.tf ├── terraform.tfvars.example
What is important in here :
main.tf where we can set all the required modules.
modules folder where the supported modules exist.
terraform.tfvars where we can set our environment variables && configurations.
.env.tftpl the template .env file for your php project.
We will configure the whole deployment only from terraform.tfvars
ssh_host = "target ip" ssh_user = "ssh user" ssh_key = "private_key path" php_version = "8.2" webmaster_email = "email@example.com" mysql_root_password = "crazySecurePassword" git_repo = "firstname.lastname@example.org:laravel/laravel" db_connexion = "mysql" db_host = "localhost" db_port = "3306" db_name = "kbouzidi" db_user = "safemood" db_password = "terraform" domain_name = "kbouzidi.com" app_env = "production" app_debug = false scheme = "http" // 'https' will auto assign ssl certificates to your domain stack_modules = ["dependencies", "node", "nginx", "php", "app", "mysql"] // dependencies","mysql", "nginx", "php","app" , "node" system_dependencies = "git tmux vim zip unzip htop fail2ban" installation_steps = [ # Set Folder Permissions "sudo chgrp -R www-data storage bootstrap/cache", "sudo chmod -R ug+rwx storage bootstrap/cache", # Installation "composer install --optimize-autoloader --no-dev", "php artisan key:generate --force", "php artisan storage:link --force", "php artisan migrate --seed --force", "sudo php artisan optimize:clear", "npm install && npm run build", "php artisan optimize" ]
What you need to know :
stack_modules is an array of the modules that you wanna install :
dependencies : to install required system dependencies and make other necessary configurations.
php : to install php on the system with the required version "php_version".
node : to install nodejs & npm on the system with the required version "node_version".
nginx : to install nginx and setup an nginx web server.
mysql : to install and setup a mysql server and a dadicated database to your project with the required permissions.
app : to setup and install our application.
Some other important notes:
scheme : https will auto assign ssl certificates to your domain using certbot.
git_repo : when its a private repo, you will need to add a deploy key to your project (link).
🚨 for private github repo make sure to use deploy keys so the token has access only to the related project only.
Deployment is the simplest part; just access the 'terraform-php-stack' folder and hit :
terraform init // only the first time terraform apply // or if you know what your doing 💥 terraform apply --auto-approve
You can see how the deployment process works in action.
As you have seen, the whole LEMP stack took only 4 minutes!
You can destroy this infrastructure with :
I created this with Laravel ❤️ in mind and i really love to expand it to be helpful for all major PHP framework and stacks, so contributions are very welcome 🤗🥰.
Just keep in mind these main points :
The ability to use the project without being a terraform expert.
Simplify the process of deploying and managing infrastructure for PHP developers using Terraform.
Make PHP developers happier 😁.
What i have in mind for this project:
Add Symfony support .
Add a fully docker version to provision the whole stack with containers.
Add support for major cloud providers (aws, google cloud, azure) to make PHP stack provisioning easier on these platforms.
I hope the information I provided was helpful. If you have any questions or need further clarification, don't hesitate to reach out to me. I'm always open to feedback, so please feel free to share any thoughts or suggestions you may have.
You can find me on LinkedIn || Twitter || Github!
Feel free to drop by and say hello - I'm always up for meeting new people and expanding my network!😊