# almalinux-deploy converts an EL host in place, with a boot-time risk

> almalinux-deploy is a shell script that converts a running CentOS, RHEL, Rocky or Oracle Linux machine to AlmaLinux without reinstalling, by replacing release packages and running a distro sync. It refuses non-GRUB2 bootloaders, warns you to work from a reliable console, and it can resume an interrupted migration from a state directory.

**AlmaLinux/almalinux-deploy** — EL to AlmaLinux migration tool.

- Repository: https://github.com/AlmaLinux/almalinux-deploy
- Stars: 602 · Forks: 82
- Language: Shell
- License: GPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/almalinux-almalinux-deploy

## An in-place distro conversion, not an installer

almalinux-deploy is a single shell script whose job is to take a machine already running an Enterprise Linux derivative and turn it into AlmaLinux without reinstalling the operating system. The mechanism is a package level conversion: the script swaps the release packages and then runs a dnf distro-sync, so the running system keeps its configuration, its packages and its data while the distribution identity underneath is replaced. The list of source systems is broad. CentOS Linux 8 from 8.4 onwards, CentOS Stream 8, 9 and 10, Oracle Linux 8, 9 and 10, RHEL 8, 9 and 10, Rocky Linux 8, 9 and 10, MiracleLinux 8 and 9, and Virtuozzo Linux 8 and 9. Architectures covered are x86_64, aarch64, ppc64le and s390x. The target audience is an administrator with a fleet of existing hosts and a requirement to move them onto a community distribution, and the appeal is precisely that nothing is reinstalled, so application state and custom packages survive.

## GRUB2 is the hard boundary of the whole tool

The boot story is where this conversion can hurt you, and the documentation is direct about it. Legacy BIOS with GRUB2 is supported, UEFI with GRUB2 is supported, and UEFI with Secure Boot enabled is supported through GRUB2 with shim. Nothing else is. Systems using LILO, syslinux, systemd-boot or any other bootloader are not supported, and the GRUB2 requirement is listed as a hard requirement for bare metal and virtual machines while being unnecessary for containers. The reason is structural rather than a matter of effort. A distro conversion replaces kernel and initramfs packages and rewrites the boot configuration, and if the boot configuration is managed by a bootloader the tool does not understand, the machine comes back to a prompt you may not be able to reach. Combined with the advice to run only from a reliable console, the practical reading is that this script assumes a serial console, an IPMI, iLO, iDRAC or VNC session in reach before you touch it.

## The requirements the script checks before it starts

The script enforces its own preconditions and exits with an error when they are not met, which is the behaviour you want from something that rewrites a running system. The requirements are root privileges, meaning the script must run as root or with sudo, the `dnf-plugins-core` package installed, GRUB2 present on hosts that need a bootloader, an active internet connection unless you point it at local mirrors with the `-l` option, at least CentOS 8.4 or an equivalent EL8, EL9 or EL10 release, enough disk space for the package downloads and installation, and a reliable console access path with no risk of disconnection. Filesystem support covers the standard EL filesystems such as xfs and ext4, with BTRFS supported on EL10 and later. Control panels are listed too, with cPanel, Plesk from version 18.0.35 and DirectAdmin named explicitly, which is the kind of detail that tells you the maintainers have thought about real hosting boxes rather than bare instances.

## Preparing the host and running the conversion

The documented sequence starts with a fully updated system and a reboot if one is needed, then a backup, and only then the script itself.

```bash
   sudo dnf update -y
   sudo reboot
```

The backup step is not boilerplate. The documentation says plainly that not every scenario was tested and that there is a risk something goes wrong, and that a backup gives you a restore point. The script is then downloaded directly from the repository.

```bash
   curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
```

And it is run as root, with the expected final line shown in the output.

```bash
   $ sudo bash almalinux-deploy.sh
     ...
     Migration to AlmaLinux is completed
```

Before running any of this on a remote host, the documentation insists you work from a console session. It suggests IPMI, iLO, iDRAC, VNC or a physical console, and if you must use SSH, it suggests a terminal multiplexer so that a dropped connection does not kill the migration.

```bash
# Start a new screen session
screen -S almalinux-migration

# If disconnected, reconnect with:
# screen -r almalinux-migration
```

After the script finishes, a reboot is recommended so the machine boots the AlmaLinux kernel, and the result is checked by reading the release file and asking grubby which kernel is the default.

## The flags that change what the script does to your repositories

The command line options are mostly about edge cases, and each one exists for a specific situation. `-f`, or `--full`, performs a dnf upgrade to 8.5 if necessary, which handles the CentOS 8 mirrorlist problems. `-d`, or `--downgrade`, allows a downgrade from CentOS Stream to stable AlmaLinux. `-l=URL`, or `--local-repo=URL`, points the script at local AlmaLinux repositories for systems with no internet access. `-e=pkg1*,pkg2*`, or `--exclude`, gives a comma-separated list of packages to leave out of the distro sync. `--preserve-rhsm` keeps the Red Hat Subscription Manager configuration for Foreman and Katello managed hosts, and it can be combined only with `-e/--exclude`, since any other option is rejected alongside it. Two environment variables exist as well, `ALMA_RELEASE_URL` for a custom download location of the almalinux-release package and `ALMA_PUBKEY_URL` for a custom RPM-GPG-KEY-AlmaLinux download, which is what you need when the default upstream host is blocked on your network.

```bash
# Standard migration
sudo bash almalinux-deploy.sh

# Migration with automatic CentOS 8 repository fix
sudo bash almalinux-deploy.sh -f

# Downgrade from CentOS Stream
sudo bash almalinux-deploy.sh -d

# Use local mirror
sudo bash almalinux-deploy.sh -l=http://mirror.example.com/almalinux

# Exclude specific packages from sync
sudo bash almalinux-deploy.sh -e=kernel-debug*,some-package

# Use custom release package URL
sudo ALMA_RELEASE_URL=http://custom.mirror/almalinux-release-latest-8.x86_64.rpm bash almalinux-deploy.sh
```

The `--exclude` flag is the one to think hardest about. Excluding a kernel package from the sync is a reasonable way to keep a vendor kernel, but excluding the wrong thing leaves a half-converted system that still has RHEL packages on disk.

## Resuming an interrupted migration from a state directory

The feature that most reduces the risk of this kind of tool is resume support. The script keeps migration state in `/var/run/almalinux-deploy-statuses/`, and the documentation says that if a migration is interrupted you simply re-run the script and it continues from where it left off. That matters because the conversion is a long sequence of package operations, and a dropped SSH session or a power loss partway through leaves a machine in a state that is neither the old distribution nor the new one. Two log files are written, a main log at `/var/log/almalinux-deploy.log` and a debug log with detailed trace information at `/var/log/almalinux-deploy.debug.log`, and previous logs are preserved with a timestamp suffix such as `almalinux-deploy.log.20260302153045`. Note that the state directory lives under `/var/run`, which is conventionally cleared on boot, so resuming works across an interrupted run on a running machine rather than across a reboot that already happened.

## RHEL sources, containers, and the licence terms

Two behaviours are worth isolating. When the source is RHEL, the script unregisters from Red Hat Subscription Manager, removes subscription-manager related packages, disables RHEL-specific DNF plugins, and backs up and removes the RHEL repository files. `--preserve-rhsm` stops all of that and keeps the subscription configuration, at the price of the administrator ensuring the correct repositories are set for AlmaLinux. In a container the script detects an OCI compliant environment and skips kernel installation, skips GRUB configuration updates, skips EFI boot record management, and excludes filesystem and bootloader packages from the sync, so containers need no bootloader at all. The licence is GPL-3.0, which means the script itself is covered by copyleft if you distribute a modified version, though running it on your own systems raises no obligation. The repository also carries a Vagrantfile, a `molecule` directory, a `Jenkinsfile`, a bats test file and ansible-lint and yamllint configuration, so the script is tested in a lab as well as documented for humans. The last push to the repository was on 2026-09-02, and there are no tagged releases, so the script version is whatever `almalinux-deploy.sh -v` reports.

## Conclusion

Adopt almalinux-deploy when you have to move an existing EL8, EL9 or EL10 machine to AlmaLinux without reinstalling and you have a console, a backup and a recent CentOS 8.4 or newer base to start from. Do not adopt it on a host with LILO, syslinux or systemd-boot, since the script supports only GRUB2, and not for a host you cannot reach out of band when the reboot goes wrong. Before you run it, take the backup the documentation insists on, confirm your bootloader is GRUB2, and check that the script's requirement checks pass on a test machine first.

## FAQ

### Which bootloaders does almalinux-deploy support?

Only GRUB2, in legacy BIOS, UEFI and UEFI with Secure Boot through shim. Systems using LILO, syslinux, systemd-boot or other bootloaders are not supported, and containers need no bootloader at all.

### How do I resume an interrupted almalinux-deploy migration?

Re-run the script. It keeps migration state in `/var/run/almalinux-deploy-statuses/` and continues from where it stopped.

### What does --preserve-rhsm do in almalinux-deploy?

It stops the RHEL-specific behaviour, meaning the script does not unregister from Subscription Manager, remove subscription-manager packages, disable RHEL DNF plugins or remove the RHEL repository files. Administrators must then set the correct repositories for AlmaLinux themselves.

### Can almalinux-deploy run without internet access?

Yes, using the `-l=URL` or `--local-repo=URL` option to point at local AlmaLinux repositories. The `ALMA_RELEASE_URL` and `ALMA_PUBKEY_URL` environment variables can also redirect the release package and GPG key downloads.

## Sources

- [AlmaLinux/almalinux-deploy on GitHub](https://github.com/AlmaLinux/almalinux-deploy)
- [Issues](https://github.com/AlmaLinux/almalinux-deploy/issues)
- [License: GPL-3.0](https://github.com/AlmaLinux/almalinux-deploy/blob/master/LICENSE)
- [README](https://github.com/AlmaLinux/almalinux-deploy/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/almalinux-almalinux-deploy
