Terraform your Laravel deployments

https://kbouzidi.com/img/containers/assets/terraform-your-laravel-deployments.jpeg/aede5dcfccc966770807a2c35c7ec2b5.jpeg

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).

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.

Terraform-php-stack

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:

  1. Installing Terraform

  2. Setup Target machine

  3. Configure terraform-php-stack

  4. Deployment

  5. Contribution

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

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.

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.

ssh-copy-id user@targetIP

🚨 if you skip this probably you will be lost into a desert 🏜️

Well only if you will use vagrant with its own private key.

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 git@github.com: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     = "example@test.com"
mysql_root_password = "crazySecurePassword"
git_repo            = "git@github.com: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 :

terraform destroy 

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!😊

Laravel News Links