Skip to content

George-Nyamao/ansible-lamp-stack

Repository files navigation

Ansible LAMP Stack Automation

Fully automated deployment of a production-ready LAMP (Linux, Apache, MySQL, PHP) stack using Ansible.

Features

  • ✅ Apache2 web server with virtual hosts
  • ✅ MySQL 8.0 database with secure configuration
  • ✅ PHP 8.1 with common extensions
  • ✅ UFW firewall configuration
  • ✅ SSL/TLS certificate support
  • ✅ Automated backups
  • ✅ Health checks and monitoring

Quick Start

# Install dependencies
ansible-galaxy install -r requirements.yml

# Update inventory
nano inventory/hosts

# Run playbook
ansible-playbook site.yml --vault-password-file .vault_pass

Project Structure

.
├── ansible.cfg
├── site.yml
├── healthcheck.yml
├── backup.yml
├── rollback.yml
├── maintenance.yml
├── test.yml
├── Makefile
├── inventory/
│   └── hosts
├── group_vars/
│   ├── all.yml
│   ├── webservers.yml
│   ├── databases.yml
│   └── vault.yml (encrypted)
├── roles/
│   ├── common/
│   │   ├── tasks/
│   │   ├── handlers/
│   │   └── defaults/
│   ├── apache/
│   │   ├── tasks/
│   │   ├── handlers/
│   │   └── templates/
│   ├── mysql/
│   │   ├── tasks/
│   │   ├── handlers/
│   │   └── templates/
│   └── php/
│       ├── tasks/
│       ├── handlers/
│       └── templates/
├── README.md
├── DEPLOYMENT.md
└── .gitignore

Requirements

  • Ansible 2.9+
  • Ubuntu 20.04/22.04 target servers
  • SSH access to target servers
  • Python 3.6+ on control node

Installation

1. Clone the Repository

git clone https://github.com/George-Nyamao/ansible-lamp-stack.git
cd ansible-lamp-stack

2. Configure Inventory

Edit inventory/hosts with your server details:

[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu

[databases]
db1 ansible_host=192.168.1.20 ansible_user=ubuntu

3. Set Up Vault Password

echo "your-strong-vault-password" > .vault_pass
chmod 600 .vault_pass

Important: Never commit .vault_pass to version control!

4. Configure Variables

Edit the following files in group_vars/:

group_vars/all.yml:

app_name: "myapp"
app_domain: "example.com"
timezone: "UTC"

group_vars/webservers.yml:

apache_listen_port: 80
php_version: "8.1"
php_memory_limit: "256M"

group_vars/databases.yml:

mysql_version: "8.0"
mysql_port: 3306

5. Update Vault Secrets

ansible-vault edit group_vars/vault.yml --vault-password-file .vault_pass

Update these variables:

vault_mysql_root_password: "YourSecureRootPassword"
vault_app_db_password: "YourSecureAppPassword"

Deployment

Using Makefile (Recommended)

# Check syntax
make check

# Deploy full stack
make deploy

# Run tests
make test

# Health check
make health

# Backup
make backup

Using Ansible Playbook Commands

# Syntax check
ansible-playbook site.yml --syntax-check

# Dry run
ansible-playbook site.yml --check --vault-password-file .vault_pass

# Deploy
ansible-playbook site.yml --vault-password-file .vault_pass

# Deploy specific components
ansible-playbook site.yml --tags "apache,php" --vault-password-file .vault_pass

# Run health checks
ansible-playbook healthcheck.yml

# Run tests
ansible-playbook test.yml --vault-password-file .vault_pass

# Backup
ansible-playbook backup.yml --vault-password-file .vault_pass

Post-Deployment

Access Your Application

After successful deployment:

  1. Main Website: http://YOUR_SERVER_IP or http://your-domain.com
  2. PHP Info: http://YOUR_SERVER_IP/info.php
  3. Database Test: http://YOUR_SERVER_IP/db_test.php

Remove Test Files (Production)

ansible webservers -m file -a "path=/var/www/example.com/html/info.php state=absent" --become
ansible webservers -m file -a "path=/var/www/example.com/html/db_test.php state=absent" --become

Configure SSL with Let's Encrypt

# Install Certbot
ansible webservers -m apt -a "name=certbot,python3-certbot-apache state=present" --become

# Obtain certificate (replace with your domain)
ansible webservers -m shell -a "certbot --apache -d example.com -d www.example.com --non-interactive --agree-tos --email admin@example.com" --become

Maintenance

Update System Packages

ansible-playbook maintenance.yml -e "maintenance_action=update" --vault-password-file .vault_pass

Restart Services

ansible-playbook maintenance.yml -e "maintenance_action=restart" --vault-password-file .vault_pass

Clean Up

ansible-playbook maintenance.yml -e "maintenance_action=cleanup" --vault-password-file .vault_pass

Manual Backup

Automated backups run daily at 2 AM. For manual backup:

make backup
# or
ansible-playbook backup.yml --vault-password-file .vault_pass

Check Service Status

# Apache status
ansible webservers -m shell -a "systemctl status apache2" --become

# MySQL status
ansible databases -m shell -a "systemctl status mysql" --become

# PHP version
ansible webservers -m shell -a "php -v" --become

Monitoring

Check System Health

make health
# or
ansible-playbook healthcheck.yml

View Logs

# Apache error logs
ansible webservers -m shell -a "tail -50 /var/log/apache2/error.log" --become

# Apache access logs
ansible webservers -m shell -a "tail -50 /var/log/apache2/access.log" --become

# MySQL error logs
ansible databases -m shell -a "tail -50 /var/log/mysql/error.log" --become

# PHP error logs
ansible webservers -m shell -a "tail -50 /var/log/php_errors.log" --become

Resource Usage

# Check disk space
ansible lamp -m shell -a "df -h" --become

# Check memory usage
ansible lamp -m shell -a "free -h" --become

# Check CPU usage
ansible lamp -m shell -a "top -bn1 | head -20" --become

Troubleshooting

Connection Issues

# Test connectivity
ansible lamp -m ping

# Test SSH
ansible lamp -m shell -a "echo 'Connection successful'"

Service Issues

# Restart Apache
ansible webservers -m systemd -a "name=apache2 state=restarted" --become

# Restart MySQL
ansible databases -m systemd -a "name=mysql state=restarted" --become

# Check service status
ansible lamp -m shell -a "systemctl list-units --type=service --state=running | grep -E 'apache|mysql'" --become

Database Connection Issues

# Test MySQL connection from web server
ansible webservers -m shell -a "mysql -h DB_SERVER_IP -u appuser -p'password' -e 'SHOW DATABASES;'" --become

# Check MySQL port
ansible databases -m shell -a "netstat -tlnp | grep 3306" --become

Permission Issues

# Fix web directory permissions
ansible webservers -m file -a "path=/var/www/example.com/html owner=www-data group=www-data recurse=yes" --become

Rollback

If deployment fails or issues occur:

make rollback
# or
ansible-playbook rollback.yml --vault-password-file .vault_pass

Testing

Run comprehensive tests:

make test
# or
ansible-playbook test.yml --vault-password-file .vault_pass

Tests include:

  • Service status verification
  • HTTP response checks
  • Database connectivity
  • PHP functionality
  • Configuration validation

Security Best Practices

  1. Strong Passwords: Use complex passwords (20+ characters with special characters)
  2. Firewall: UFW is configured automatically - review rules regularly
  3. Regular Updates: Run weekly security updates
  4. Remove Test Files: Delete info.php and db_test.php in production
  5. SSL/TLS: Always use HTTPS in production
  6. Database Access: Restrict MySQL to specific IPs
  7. Backup Verification: Test backups regularly
  8. Log Monitoring: Check logs for suspicious activity
  9. Principle of Least Privilege: Use minimal required permissions
  10. Security Headers: Already configured in Apache

Common Commands

# Deploy everything
make deploy

# Deploy only Apache
ansible-playbook site.yml --tags apache --vault-password-file .vault_pass

# Deploy only MySQL
ansible-playbook site.yml --tags mysql --vault-password-file .vault_pass

# Deploy only PHP
ansible-playbook site.yml --tags php --vault-password-file .vault_pass

# Run health checks
make health

# View all hosts
ansible lamp --list-hosts

# Gather facts
ansible lamp -m setup --tree /tmp/facts

# Ad-hoc command execution
ansible lamp -m shell -a "uptime" --become

Performance Tuning

Apache Tuning

Edit group_vars/webservers.yml:

apache_mods_enabled:
  - rewrite
  - ssl
  - headers
  - expires
  - deflate  # Enable compression
  - cache    # Enable caching

MySQL Tuning

Edit group_vars/databases.yml:

mysql_innodb_buffer_pool_size: "2G"  # Adjust based on RAM
mysql_max_connections: 500

PHP Tuning

Edit group_vars/webservers.yml:

php_memory_limit: "512M"
php_max_execution_time: "300"
php_opcache_enable: 1

Customization

Add New Virtual Hosts

  1. Edit roles/apache/templates/vhost.conf.j2
  2. Add domain to group_vars/webservers.yml
  3. Re-run playbook

Add PHP Extensions

Edit roles/php/tasks/main.yml and add to the package list:

- php{{ php_version }}-imagick
- php{{ php_version }}-soap
- php{{ php_version }}-ldap

Custom MySQL Configuration

Create custom configuration in roles/mysql/templates/ and reference in tasks.

CI/CD Integration

GitHub Actions Example

name: Deploy LAMP Stack

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Install Ansible
        run: |
          sudo apt update
          sudo apt install -y ansible
      
      - name: Deploy
        run: |
          echo "${{ secrets.VAULT_PASSWORD }}" > .vault_pass
          ansible-playbook site.yml --vault-password-file .vault_pass
        env:
          ANSIBLE_HOST_KEY_CHECKING: False

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT License - see LICENSE file for details

Support

GitHub Issues GitHub Discussions

Changelog

v1.0.0 (2025-10-21)

  • Initial release
  • Complete LAMP stack automation
  • Backup and rollback functionality
  • Comprehensive testing suite
  • Security hardening

Author

George Nyamao

Acknowledgments

  • Ansible community for excellent documentation
  • Contributors who helped improve this project

Star this repository if you find it helpful!

About

A web server automation with Ansible LAMP stack

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors