Solution to os-prober not finding other operating systems (Windows & Linux)

Occasionally os-prober fails to detect other operating systems installed on other disks or partitions. While this might be due to complex issues with the installation or boot, there’s a workaround that usually remedies the issue. In this article, however, I’d like to provide information that actually solves os-prober issues once and for all and provide fundamental understanding of how this extremely popular package functions.

We will look at different approaches based on detecting other UNIX installations (including Linux and MacOS) and other Windows installations (which uses NTFS file system) when os-prober fails.

Let’s consider how os-prober functions first.

How does os-prober work?

os-prober is an impressive solution that detects operating systems and adds them to the GRUB’s boot list. But how does os-prober actually work? Often this package will be confused with things it doesn’t do and it gets a lot of bad reputation for not finding OS installations sometimes. Understanding the way os-prober works will give you more confidence in troubleshooting booting issues with Linux or Windows.

I remember when I first used os-prober and when it detected a bunch of operating systems on my disk I was so amazed. It felt like magic because for some reason I thought it did so without mounting any disks or partitions.

The reality is it’s not magic. os-prober will attempt to mount each disk/partition as read only in order to scan them for operating systems and if Linux, Windows or MacOS installations are found, it will create an additional record in the boot configuration. In doing so, os-prober will exclusively use grub-mount (this part is critical knowledge) to mount partitions/disks.

Let’s look at os-prober‘s workflow. First of all in a Linux system a disk can’t be read before it is mounted. Unless mounted, a disk (or its partitions) is just a piece of board attached to the computer. No matter how advanced the software is, it needs to be mounted before it can be read.

  • So first, os-prober temporarily mounts all the available disks to /var/lib/os-prober
  • Then it checks OS directories on them strategically such as /etc

That’s what happens when you run the following command:

grub-mkconfig -o /boot/grub/grub.cfg

And the operating systems which are found will be listed in the Grub boot menu.

To have os-prober activated along with grub-mkconfig command you will need to have the following command line uncommented in the /etc/default/grub file:


This assumes it is disabled by default.

Introducing grub-mount

os-prober utilizes grub-mount to ensure disks (especially NTFS disks) are mounted only as read-only and never written on. This prevents potential corruption in file system and the disk tables which can be fragile in some cases.

Here is the grub-mount command and its detailed options as a list:

grub-mount [OPTION...] IMAGE1 [IMAGE2 ...] MOUNTPOINT
  •  -C, –crypto: Mount crypto devices.
  • -d, –debug=STRING: Set a debug environment variable.
  • -K, –zfs-key=FILE|prompt: Load a ZFS crypto key.
  • -r, –root=DEVICE_NAME: Set the root device.
  • -v, –verbose: Print verbose messages.
  • -?, –help: Display the help list.
  • -usage: Display a short usage message.
  • -V, –version: Print the program version.

Usually you don’t have to worry about how partitions or disks are mounted as it all takes place in the background while os-prober detects and adds operating systems. But as you probably know, it often fails to do so as well.

It’s crucial to find out if grub-mount is actually functioning properly to ensure os-prober can mount and detect operating systems under the hood.

Quick Workaround 1: Forcing os-prober to detect other Linux Operating Systems

There is a quick workaround which often succeeds to help os-prober detect other Linux installations which is mounting root partitions of other Linux systems manually before running os-prober or grub-mkconfig (also sometimes used as grub-update).

Typically you would do something like this:

(Replace “dev/nvme0n1p5” with the partition or disk where other Operating System’s root is)

!! Important : Don’t casually mount Windows installations to Linux systems as this can corrupt fragile NTFS file system and your Windows installation.


mount /dev/nvme0n1p5 /mnt

grub-mkconfig -o /boot/grub/grub.cfg

Quick Workaround 2: Forcing os-prober to detect Windows on NTFS file system

Windows typically runs on NTFS file system which is quite outdated in my opinion but that’s another discussion.

You can run the following command, remember to replace your exact partition with the example below such as /dev/nvme0n1XY or dev/sdaX

Note: You will need the ntfs-3g library.

"Carefully" Mounting Windows Partitions or Disks in Linux File Systems

Below you can find the exact commands needed to safely mount a Windows partition from inside a Linux operating system with specific options that are necessary to ensure protecting the Windows OS’ integrity.

Here is what those ntfs-3g and mount options mean: (They basically ensure a secure read-only Windows partition mounting but its quite intriguing to see each option’s function.)

  • -t ntfs-3g: This option specifies the file system type to be mounted, which is ntfs-3g in this case. ntfs-3g is a third-party NTFS driver that provides read and write support for NTFS partitions on Linux systems.
  • -o ro,noexec,nodev,nosuid: These options specify various mount options for the NTFS file system:
  • ro: Mounts the file system in read-only mode, ensuring that no modifications can be made to the files on the NTFS partition.
  • noexec: Prevents the execution of binaries or programs from the mounted NTFS partition, enhancing security by disallowing the execution of potentially malicious code.
  • nodev: Disables the interpretation of special device files on the NTFS partition, ensuring that no special device files can be created or accessed.
  • nosuid: Prevents the execution of setuid programs from the mounted NTFS partition, ensuring that no programs can be executed with elevated privileges.

/dev/sdX#: This is the device file representing the specific NTFS partition you want to mount. You should replace sdX# with the actual device identifier and partition number of the NTFS partition you wish to mount. For example, /dev/sda1 represents the first partition on the first hard disk.

/mnt: This is the mount point directory where you want to mount the NTFS partition. In this example, it is set to /mnt. You can choose a different directory if desired.

sudo mount -t ntfs-3g -o ro,noexec,nodev,nosuid /dev/nvme0n1pX /mnt

grub-mkconfig -o /boot/grub/grub.cfg

Fixing os-prober Problems' Root Causes

In most cases os-prober fails to detect other OS installations because one of its dependencies isn’t functioning properly.

In majority of the cases, fixing os-prober means fixing grub-mount which is one of the major background actors os-prober relies on.

Try to isolate the issue by manually using grub-mount to mount a partition.

sudo grub-mount /dev/nvme0n1p2 /mnt

You might get an error like:

Error: grub-mount: error while loading shared libraries: cannot open shared object file: No such file or directory

Missing means this particular library is missing. To confirm you can run a find command on the root directory.

sudo find / -name 2> /dev/null

Last part silences the irrelevent errors such as accessing proc. Most likely nothing will be found because libfuse3 doesn’t exist on your system and that’s most likely because fuse3 isn’t installed.

If we look at the dependencies of grub:

Name : grub
Version : 2:2.06.r591.g6425c12cd-1
Description : GNU GRand Unified Bootloader (2)
Architecture : x86_64
Licenses : GPL3
Groups : None
Provides : grub-common grub-bios grub-emu grub-efi-x86_64
Depends On : sh xz gettext device-mapper
Optional Deps : freetype2: For grub-mkfont usage [installed]
fuse3: For grub-mount usage
dosfstools: For grub-mkrescue FAT FS and EFI support [installed]
lzop: For grub-mkrescue LZO support
efibootmgr: For grub-install EFI support [installed]
libisoburn: Provides xorriso for generating grub rescue iso using grub-mkrescue
os-prober: To detect other OSes when generating grub.cfg in BIOS systems [installed]
mtools: For grub-mkrescue FAT FS support

You can see that fuse3 is listed as an optional dependency for grub-mount. Even if you have fuse or fuse2 you will want to install this fuse3 grub optional dependency so that grub-mount can work so that os-prober can work.

Depending on your Linux distribution you can use one of the following commands:

sudo pacman -S fuse3
sudo apt-get install fuse3
sudo yum install fuse3
sudo zypper install fuse3
sudo dnf install fuse3

You can also compile fuse3 yourself. See Installing AUR Packages.

Once you clear the grub-mount-related issues you will see that it functions properly and you can navigate to your mount point with sudo cd to confirm, it might not appear in lsblk output due to permissions. You will also see that os-prober now works as it should.

sudo grub-mount /dev/nvme0n1p2 /mnt

In my experience, most os-prober fails boil down to issues with executing grub-mount command or dependencies and/or libraries involved such as fuse or libfuse3.

Hopefully, methods above can provide a sensible alternative to manually mounting those partitions so that os-prober can pick them up and add them to GRUB.

You can apply some of the suggested solutions above for detecting and adding boot records for Debian, Arch Linux, Fedora, Ubuntu, Deepin, Manjaro, CentOS, Linux Mint, EndeavourOS and many others as well as Windows 10 and Windows 11. Please make sure to mount Windows partitions carefully as explained above as writing on a Windows NTFS disk from a Linux system can corrupt your Windows installation. (Methods shared above to mount Windows properly).

Fixing Grub on an Encrypted Luks Disc

Deciding on Different Boot Solutions

Fixing Grub on an encrypted disc can be similar to fixing unencrypted Linux installation or it can be quite different.

It’s important that you understand your exact situation first and it mainly comes down to:

  • Mount points
  • Encryption

Boot Partition Mount Points

Normally, you will have a structure similar to this:

  • /boot : You will see Linux kernel and initramfs right here.
  • /boot/grub : You will have grubenv, grub configuration here.
  • /boot/efi : You will find the efi bootloader here.

Encryption of Disc or Partitions

It’s common to encrypt only the root partition with cryptsetup and leave the boot partitions unencrypted.

This is useful especially if you are sometimes using other bootloaders or dual-booting with Windows etc. It’s slightly less-secure obviously since your boot partition is unencrypted. But unless you are Ethan Hunt or Edward Snowden or something it should be fine.

Logic of Boot Partition Mounting Points

Understanding both sections is crucial because if you mount your boot partition to only /boot/efi , then grub-install will install EFI bootloader there but the rest will be on /boot directory which is a directory on the encrypted root partition.

If you however, mount boot partition to /boot now the grub installation as well as /boot/efi and linux kernel (plus initramfs) will all be on the unencrypted /boot directory.

A mini-test to understand this is, if you are using the /boot dir for boot partition and if you unmount boot partition local /boot directory of the root partition should be completely empty,  Otherwise when you unmount the boot partition only /boot/efi would be empty.

Implications of it all

Hopefully it’s clear that we have two scenarios where Grub can freely read all boot files including kernel versus grub can only read EFI bootloader entry and then it would need encryption password to proceed.

Solutions will be different and the former is less complicated and generally convenient while the latter is more secure. Rest assure, in both cases you can save your operating system even if you completely wipe the boot partition.

Re-generating vmlinuz linux kernel and initramfs files.

If you have accidentally deleted your boot directory’s content also, this is actually an easy fix to replace those files.

First chroot into your root partition using a live USB.

In a Linux computer, typically crucial system files such as initramfs, vimuz-linux kernel and efi and grub folders reside inside the boot directory.

Although these are seriously important system files for a computer, they can actually be restored quite conveniently in most cases.

To generate linux kernel and initramfs files simply run this command:

mkinitcpio -P

This will recreate the files named:

  • initramfs-linux-fallback.img
  • initramfs-linux.img
  • intel-ucode.img
  • vmlinuz-linux

under the boot directory.

Solutions for Luks encrypted Root Partition only

Most tutorials will suggest following mount points when installing grub.

sudo mount /dev/sdXY /mnt/boot/efi
sudo mount /dev/sdXX /mnt

However, when you are dealing with a luks encrypted root partition, you will want to mount as below:
(See below for more explanation on this.)

sudo mount /dev/sdXY /mnt/boot
sudo mount /dev/sdXX /mnt

This is mainly because we don’t want grub and linux kernel will be installed inside /boot directory and we don’t want them to fall outside the unencrypted EFI partition. If they are installed on the root partition, they won’t be accessible during startup boot loading period as they will be on the encrypted partition.

Luks encrypted systems are in most cases

  • sda
    • sda1 (Buffer for Legacy)
    • sda2 (EFI Partition)
    • sda3 (Luks Encrypted Root)

In 90%+ of the cases users don’t have to encrypt the boot partitions as there won’t be any personal data in there (there can still be security implications).

This means uncommenting #GRUB_ENABLE_CRYPTODISK=y is usually not necessary.

If you are encrypting the whole disk including the boot partitions however, this is also possible and you will need to uncomment. see below section.

When grub configuration goes wrong on an encrypted setup users often get errors like below while attempting to reinstall grub:

grub-install: error: attempt to install to encrypted disk without cryptodisk enabled. Set `GRUB_ENABLE_CRYPTODISK=1′ in file `/etc/default/grub’..

Don’t do this:


!! Leave this option commented unless your EFI boot partition is encrypted (luks). !!

However, let’s reiterate this, unless your boot partition is encrypted as well as your root partition, you don’t need to enable crypto disk in grub configuration. But why the error then?

The answer is, in most cases it will be a mounting issue. Let’s clarify a couple things to solve this issue forever.

Normally root partition is mounted to /mnt while EFI partition is mounted to /boot/efi

In a luks encrypted system however, it makes more sense to mount EFI partition (for example /dev/sda2) into /boot instead of /boot/efi.

This is because while you install grub to /boot/efi, linux kernel and initramfs will remain in /boot directory.and if the /boot resides under encrypted /mnt such as /mnt/boot, this means kernel and initramfs files will fall outside the unencrypted EFI partition and they will be inside the luks partition. In this case grub-install will think you are trying to install grub to an encrypted disc and suggest crypto disc to be enable although you actually don’t need that if you mount properly.

Long story short, 

mount EFI partition to /mnt/boot

create /mnt/boot/efi

install grub to efi directory with –efi-directory=/boot/efi argument


## !! ATTENTION: change sdaX as need, values below are hypothetical !!
# Assuming sda3 is encrypted root partition and sda2 is unencrypted EFI partition.

sudo cryptsetup luksOpen /dev/sda3 cryptdisc
mount /dev/mapper/cryptdisc /mnt
mount /dev/sda2 /mnt/boot

Chroot into /mnt and install and configure grub on right mount points as discussed above.

Make sure /etc/fstab has the correct mount points as well for after the reboot.

arch-chroot /mnt

grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB
grub-mkconfig -o /boot/grub/grub.cfg

Now, if you need to regenerate vimuz-linux kernel and initramfs files, you can simply run the command below and they will be created inside the boot directory which is unencrypted as EFI partition is mounted there.

You might have to install linux kernel if it’s deleted.

sudo pacman -S linux

mkinitcpio uses linux kernel to create initramfs or initial ram disk file system.

mkinitcpio -P

After running mkinitcpio, run grub-mkconfig as above again and then you can unmount everything with umount -a and reboot.

-P flag signifies all presets which can be found inside the /.etc/mkinitcpio.d/linux.preset file as below:

# mkinitcpio preset file for the 'linux' package


PRESETS=('default' 'fallback')

#default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"

fallback_options="-S autodetect"
Finally, this will all result in a harmonious GRUB > initramfs > kernel > root pipeline as explained below:

Solutions for Luks encrypted Root & Boot Partitions

In this case solutions won’t be too different to above. Edit /etc/default/grub file to uncomment below command. This will allow Grub to recognize and boot from Encrypted boot directory/partition. Obviously this will cause you to get password prompt twice:

  • Once before boot
  • Once before system is mounted

If you enable cryptodisk but you’re actually not using encrypted boot partition you might get an error like below:

Error : grub-install: error: attempt to install to encrypted disk without cryptodisk enabled. Set `GRUB_ENABLE_CRYPTODISK=1′ in file `/etc/default/grub’..

Solution is either, don’t use GRUB_ENABLE_CRYPTODISK=y or actually encrypt your boot partition. If it’s a bit confusing make sure to understand the mount points at the beginning of this tutorial.

Uncommenting the line above only instructs Grub about encrypted boot. It doesn’t solve all your boot problems. If something is wrong with your grub installation or configuration, you will still have errors like this one:

Enter passphrase for (hd,gpt):

Error : Invalid passphrase.
Error : access denied.
Error : no such cryptodisk found.
Error : disk ‘cryptouuid/……’ not found.
Entering rescue mode…
grub rescue>

To solve this, you can make sure grub-install is properly executed for /boot/efi and contains valid linux kernel and initramfs files along with grub folder.

If somehow you managed to corrupt or remove the Encryption Headers in the beginning of the encrypted disc, in most cases there is not much to do to save that system. Getting the boot errors and invalid passphare above doesn’t necessarily mean this is the case and just fixing the boot issues will resolve all errors. Unless again, if encryption data is corrupted. You can read more about LUKS Encryption below:

LUKS Encryption Headers

LUKS (Linux Unified Key Setup) is a disk encryption specification used in Linux-based systems. It provides a standard format for storing encrypted data on disk, allowing for secure storage of sensitive information.

In the context of LUKS, the “LUKS encryption header” refers to a specific data structure that contains important information about the encrypted disk or partition. This header is located at the beginning of the encrypted device and holds essential metadata needed to access and decrypt the data.

The LUKS encryption header includes the following information:

Key Slots: The header contains several key slots, which store encryption keys used to decrypt the data. Each key slot can hold a passphrase or a key file that grants access to the encrypted disk. Multiple key slots allow for the use of different passphrases or multiple users with distinct encryption keys.

Cipher and Encryption Parameters: The header stores information about the encryption algorithm, key size, and other parameters used for the encryption process. These parameters determine the strength of the encryption and the algorithm used to protect the data.

UUID and Label: The LUKS header may also include a Universally Unique Identifier (UUID) and a user-defined label. The UUID uniquely identifies the encrypted device, while the label provides a human-readable identifier for easier identification and management.

Anti-Forensic Information: LUKS supports anti-forensic features to mitigate attacks aimed at revealing information about the encrypted data. The header may include details such as the number of times the device has been opened or various parameters related to anti-forensic measures.

The LUKS encryption header is crucial for the proper functioning of the encrypted disk or partition. It contains the necessary information for the system to validate and access the encrypted data. During the boot process or when mounting an encrypted device, the system reads and verifies the header, prompts for a passphrase or key, and uses the provided information to decrypt the data.

It’s important to ensure the security and integrity of the LUKS encryption header. Any damage or corruption to the header could lead to the loss of data or difficulties in accessing the encrypted device. Therefore, it is recommended to keep backup copies of the LUKS header and store them securely to ensure the ability to recover the encrypted data if needed.

Flow of a Boot Process in Linux Systems

GRUB, or the GRand Unified Bootloader, is a commonly used bootloader in Linux systems. Its main function is to load and start the operating system. While the Linux kernel and initramfs files are essential components of the operating system, they need a bootloader like GRUB to be loaded into memory and executed.

Here’s a brief overview of how GRUB functions when Linux is installed on a machine:

Powering on the machine: When you power on a computer, the BIOS (Basic Input/Output System) or UEFI (Unified Extensible Firmware Interface) firmware initiates the boot process.

GRUB installation: GRUB is typically installed in the Master Boot Record (MBR) or the EFI system partition, depending on the boot mode (legacy or UEFI).

GRUB initialization: Once the firmware locates and loads GRUB, GRUB initializes itself and presents the user with a boot menu (if configured).

Kernel and initramfs loading: From the boot menu, the user selects the desired Linux kernel and initramfs. GRUB then reads the necessary files from the configured boot partition.

Passing control to the kernel: GRUB transfers control to the loaded Linux kernel by passing the necessary parameters and memory location details.

Kernel execution: The Linux kernel takes control and starts initializing the hardware, loading drivers, and setting up the essential components of the operating system.

Initramfs usage: The initramfs (initial RAM file system) is a temporary root file system that the kernel mounts early during the boot process. It contains essential drivers and utilities required to mount the actual root file system. The kernel uses initramfs to load the necessary modules and prepare the system for the handover to the real root file system.

How to Properly Serve Python Apps with PM2 and Gunicorn on any Port and any Server

Gold unicorn for Python Flask Apps

Normally you can serve a Python Flask app using Gunicorn like this:

gunicorn -b app:app

This binds all network traffic ( on port 8080 to program’s app object. First one is the file name (without py extension) and second one is the app object inside the Python code.

Normally you can serve a Python Flask app using Gunicorn like this:

sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload

Here is a common structure of a flask app:

Using Gunicorn with Pm2

With pm2 usage of gunicorn is slightly more complicated.

pm2 start "gunicorn -b" app:app

Or giving the app a name for monitoring purposes like below.

pm2 --name=PythonApp start "gunicorn -b" app:app

The difference between using and localhost as the bind address in the Gunicorn command can affect the accessibility of the server.

When you use gunicorn -b app:app, Gunicorn binds to all network interfaces, allowing connections from any IP address, including external IP addresses. This makes your server accessible from both the local machine and other machines on the network.

However, when you use gunicorn -b localhost:8000 app:app, Gunicorn only binds to the loopback interface, also known as This means that the server is only accessible from the local machine itself. Connections from other machines on the network or external IP addresses will be blocked.

Add Ingress Rule to allow Inbound Traffic

You should configure the server to allow Inbound traffic for specific port you’d like to use such as 8000, 8080, 80, 81, 3000, 5000 etc.

Port 80 is the universally accepted HTTP port and browsers automatically look for port 80 when a root domain URL or IP is accessed.

You need to open the port to listening under VCN (Virtual Cloud Networks) > Subnet > Default Security List for vcn-xyz > Add Ingress Rules

Listing Post Listening Activity

lsof -i -P -n

You can use lsof to show a list of files being served and filter it to internet files only and force it to show the ports instead of app names.

-i: Filters the output to show only Internet-related open files (network connections).
-P: Prevents the conversion of port numbers to service names.
-n: Skips the conversion of IP addresses to hostnames.

Alternatively, you can use netstat to do something similar:

netstat -tln  # Show only listening TCP ports
netstat -uln  # Show only listening UDP ports

If you don’t see your desired port here. First place to look is the firewall rules.

Additionally, you will want to allow your cloud instance or server to accept inbound traffic from those ports if you want to achieve access from other machines to the specific port.

A good test for this is to use curl command.


curl localhost:8080

works from inside ssh but you still can’t access 8080 through public ip that means inbound traffic is not being allowed.

Serving Flask App Using Gunicorn via Pm2

Even a classier way to serve Flask app is to generate a configuration JS file and instruct Pm2 to use gunicorn to serve the Flask app.

File can be created as below:

module.exports = { 
  apps: [ 
      name: 'Flaskmyapp', 
      script: 'gunicorn', 
      args: 'app:app -b', 
      interpreter: 'python', 
      interpreter_args: '-u', 
      instances: 1, 
      autorestart: true, 
      watch: false, 
      max_memory_restart: '1G', 
      env: { 
        FLASK_APP: '', 
        FLASK_ENV: 'production', 

Nginx Reverse Proxy

It’s common to reverse proxy with Nginx to specific ports. You can instruct Nginx to Reverse Proxy multiple ports, especially other than port 80, like this:

server {
  listen 80;
  server_name servername;

  location / {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

server {
  listen 81;
  server_name servername;

  location / {
    proxy_pass http://localhost:5000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

In this example port 80 on public IP will forward to port 3000 while port 81 on public IP forwards to port 5000.

How to remove expired Git PAT and add the new PAT to Git Clone

Below command will remove Git credentials such as PAT globally.

git config --global --unset credential.helper

While the one below will remove stored and cached Git credentials from specific repository you are in.

git config --unset credential.helper

After removing the credentials, you can reintroduce the new PAT by setting the remote url for origin or any other branch you are using as below:

Use git set-url to set the upstream url for pushing and fetching.

git set-url origin https://Your-PAT-here@>

The git remote -v command is used to view the remote repositories associated with your Git repository. It shows the names and URLs of the remote repositories that your local repository is configured to interact with.

git remote -v

You should get an output similar to below. This shows the urls associated with your repo and if the PAT tokens (before @ sign and after https://) look updated you are golden.

origin (fetch)
origin (push)