Automating LAMP Stack Deployment Using a Bash Script on an Ubuntu Server
Tags: devops, ubuntu, bash, laravel
Published: 2024-05-17 06:12:18

**Introduction**
Laravel is a popular free and open-source PHP-based web framework used for building high-end web applications. It is renowned for its expressive and elegant syntax.

In this article, we will deploy a Laravel app on a LAMP stack. LAMP stands for Linux, Apache, MySQL, and PHP. We will automate this deployment with a Bash script. This will not only speed up the deployment but also reduce the errors that might occur in manual deployment, while also ensuring consistency in the deployment process. Let’s go through the process step by step.

**Prerequisites**
1. Basic knowledge of Linux and terminal commands
2. An accessible Ubuntu server instance.
3. A Laravel application in a GitHub repository.
4. SSH Access into the Ubuntu server.

**Laravel LAMP Automation Process**
**Step 1:** Create a bash script file, I’ll name mine “lamp.sh”.
`touch lamp.sh`

**Step 2:** Give the file executable permission.
`chmod +x lamp.sh`
I will be using vim as my editor you can use nano or any editor of your choice to edit the bash script file.
`vim lamp.sh`

**Step 3:** Now we can start writing our bash script, we will be dividing our tasks into functions, this is good for modularity and reusability. First, we declare our shebang
`#!/bin/bash`

**Step 4:** let’s write a function to update the repository and a function to install each of the LAMP stack

```
update_repository() {
    sudo apt update
}
```
To install apache
```
install_apache() {
    sudo apt -y install apache2
}
```
To install MySQL
```
install_mysql() {
    sudo apt -y install mysql-server mysql-client
}
```
To install PHP and other PHP extensions required for the deployment, note that I installed PHP 8.2 hence all the extensions must be of the same version, I will also install zip and unzip which are not PHP extensions but will be needed later for composer.
```
install_php() {
    sudo apt install software-properties-common --yes
    sudo add-apt-repository -y ppa:ondrej/php
    sudo apt update
    sudo apt -y install php8.2 php8.2-curl php8.2-dom php8.2-mbstring php8.2-xml php8.2-mysql zip unzip
}
```
**Step 5:** Enable URL rewriting and Restart Apache
```
enable_url_rewriting() {
    sudo a2enmod rewrite
    sudo systemctl restart apache2
}
```
**Step 6:** Write a function to install and setup composer, note that we will do this in the /usr/bin directory
```
install_composer() {
    cd /usr/bin
    curl -sS https://getcomposer.org/installer | sudo php -q
    if [ ! -f "composer" ]; then
        sudo mv composer.phar composer
    fi
}
```
**Step 7:** Write a function to clone the Laravel app from a GitHub repo. Here is a link to the repository Laravel repo, note that this function will also change the ownership of the /var/www directory to the current user.
```
clone_laravel_repo() {
    sudo chown -R $USER:$USER /var/www
    cd /var/www
    if [ ! -d "laravel" ]; then
       git clone https://github.com/laravel/laravel.git
    fi
}
```
**Step 8:** Now we will install composer in the laravel directory which we just cloned.
```
install_composer_in_project() {
    cd /var/www/laravel
    composer update --no-interaction
}
```
**Step 9:** Write a function to configure the .env file.
```
build_env_file() {
    cd /var/www/laravel
    if [ ! -f ".env" ]; then
        cp .env.example .env
    fi
    sudo php artisan key:generate
    sudo chown -R www-data storage
    sudo chown -R www-data bootstrap/cache
    
}
```
**Step 10:** Write a function to create a new virtual host and use it as the default.
```
create_apache_config() {
    sudo bash -c 'cat > /etc/apache2/sites-available/laravel.conf <<EOF
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName localhost
    ServerAlias localhost
    DocumentRoot /var/www/laravel/public

    <Directory /var/www/laravel/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/laravel-error.log
    CustomLog ${APACHE_LOG_DIR}/laravel-access.log combined
</VirtualHost>
EOF'

  cd ~
    sudo a2dissite 000-default.conf
    sudo a2ensite laravel.conf
    sudo systemctl restart apache2
}
```
**Step 11:** Now we can write a function that will configure our MySQL i.e. create a database and user.
```
create_database_and_user() {
    sudo systemctl start mysql
    sudo mysql -uroot -e "CREATE DATABASE IF NOT EXISTS laravel;"
    sudo mysql -uroot -e "CREATE USER IF NOT EXISTS 'vagrant'@'localhost' IDENTIFIED BY '1805';"
    sudo mysql -uroot -e "GRANT ALL PRIVILEGES ON laravel.* TO 'vagrant'@'localhost';"
    
    cd /var/www/laravel
    grep -qF 'DB_CONNECTION=mysql' .env && sed -i 's/DB_CONNECTION=mysql/DB_CONNECTION=mysql/' .env || echo "DB_CONNECTION=mysql" >> .env
    grep -qF 'DB_HOST=localhost' .env && sed -i 's/DB_HOST=localhost/DB_HOST=localhost/' .env || echo "DB_HOST=localhost" >> .env
    grep -qF 'DB_PORT=3306' .env && sed -i 's/DB_PORT=3306/DB_PORT=3306/' .env || echo "DB_PORT=3306" >> .env
    grep -qF 'DB_DATABASE=laravel' .env && sed -i 's/DB_DATABASE=laravel/DB_DATABASE=laravel/' .env || echo "DB_DATABASE=laravel" >> .env
    grep -qF 'DB_USERNAME=vagrant' .env && sed -i 's/DB_USERNAME=vagrant/DB_USERNAME=vagrant/' .env || echo "DB_USERNAME=vagrant" >> .env
    grep -qF 'DB_PASSWORD=1805' .env && sed -i 's/DB_PASSWORD=1805/DB_PASSWORD=1805/' .env || echo "DB_PASSWORD=1805" >> .env

    sudo php artisan storage:link
    sudo php artisan migrate --force
    sudo php artisan db:seed --force
    sudo systemctl restart apache2

}
```
**NOTE:** My Database name is *laravel*, my Username is *vagrant* and my Password is *1805*, you can use values of your choice.

**Step 11:** Now we can call all our functions as we know functions won’t execute until they are called.
```
update_repository
install_apache
install_mysql
install_php
enable_url_rewriting
install_composer
clone_laravel_repo
install_composer_in_project
build_env_file
create_apache_config
create_database_and_user
```

- Save the script and exit
- Execute the script
`./lamp.sh`

Load the IP of your server or your domain in your browser and you should have the output below

**OUTPUT**

![Output of deploying a laravel project](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8m34q5rl0tjmv4dztqvz.jpg)

**Conclusion**
By following the steps outlined in this guide, you will be able to streamline the deployment of the LAMP (Linux, Apache, MySQL, PHP) stack through the utilization of a bash script. While it is possible to carry out this process manually, automation offers the advantage of increased speed, consistency, and reduced potential for errors. Furthermore, the bash script can be reused for future deployments, saving time and effort.