3. Installing and Configuring phpMyAdmin for MySQL Admin

๐ŸŽฏ Goal

Install and configure phpMyAdmin to provide a web-based graphical interface for managing your MySQL database, making it easier to view data, run queries, and perform database administration tasks.

๐Ÿ“‹ Prerequisites

Before beginning this tutorial, you should:

๐Ÿ“š Learning Objectives

By the end of this tutorial, you will:

๐Ÿ” Why This Matters

In real-world applications, phpMyAdmin is valuable because:

๐Ÿ“ Step-by-Step Instructions

Step 1: Install phpMyAdmin

  1. Connect to your VM via SSH:

    ssh azureuser@<VM_Public_IP>
    
  2. Update package repositories:

    sudo apt update
    
  3. Install phpMyAdmin and required dependencies:

    sudo apt install phpmyadmin php-mbstring php-zip php-gd php-json php-curl -y
    
  4. During installation, you’ll see configuration prompts:

    • Web server selection: Choose apache2 (press Tab, then Space to select, then Enter)
    • Configure database: Select Yes
    • MySQL application password: Create a strong password for phpMyAdmin (e.g., phpMyAdmin123!)

๐Ÿ’ก Information

  • php-mbstring: Required for handling multi-byte character strings
  • php-zip: Enables import/export of compressed database files
  • php-gd: Required for generating graphics and charts
  • php-json: Handles JSON data operations
  • Even though we select apache2 during installation, we’ll configure it to work with Nginx

โš ๏ธ Common Mistakes

  • Not selecting a web server during installation can cause configuration issues
  • Using a weak phpMyAdmin password creates security vulnerabilities

Step 2: Configure Nginx to Serve phpMyAdmin

  1. Create a symbolic link to make phpMyAdmin accessible via Nginx:

    sudo ln -s /usr/share/phpmyadmin /var/www/html/phpmyadmin
    
  2. Update Nginx configuration to handle phpMyAdmin properly:

    sudo nano /etc/nginx/sites-available/default
    
  3. Add a specific location block for phpMyAdmin within the existing server block:

    server {
        listen 80;
        root /var/www/html;
        index index.php index.html index.nginx-debian.html;
    
        # Existing configuration...
    
        # phpMyAdmin configuration
        location /phpmyadmin {
            root /var/www/html;
            index index.php index.html index.htm;
    
            location ~ ^/phpmyadmin/(.+\.php)$ {
                try_files $uri =404;
                root /var/www/html;
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
    
            location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
                root /var/www/html;
            }
        }
    
        # Restrict access to phpMyAdmin from specific IPs (optional security measure)
        location /phpmyadmin {
            # allow YOUR_IP_ADDRESS;
            # deny all;
            try_files $uri $uri/ =404;
        }
    
        # General PHP processing (existing)
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
        }
    
        # Basic file serving (existing)
        location / {
            try_files $uri $uri/ =404;
        }
    }
    
  4. Test and reload Nginx configuration:

    sudo nginx -t
    sudo systemctl reload nginx
    

๐Ÿ’ก Information

  • Symbolic link: Creates a reference to phpMyAdmin files without copying them
  • Location blocks: Nginx directives that define how to handle specific URL paths
  • IP restrictions: Optional security measure to limit access to specific IP addresses
  • The configuration ensures PHP files in phpMyAdmin are processed correctly

Step 3: Configure phpMyAdmin Security

  1. Configure phpMyAdmin with enhanced security settings:

    sudo nano /etc/phpmyadmin/config.inc.php
    
  2. Add or modify the following security configurations:

    <?php
    /* Existing configuration... */
    
    /* Authentication type */
    $cfg['Servers'][$i]['auth_type'] = 'cookie';
    $cfg['Servers'][$i]['host'] = 'localhost';
    $cfg['Servers'][$i]['compress'] = false;
    $cfg['Servers'][$i]['AllowNoPassword'] = false;
    
    /* Security settings */
    $cfg['blowfish_secret'] = 'CHANGE_THIS_TO_32_RANDOM_CHARACTERS'; /* You must fill in this for cookie auth! */
    
    /* Disable some potentially dangerous features */
    $cfg['ShowPhpInfo'] = false;
    $cfg['ShowServerInfo'] = false;
    $cfg['ShowDbStructureCreation'] = false;
    $cfg['ShowDbStructureLastUpdate'] = false;
    $cfg['ShowDbStructureLastCheck'] = false;
    
    /* Hide databases that user shouldn't see */
    $cfg['Servers'][$i]['hide_db'] = '^(information_schema|performance_schema|mysql|sys)$';
    
    /* Set session timeout */
    $cfg['LoginCookieValidity'] = 3600; // 1 hour
    
    /* Disable warning about configuration file */
    $cfg['CheckConfigurationPermissions'] = false;
    ?>
    
  3. Generate a secure blowfish secret:

    openssl rand -base64 32
    
  4. Replace CHANGE_THIS_TO_32_RANDOM_CHARACTERS with the generated string.

  5. Set proper permissions for the configuration file:

    sudo chmod 644 /etc/phpmyadmin/config.inc.php
    sudo chown root:www-data /etc/phpmyadmin/config.inc.php
    

๐Ÿ’ก Information

  • Blowfish secret: Used to encrypt cookies for session management
  • hide_db: Hides system databases that regular users shouldn’t modify
  • LoginCookieValidity: Automatically logs out users after specified time
  • AllowNoPassword: Prevents login without a password

Step 4: Create a Dedicated phpMyAdmin User

  1. Connect to MySQL as root:

    sudo mysql -u root -p
    
  2. Create a dedicated user for phpMyAdmin administration:

    -- Create phpMyAdmin admin user
    CREATE USER IF NOT EXISTS 'phpmyadmin_user'@'localhost' IDENTIFIED BY 'SecureAdminPass123!';
    
    -- Grant necessary privileges for database administration
    GRANT ALL PRIVILEGES ON contact_db.* TO 'phpmyadmin_user'@'localhost';
    GRANT SELECT ON mysql.user TO 'phpmyadmin_user'@'localhost';
    GRANT SELECT ON mysql.db TO 'phpmyadmin_user'@'localhost';
    GRANT SELECT ON mysql.host TO 'phpmyadmin_user'@'localhost';
    GRANT SELECT ON mysql.tables_priv TO 'phpmyadmin_user'@'localhost';
    
    FLUSH PRIVILEGES;
    EXIT;
    

๐Ÿ’ก Information

  • Dedicated user: Separate user for phpMyAdmin reduces security risks
  • Limited privileges: Only necessary permissions for database administration
  • mysql. tables*: Required for phpMyAdmin to display user and privilege information
  • This user can manage the contact_db but has limited system access

Step 5: Test phpMyAdmin Installation

  1. Open your web browser and navigate to:

    http://<VM_Public_IP>/phpmyadmin
    
  2. You should see the phpMyAdmin login screen.

  3. Log in using the credentials you just created:

    • Username: phpmyadmin_user
    • Password: SecureAdminPass123!
  4. After successful login, you should see the phpMyAdmin dashboard with:

    • Database list on the left sidebar
    • Main content area showing server information
    • Navigation tabs for different functions

โœ… Verification Steps

  • phpMyAdmin login page loads without errors
  • Successful authentication with the dedicated user
  • Can see the contact_db database in the sidebar
  • No error messages about missing extensions

Step 6: Using phpMyAdmin - Basic Database Operations

6.1: Browse Database Structure

  1. In the left sidebar, click on contact_db to expand it
  2. Click on the contacts table to view its structure
  3. Use the Structure tab to see column definitions:
    • Column names (id, name, email, message, created_at)
    • Data types (INT, VARCHAR, TEXT, TIMESTAMP)
    • Key information (PRIMARY KEY on id)

6.2: View and Browse Data

  1. Click the Browse tab to see all records in the contacts table
  2. You should see any messages submitted through your contact form
  3. Use the navigation controls to:
    • Browse through pages if you have many records
    • Sort data by clicking column headers
    • Search for specific records

6.3: Insert New Data

  1. Click the Insert tab to add a new contact manually
  2. Fill in the form fields:
    • name: “Test Admin User”
    • email: “admin@example.com
    • message: “This is a test message from phpMyAdmin”
    • Leave id and created_at empty (auto-generated)
  3. Click Go to insert the record
  4. Navigate back to Browse to see your new record

6.4: Execute SQL Queries

  1. Click the SQL tab at the top of the interface

  2. Try some basic SQL queries:

    -- Count total messages
    SELECT COUNT(*) as total_messages FROM contacts;
    
    -- Find messages from a specific email domain
    SELECT * FROM contacts WHERE email LIKE '%@gmail.com';
    
    -- Get messages from the last 7 days
    SELECT * FROM contacts WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY);
    
    -- Update a message (be careful with this!)
    UPDATE contacts SET message = 'Updated message' WHERE id = 1;
    
  3. Click Go to execute each query and see the results

๐Ÿ’ก Information

  • Browse tab: Shows actual data stored in tables
  • Structure tab: Displays table schema and indexes
  • Insert tab: Provides a form interface for adding new records
  • SQL tab: Allows execution of custom SQL commands
  • Always be careful with UPDATE and DELETE operations

Step 7: Database Export and Backup

  1. Select the contact_db database from the sidebar
  2. Click the Export tab at the top
  3. Choose export options:
    • Export method: Quick (for simple backup) or Custom (for advanced options)
    • Format: SQL (most common) or other formats like CSV
    • Tables: Select all or specific tables to export
  4. Click Go to download the backup file

Creating Automated Backups

  1. Create a backup directory:

    sudo mkdir -p /var/backups/mysql
    sudo chown mysql:mysql /var/backups/mysql
    
  2. Create a backup script:

    sudo nano /usr/local/bin/backup_contact_db.sh
    
  3. Add the backup script content:

    #!/bin/bash
    
    # Database backup script
    DB_NAME="contact_db"
    DB_USER="contact_app"
    DB_PASS="StrongAppPassword123!"
    BACKUP_DIR="/var/backups/mysql"
    DATE=$(date +%Y%m%d_%H%M%S)
    
    # Create backup
    mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/contact_db_backup_$DATE.sql
    
    # Keep only last 7 days of backups
    find $BACKUP_DIR -name "contact_db_backup_*.sql" -mtime +7 -delete
    
    echo "Backup completed: contact_db_backup_$DATE.sql"
    
  4. Make the script executable:

    sudo chmod +x /usr/local/bin/backup_contact_db.sh
    
  5. Test the backup script:

    sudo /usr/local/bin/backup_contact_db.sh
    

Setting Up Automated Backups with Cron

  1. Create a cron job to run backups automatically:

    sudo crontab -e
    
  2. If prompted to choose an editor, select nano (option 1).

  3. Add the following line to schedule daily backups at 2:00 AM:

    # Daily database backup at 2:00 AM
    0 2 * * * /usr/local/bin/backup_contact_db.sh >> /var/log/mysql_backup.log 2>&1
    
  4. Save and exit the editor (Ctrl+X, then Y, then Enter).

  5. Verify the cron job was added:

    sudo crontab -l
    
  6. Create the log file with proper permissions:

    sudo touch /var/log/mysql_backup.log
    sudo chown root:adm /var/log/mysql_backup.log
    sudo chmod 640 /var/log/mysql_backup.log
    
  7. Test the cron job by temporarily setting it to run every minute:

    sudo crontab -e
    
  8. Change the line to:

    # Test backup every minute (remove after testing)
    * * * * * /usr/local/bin/backup_contact_db.sh >> /var/log/mysql_backup.log 2>&1
    
  9. Wait a few minutes, then check if backups are being created:

    ls -la /var/backups/mysql/
    cat /var/log/mysql_backup.log
    
  10. Once confirmed working, change it back to daily at 2:00 AM:

    sudo crontab -e
    
    # Daily database backup at 2:00 AM
    0 2 * * * /usr/local/bin/backup_contact_db.sh >> /var/log/mysql_backup.log 2>&1
    

๐Ÿ’ก Information

  • Cron format: minute hour day month day-of-week command
  • **0 2 * * ***: Runs at 2:00 AM every day
  • » /var/log/mysql_backup.log: Appends output to log file
  • 2>&1: Redirects error messages to the same log file
  • sudo crontab: Runs cron jobs with root privileges (needed for MySQL access)

For more advanced backup configurations, you can:

Step 8: Database Import and Restore

  1. To restore from a backup using phpMyAdmin:

    • Select the database (contact_db)
    • Click the Import tab
    • Click Choose File and select your SQL backup file
    • Click Go to import
  2. To restore from command line:

    # Restore from backup file
    mysql -u contact_app -pStrongAppPassword123! contact_db < /var/backups/mysql/contact_db_backup_YYYYMMDD_HHMMSS.sql
    

โš ๏ธ Important Security Notes

  • Always backup before making significant changes
  • Test restores on a copy, not production data
  • Import operations will overwrite existing data
  • Keep backups in a secure location with appropriate permissions

Step 9: Security Hardening for phpMyAdmin

  1. Create an additional security layer with HTTP authentication:

    sudo nano /etc/nginx/sites-available/default
    
  2. Add HTTP basic authentication to the phpMyAdmin location:

    location /phpmyadmin {
        auth_basic "Admin Area";
        auth_basic_user_file /etc/nginx/.htpasswd;
    
        root /var/www/html;
        try_files $uri $uri/ =404;
    }
    
  3. Install apache2-utils to create password file:

    sudo apt install apache2-utils -y
    
  4. Create HTTP authentication credentials:

    sudo htpasswd -c /etc/nginx/.htpasswd admin
    
  5. Enter a strong password when prompted (e.g., WebAdmin123!)

  6. Test and reload Nginx:

    sudo nginx -t
    sudo systemctl reload nginx
    
  7. Now accessing phpMyAdmin will require both HTTP authentication and MySQL login.

๐Ÿ’ก Information

  • HTTP Basic Auth: Adds an extra layer of protection before reaching phpMyAdmin
  • Double authentication: Users must pass HTTP auth, then MySQL auth
  • htpasswd: Creates encrypted password files for web server authentication
  • This significantly reduces automated attacks on phpMyAdmin

๐Ÿงช Core Installation Tests

Test 1: Verify Basic phpMyAdmin Access

  1. Open browser and navigate to http://<VM_Public_IP>/phpmyadmin
  2. Should prompt for HTTP authentication first (username: admin, password: WebAdmin123!)
  3. Then show phpMyAdmin login screen
  4. Login should work with phpmyadmin_user credentials (password: SecureAdminPass123!)

Test 2: Test Basic Database Operations

  1. Browse the contacts table and verify data displays correctly
  2. Insert a test record through phpMyAdmin interface
  3. Execute a simple SELECT query in the SQL tab
  4. Verify the new record appears in your contact form application

โœ… Expected Results

๐ŸŽ‰ Basic phpMyAdmin Installation Complete!

Congratulations! You now have a fully functional phpMyAdmin installation for managing your MySQL database. You can:


๐Ÿ“ฆ Optional Advanced Features

The sections below cover additional features for production environments and automation. These are optional and not required for basic phpMyAdmin functionality.

Database Export and Backup (Optional)

  1. To export databases for backup using phpMyAdmin:
    • Select the contact_db database from the sidebar
    • Click the Export tab at the top
    • Choose export options:
      • Export method: Quick (for simple backup) or Custom (for advanced options)
      • Format: SQL (most common) or other formats like CSV
      • Tables: Select all or specific tables to export
    • Click Go to download the backup file

Automated Backups with Scripts (Optional)

Creating Manual Backup Scripts

  1. Create a backup directory:

    sudo mkdir -p /var/backups/mysql
    sudo chown mysql:mysql /var/backups/mysql
    
  2. Create a backup script:

    sudo nano /usr/local/bin/backup_contact_db.sh
    
  3. Add the backup script content:

    #!/bin/bash
    
    # Database backup script
    DB_NAME="contact_db"
    DB_USER="contact_app"
    DB_PASS="StrongAppPassword123!"
    BACKUP_DIR="/var/backups/mysql"
    DATE=$(date +%Y%m%d_%H%M%S)
    
    # Create backup
    mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/contact_db_backup_$DATE.sql
    
    # Keep only last 7 days of backups
    find $BACKUP_DIR -name "contact_db_backup_*.sql" -mtime +7 -delete
    
    echo "Backup completed: contact_db_backup_$DATE.sql"
    
  4. Make the script executable:

    sudo chmod +x /usr/local/bin/backup_contact_db.sh
    
  5. Test the backup script:

    sudo /usr/local/bin/backup_contact_db.sh
    

Setting Up Automated Backups with Cron (Optional)

  1. Create a cron job to run backups automatically:

    sudo crontab -e
    
  2. If prompted to choose an editor, select nano (option 1).

  3. Add the following line to schedule daily backups at 2:00 AM:

    # Daily database backup at 2:00 AM
    0 2 * * * /usr/local/bin/backup_contact_db.sh >> /var/log/mysql_backup.log 2>&1
    
  4. Save and exit the editor (Ctrl+X, then Y, then Enter).

  5. Verify the cron job was added:

    sudo crontab -l
    
  6. Create the log file with proper permissions:

    sudo touch /var/log/mysql_backup.log
    sudo chown root:adm /var/log/mysql_backup.log
    sudo chmod 640 /var/log/mysql_backup.log
    

Database Import and Restore (Optional)

  1. To restore from a backup using phpMyAdmin:

    • Select the database (contact_db)
    • Click the Import tab
    • Click Choose File and select your SQL backup file
    • Click Go to import
  2. To restore from command line:

    # Restore from backup file
    mysql -u contact_app -pStrongAppPassword123! contact_db < /var/backups/mysql/contact_db_backup_YYYYMMDD_HHMMSS.sql
    

๐Ÿ”ง Troubleshooting

If phpMyAdmin shows “The mbstring extension is missing”:

If you can’t access phpMyAdmin:

If MySQL connection fails in phpMyAdmin:

If backup script fails:

๐Ÿš€ Optional Challenge

Want to enhance your phpMyAdmin setup further? Try:

๐Ÿ“š Further Reading

Done! ๐ŸŽ‰

Excellent work! You’ve successfully installed and configured phpMyAdmin for your LEMP stack and learned how to use it for database administration, backup operations, and security hardening! You now have a powerful web-based tool for managing your MySQL databases efficiently. ๐Ÿš€