megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

Ubuntu Bootloader Recovery

This is a guide on how to recover Ubuntu's GRUB Bootloader in the case of whenever a LVM UUID is changed or corrupted.

The Problem

The error "disk not found: /xxx-xxx" in grub rescue> mode suggests GRUB can't find the device or logical volume it was previously configured to boot from.

This usually happens when: * LVM volumes weren't activated during boot * The volume group UUID changed or became corrupted

The Context

The /xxx-xxx in the message is likely referring to a LVM volume by UUID, e.g.:

error: disk 'lvmid/XXX-XXX-XXX' not found

This typically means GRUB is referencing a missing or renamed LVM LV or VG

The Solution

Boot from a live ISO, open a terminal and follow these steps:

1. Check Disks and LVM State

sudo lsblk
sudo fdisk -l

Then:

sudo vgscan

This activates any found LVM volume groups and logical volumes.

Then verify with:

sudo lvdisplay

3. Mount the System Manually

Assuming your root volume is /dev/mapper/your_lvm_drive:

sudo mkdir /mnt/recovery
sudo mount /dev/mapper/your_lvm_drive /mnt/recovery

4. Prepare for chroot

sudo mount --bind /dev /mnt/recovery/dev
sudo mount --bind /proc /mnt/recovery/proc
sudo mount --bind /sys /mnt/recovery/sys
sudo chroot /mnt/recovery

The chroot command changes the root directory for the kernel, effectively making a specified directory the new starting point for any file access within the chrooted process.

5. Reinstall GRUB

grub-install /dev/sdX  # Replace sdX with the actual disk (like /dev/sda)
update-grub

Exit chroot mode, unmount the recovery path from live-boot OS and reboot the system:

exit
sudo umount -R /mnt/recovery
sudo reboot

Hope you found this article useful!

Eliminate Laravel .env leakage between multiple sites on Apache (Windows)

Today, I learned something pretty important (and frustrating until I figured it out): if you're running multiple Laravel applications on Apache (Windows) using mod_php, you can run into a strange bug where one site's .env settings override the other.

This became painfully obvious when I noticed that one of my Laravel sites was randomly connecting to the wrong database, even though the configurations in each .env were different. Weird, right?

Turns out, the culprit was mod_php.

The problem

I had two Laravel sites hosted on the same Windows machine with Apache. Both were running fine — until they weren’t.

The issue? Sometimes one site would pick up the database config of the other. One minute I’d be on Site A, and then somehow its .env settings were coming from Site B.

This is just total chaos and worse, this issue existed from more two years until I decided to dive into the problem.

The cause

Laravel loads .env values during the bootstrap process and caches them in memory. When using mod_php, Apache loads PHP as a module once and shares it across all sites. That means only one copy of Laravel’s environment gets loaded — and reused across both apps.

So even if each app had its own .env, it didn’t matter. Apache was essentially saying:

“Hey, here’s PHP. I already booted Laravel with this config — just reuse it.”

The solution

After some digging, the solution is ditch mod_php and switch to FastCGI (mod_fcgid).

With FastCGI, each site runs its own instance of PHP via php-cgi.exe, which boots Laravel in isolation — meaning each .env file is respected per site.

How to configure it?

First, you need to disable mod_php in httpd.conf:

# LoadModule php_module "C:/path/to/php/php8apache2_4.dll"
# <FilesMatch \.php$>
#     SetHandler application/x-httpd-php
# </FilesMatch>
# PHPIniDir "C:/path/to/php/"

Then install mod_fcgid from Apache Lounge and copy mod_fcgid.so to modules/ directory and enable it in httpd.conf:

LoadModule fcgid_module modules/mod_fcgid.so
Include conf/extra/httpd-fcgid.conf

Next, you have to create/update httpd-fcgid.conf:

<IfModule fcgid_module>
   AddHandler fcgid-script .php
   FcgidInitialEnv PHPRC "C:/path/to/php"
   FcgidWrapper "C:/path/to/php/php-cgi.exe" .php
   Options +ExecCGI
   FcgidMaxProcessesPerClass 150
   FcgidMaxRequestsPerProcess 1000
   FcgidProcessLifeTime 300
   FcgidIOTimeout 120
   FcgidPassHeader Authorization
   FcgidFixPathinfo 0
</IfModule>

And then atlast, update your virtual host:

<VirtualHost *:443>
   ServerName example.com
   DocumentRoot "C:/path/to/website/public"

   <Directory "C:/path/to/website/public">
      Options +ExecCGI -Indexes +FollowSymLinks
      AllowOverride All
      Require all granted
      AddHandler fcgid-script .php
      FCGIWrapper "C:/path/to/php/php-cgi.exe" .php
   </Directory>

   SSLEngine on
   SSLCertificateFile "..."
   SSLCertificateKeyFile "..."
</VirtualHost>

Restart the nginx service and clear the laravel application cache:

httpd -k restart
php artisan config:clear
php artisan cache:clear

Bonus: Fixing 403 Forbidden Errors

After switching to FastCGI, I ran into a 403 Forbidden error on one site. That turned out to be a missing Options +ExecCGI and Require all granted in the <Directory> block. Once added, everything worked perfectly.

Result

Now, each Laravel site runs completely isolated, even though they use the same php-cgi.exe. No more .env bleed. No more wrong DBs. Just clean, independent Laravel environments — as it should be.

Takeaways

  • Don’t run multiple Laravel apps on Apache with mod_php unless you're okay with shared config risks.
  • Use mod_fcgid and php-cgi.exe for true isolation.
  • Even if using the same PHP version, FastCGI will spawn separate processes, so .env loading stays scoped.
  • Always check Apache error logs (error.log) and php_sapi_name() for confirmation.

If you’re running Laravel on Windows with Apache — this fix is a must.

Happy hosting and hope you found this article useful!

Removing Commits from a Branch Using Git Interactive Rebase

I'm working on a project that had approximately five minor incident fixes. However, I got approval from the client side to push only three of them. Luckily, my commits are atomic, so making this build was easier than I thought.

At this moment, I decided to clone the latest branch into a temporary branch and roll back two commits for today's deployment while keeping the latest branch intact with all the fixes.

To achieve this, I used Git interactive rebase, a powerful tool for modifying commit history.

Why Use Interactive Rebase?

Interactive rebase allows you to modify commit history, including:

  • Removing unwanted commits
  • Reordering commits
  • Squashing multiple commits into one
  • Editing commit messages

How I Did It?

Here’s the step-by-step process I followed:

1. Clone the Branch

Before making any changes, I cloned the branch to have a backup:

git checkout -b my-cloned-branch original-branch

2. Start Interactive Rebase

To remove specific commits, I ran:

git rebase -i HEAD~N

Where N is the number of commits I wanted to review. This opened an editor displaying the most recent commits.

3. Modify the Commit List

The interactive rebase interface showed something like this:

pick abc123 Commit message 1
pick def456 Commit message 2
pick ghi789 Commit message 3

To remove a commit, I replaced pick with drop.

To edit or squash commits, I could replace pick with commands like edit or squash.

After making my changes, I saved and closed the editor.

4. Handle Any Conflicts (If Needed)

If Git encountered conflicts, it prompted me to resolve them. I fixed the files and continued the rebase:

git rebase --continue

Key Takeaways

  • Interactive rebase is powerful for cleaning up commit history.
  • Always clone or create a backup branch before rebasing.
  • If working with a team, communicate before modifying shared branches.

This was a great learning experience, and now I feel more confident managing Git history efficiently!

Hope you found this tip useful!

Recovering MySQL After an Accidental Binlog Deletion

Last night, I found myself debugging a MySQL issue at an ungodly hour. The MySQL80 service refused to start, throwing a vague error:

The MySQL80 service started and then stopped…

Digging into mysql.err, I discovered the culprit—someone (not me! 😤) had accidentally deleted a binary log (mysql-bin.000xxx) while MySQL was still tracking it. Since MySQL relies on binlogs for replication and crash recovery, it panicked when it couldn't find the missing file.

The Fix

To get MySQL running again, I had to:

  • Disable binary logging (since this is a standalone server)
  • Delete the corrupt binlog index file (mysql-bin.index)
  • Purge all old binlog files that were hogging disk space

How to Properly Disable Binary Logging in MySQL 8.0?

Since MySQL 8.0 enables binlogs by default, simply removing log-bin=mysql-bin from my.ini wasn’t enough. I had to:

Comment out the existing binlog setting in my.ini

# log-bin=mysql-bin

Explicitly disable binary logging

[mysqld]
skip-log-bin

Delete the old mysql-bin.index file

  • This file keeps track of all binary log files.
  • Since a referenced binlog file was deleted, MySQL would fail to start if the index still contained entries for missing files.
  • Deleting it ensures that MySQL doesn’t look for non-existent logs.

After restarting the service, I confirmed binlogging was off with:

SHOW VARIABLES LIKE 'log_bin';

Output:

log_bin | OFF

In conclusion, crisis averted, disk space reclaimed and finally got some sleep. 😴

Hope you found this useful!

9 Software Books I'm Reading This Year to Become a Better Engineer

As a software engineer, continuous learning is essential. The tech industry evolves rapidly, and keeping up requires a commitment to improving skills, refining best practices, and understanding the deeper principles behind great software design. This year, I’ve curated a list of nine must-read books that will help me become a better developer, architect, and problem solver.

If you're looking to level up your software engineering skills, these books might interest you too:

The Pragmatic Programmer

By Andrew Hunt & David Thomas

"Care about the code you write and the people who will maintain it after you."

A foundational book that every developer should read. It provides practical advice on coding, debugging, and automation, making you a more adaptable and efficient engineer.

Designing Data-Intensive Applications

By Martin Kleppmann

"A well-designed system grows gracefully as the dataset, traffic volume, or complexity increases."

A must-read for backend engineers and system architects, this book explores data modeling, distributed systems, and scalability challenges.

Clean Code

By Robert C. Martin

"Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code."

Writing clean, maintainable code is a core skill for developers. This book offers practical techniques for improving code quality.

The Mythical Man-Month

By Frederick P. Brooks Jr.

"Adding manpower to a late software project makes it later."

A classic in software project management, this book explains why adding more people to a late project only makes it later.

Refactoring

By Martin Fowler

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."

A practical guide to improving existing code without altering its functionality, making it more readable and maintainable.

Domain-Driven Design

By Eric Evans

"The heart of software is its ability to solve domain-related problems for users."

This book teaches how to align software design with business logic, making complex software systems more manageable.

Working Effectively with Legacy Code

By Michael Feathers

"To change software means to change behavior. Our goal is to do so safely."

If you’ve ever had to deal with old, complex codebases, this book provides strategies for refactoring without breaking functionality.

Why Programs Fail

By Andreas Zeller

"Every bug has a cause, and every cause has a cure."

A systematic approach to debugging, helping developers diagnose and fix software defects effectively.

Extreme Ownership

By Jocko Willink & Leif Babin

"Leaders must own everything in their world. There is no one else to blame."

Leadership and accountability are critical for engineers working in teams. This book teaches how taking full responsibility leads to success.

Final Thoughts

These books cover a wide spectrum of skills—from writing clean code and designing scalable systems to debugging, refactoring, and leadership. By reading and applying the lessons in these books, I aim to become a better software engineer this year.

How to Revert a Git Commit on the Server?

Today I learned how to revert a Git commit after pulling it on a server. Whether you've made a mistake or just need to backtrack, Git offers several ways to undo commits depending on your situation. Here's a quick guide on how to handle it.

If you haven't pushed the commit yet

If the commit hasn't been pushed to the remote repository, you can use git reset to undo it.

Soft Reset (keeps changes staged)

git reset --soft HEAD~1

This moves the HEAD back by one commit but keeps your changes staged.

Mixed Reset (keeps changes unstaged):

git reset --mixed HEAD~1

This moves the HEAD back by one commit and unstages your changes.

Hard Reset (discards changes):

git reset --hard HEAD~1

This completely removes the last commit and discards any changes.

Tip: Replace HEAD~1 with HEAD~2 to go back two commits, and so on.

If you've already pushed the commit

Revert the commit (safe for shared repos):

If you've already pushed the commit and want to undo it without rewriting history, use git revert. This creates a new commit that undoes the changes.

git revert <commit_hash>

Find the commit hash using:

git log --oneline

Force Reset (i.e. if you're okay with rewriting history):

If you don't mind rewriting history (and no one else is working on the branch), you can force reset.

git reset --hard <commit_hash>
git push origin HEAD --force

⚠️Warning

This is not recommended if others are working on the same branch as it can cause conflicts.

If you just pulled and want to undo

If you just pulled and want to undo the merge, you can reset to the previous state using ORIG_HEAD.

Undo a merge pull:

git reset --hard ORIG_HEAD

This will bring your repository back to the state before the last pull.

Final thoughts

Reverting commits can seem daunting at first, but once you understand the tools Git offers, it's pretty straightforward. Always double-check before using --hard or --force to avoid accidental data loss!

Hope this helps you get back on track!

How to Delete Multiple Git Branches from the Command Line?

Whether you're cleaning up local branches after a feature merge or tidying up remote branches, here’s how you can do it.

Deleting Multiple Local Branches

To delete multiple local branches safely (only if they’ve been merged), use:

git branch -d branch1 branch2 branch3

If the branches haven't been merged and you still want to delete them, force delete with:

git branch -D branch1 branch2 branch3

Deleting Multiple Remote Branches

For remote branches, you can delete them by running:

git push origin --delete branch1 branch2 branch3

Alternatively, you can use the colon : syntax:

git push origin :branch1 :branch2 :branch3

Deleting Multiple Branches Using a Pattern

If you want to delete branches that follow a naming pattern (like feature/ branches), you can use grep and xargs:

For local branches:

git branch | grep 'feature/' | xargs git branch -d

To force delete:

git branch | grep 'feature/' | xargs git branch -D

For remote branches:

git branch -r | grep 'origin/feature/' | sed 's/origin\///' | xargs -I {} git push origin --delete {}

Final Tips

  • List branches before deleting: Use git branch for local and git branch -r for remote branches to verify which ones you’re about to delete.
  • Be cautious with force delete (-D): It will remove branches even if they haven’t been merged, so make sure you won’t lose important work.

Hope you found this useful!

Laravel Scopes vs. Builder Queries: Which Should You Use?

If you're building a Laravel application, you're probably spending a lot of time writing queries. And as your project grows, you'll inevitably face this question: Should I use scopes or builder queries? While both have their place, choosing the right tool for the job can make a world of difference. Here's my opinionated take on the matter.

The Case for Scopes

Scopes are, quite simply, one of Laravel's hidden gems. They let you encapsulate common query logic within your models, making your code clean, reusable, and easy to read. Think of them as tiny, purposeful functions designed to save you time and sanity.

Take this example:

<?php
    // In your model
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    // Usage
    $activeUsers = User::active()->get();
?>

Suddenly, instead of littering your controllers with where('status', 'active') everywhere, you have a single, reusable method that reads like English. Scopes shine when you need commonly used filters like active, published, or recent. They’re easy to use, they’re consistent, and they make your code feel more intuitive.

Why I Prefer Scopes for Reusability

Here’s the thing: in any sizable Laravel app, you’ll inevitably find patterns in your queries. Rewriting the same query logic over and over? That’s a code smell. By using scopes, you centralize your query logic, reducing redundancy and improving maintainability.

For example:

<?php
    $pubishedPosts = Post::published()->recent()->get();
?>

This reads beautifully and keeps your codebase DRY (Don’t Repeat Yourself). If the definition of "published" or "recent" changes, you only need to update it in one place. Scopes turn repetitive query logic into single lines of magic.

The Case for Builder Queries

That said, not everything belongs in a scope. Some queries are just too specific, too complex, or too dynamic. This is where builder queries come in.

Imagine you’re building a report that requires multiple joins, conditional logic, or dynamic filters. Scopes could become unwieldy here. Instead, a well-crafted builder query in your controller, service, or repository might make more sense:

<?php
    $users = User::where('status', 'active')
        ->whereDate('created_at', '>', now()->subDays(30))
        ->orderBy('created_at', 'desc')
        ->get();
?>

Builder queries are perfect for:

  • One-off operations.
  • Highly dynamic queries.
  • Scenarios where scopes would make your models bloated or overly complex.

The flexibility of builder queries is unmatched. You can construct them on the fly, adapt them to user inputs, and handle edge cases without worrying about making your models an unreadable mess.

My Opinionated Take: Use Scopes as a Default, Builder Queries for the Edge Cases

If I had to pick a side, I’d say: lean on scopes as your default tool, and reserve builder queries for those rare cases when scopes just don’t cut it. Why?

  1. Scopes enhance readability. Your queries read like sentences, and your intentions are crystal clear.
  2. Scopes promote DRY principles. They’re reusable and encapsulate logic, which makes future maintenance a breeze.
  3. Builder queries are powerful but can become messy. Unless you’re careful, a complex query in your controller can grow into a sprawling monstrosity. Keep your controllers lean and delegate to scopes or dedicated query classes where possible.

When Not to Use Scopes

There are times when using a scope might do more harm than good:

  • Too much complexity: If a scope needs multiple parameters or involves complex joins, it’s better suited as a custom query builder or a dedicated repository method.
  • Rarely used logic: Don’t clutter your models with scopes for queries that are only needed once or twice.
  • Dynamic, user-driven queries: When filters are highly variable, builder queries give you the flexibility you need.

Conclusion: Balance Is Key

Laravel gives you powerful tools to write queries, and both scopes and builder queries have their roles. Use scopes to simplify and centralize reusable logic, and reach for builder queries when flexibility and complexity demand it. By balancing both, you’ll keep your codebase clean, maintainable, and a joy to work with.

So, what’s your take? Are you a scope enthusiast or a builder query champion? Either way, Laravel’s got you covered.