DEV Community

Cover image for Developing a Reusable and Readable Bash Script for Automated LAMP Stack Deployment
Gbenga Akinbajo Okunniyi
Gbenga Akinbajo Okunniyi

Posted on

Developing a Reusable and Readable Bash Script for Automated LAMP Stack Deployment

Image descriptionAutomating the deployment of a LAMP (Linux, Apache, MySQL, PHP) stack is a crucial task for any system administrator or DevOps engineer. In this guide, we'll walk through the creation of a powerful Bash script that automates the entire deployment process, from cloning a PHP application from GitHub to configuring Apache web server and MySQL. Our goal is to ensure ease of maintenance and future deployments by developing a script that is both reusable and readable.

  1. Updating the System and Installing Apache
sudo apt update -y || handle_error "Failed to update the system."
sudo apt install apache2 -y || handle_error "Failed to install Apache web server."
Enter fullscreen mode Exit fullscreen mode

We begin by updating the Linux system and installing the Apache web server. The -y flag is used to automatically confirm any prompts during the installation process.

  1. Adding PHP Repository and Installing PHP

sudo add-apt-repository ppa:ondrej/php --yes || handle_error "Failed to add PHP repository."
sudo apt update -y || handle_error "Failed to update repository."
sudo apt install php8.2 php8.2-curl php8.2-dom php8.2-mbstring php8.2-xml php8.2-mysql zip unzip -y || handle_error "Failed to install PHP and extensions."
Enter fullscreen mode Exit fullscreen mode

We add the PHP repository maintained by Ondřej Surý and install PHP 8.2 along with necessary extensions required for our LAMP stack.

  1. Enabling Apache Modules and Restarting Apache
sudo a2enmod rewrite || handle_error "Failed to enable rewrite module for Apache."
sudo systemctl restart apache2 || handle_error "Failed to restart Apache server."
Enter fullscreen mode Exit fullscreen mode

We enable the rewrite module for Apache to allow for clean URL configuration and then restart the Apache server to apply the changes.

  1. Installing Composer Globally
sudo curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer || handle_error "Failed to install Composer globally."
Enter fullscreen mode Exit fullscreen mode

Composer, a dependency manager for PHP, is installed globally to facilitate dependency management for our PHP applications.

  1. Cloning Laravel Application from GitHub
cd /var/www/ || handle_error "Failed to change directory to /var/www/."
sudo git clone https://github.com/laravel/laravel.git laravel || handle_error "Failed to clone Laravel repository."
Enter fullscreen mode Exit fullscreen mode

We navigate to the web root directory and clone a Laravel application from its GitHub repository.

  1. Configuring Apache Virtual Host
sudo tee /etc/apache2/sites-available/latest.conf > /dev/null <<EOF
<VirtualHost *:80>
    ServerName localhost
    DocumentRoot /var/www/laravel/public

    <Directory /var/www/laravel>
        AllowOverride All
    </Directory>

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




Enter fullscreen mode Exit fullscreen mode

We configure a virtual host for our Laravel application, pointing Apache to the application's public directory and setting up error and access logs.

  1. Enabling and Disabling Virtual Hosts
sudo a2ensite latest.conf || handle_error "Failed to enable new Virtual Host."
sudo a2dissite 000-default.conf || handle_error "Failed to disable default Virtual Host."

Enter fullscreen mode Exit fullscreen mode

We enable the newly configured virtual host while disabling the default one to ensure our Laravel application is served correctly.

  1. Installing MySQL Server and Client
sudo apt install mysql-server mysql-client -y || handle_error "Failed to install MySQL server and client."
sudo systemctl start mysql || handle_error "Failed to start MySQL service."


Enter fullscreen mode Exit fullscreen mode

MySQL server and client are installed, and the MySQL service is started to set up the database management system.

  1. Updating .env File with MySQL Configuration

sudo cp .env.example .env
sudo chown -R $USER:$USER /var/www/laravel/.env

echo "APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD= " >> /var/www/laravel/.env
Enter fullscreen mode Exit fullscreen mode

We copy the example environment file, set appropriate ownership, and update it with MySQL configuration details.

  1. Generating Laravel Application Key and Creating Symbolic Link
sudo php artisan key:generate || handle_error "Failed to generate application key."
sudo php artisan storage:link || handle_error "Failed to create storage symbolic link."
Enter fullscreen mode Exit fullscreen mode

We generate a unique application key for Laravel and create a symbolic link for storage.

  1. Migrating and Seeding Database

sudo php artisan migrate
sudo php artisan db:seed
Enter fullscreen mode Exit fullscreen mode

Database migration and seeding are performed to set up the database schema and populate it with initial data.

  1. Serving the Application
sudo php artisan serve
Enter fullscreen mode Exit fullscreen mode

Finally, we serve the Laravel application using the built-in PHP development server.

Conclusion
By following this guide and developing a reusable and readable Bash script, one can automate the deployment of a LAMP stack with ease. This script ensures consistency, scalability, and ease of maintenance for future deployments.

Follow-Up: Enhancing Automation with Ansible Playbooks and Cron Jobs

In our previous blog post, we explored the development of a robust Bash script for automating the deployment of a LAMP stack. Building upon that foundation, we will now leverage Ansible playbooks and cron jobs to further enhance our automation capabilities and ensure seamless management of our server infrastructure.

  1. Ansible Playbook for Deployment

Ansible provides a powerful automation framework for orchestrating configuration management tasks across multiple servers. We'll start by creating an Ansible playbook that executes our Bash script on the slave node, ensuring consistent deployment across our server infrastructure.

# deploy.yml

- hosts: slave
  tasks:
    - name: Transfer deployment script to slave node
      copy:
        src: /path/to/deploy.sh
        dest: /tmp/deploy.sh

    - name: Execute deployment script on slave node
      shell: /bin/bash /tmp/deploy.sh
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. hosts: Specifies the target host or group of hosts where the playbook tasks will be executed. In this case, we target the "slave" server.
  2. copy: Copies the deployment script from the control node to the specified destination on the slave node.
  3. shell: Executes the deployment script on the slave node using the Bash shell.

  4. Cron Job for Uptime Monitoring

# Add the following line to the crontab file
0 0 * * * /usr/bin/uptime >> /var/log/server_uptime.log

Enter fullscreen mode Exit fullscreen mode

Explanation:

0 0 * * *: Specifies the schedule for the cron job. In this case, the job runs every day at midnight (00:00).
/usr/bin/uptime: Executes the uptime command to retrieve information about the server's uptime.
>> /var/log/server_uptime.log: Appends the output of the uptime command to a log file for record-keeping and monitoring.
Enter fullscreen mode Exit fullscreen mode

Execution and Verification
Executing Ansible Playbook:
Run the Ansible playbook (ansible-playbook deploy.yml) from the control node.
Verify successful execution by accessing the PHP application through the slave node's IP address.

Cron Job Verification:
Check the /var/log/server_uptime.log file on the slave node to ensure that uptime logs are being recorded as expected.
Tail the log file (tail -f /var/log/server_uptime.log) to monitor real-time uptime updates.

Conclusion
By incorporating Ansible playbooks and cron jobs into my automation workflow, I have further streamlined the deployment process and implemented proactive monitoring for server uptime. These tools enable one

Image description to maintain a reliable and efficient server infrastructure while reducing manual intervention.

Top comments (0)