Login loop after Leapp from Centos 7.9

I have finally managed to upgrade the CentOS to Rocky Linux 8.10 using Leapp. Before that I had to uninstall a few packages that inhibited preupdate and update.
The initramfs failed near the end saying some python program cannot import pyudev, and put me in rescue mode.

I rebooted and got to the login screen, the OS is displayed as Rocky Linux 8.10. But whenever I login using correct credentials, it displays motd in a flash and returns to the login screen. Incorrect credentials are denied normally.

The machine can be pinged but cannot ssh, saying client_loop: send disconnect: Broken pipe

GRUB menu does not show up. Even for initramfs it directly went there after rebooting.

Can anyone help with this? I should be near the end of successfully upgrading while preserving all data. Any help is welcome! Thank you!

First, Rocky does not support in-place conversion from one distro to another (as in different major version). The el8 → el8 sidegrade is no real change.

Fresh install, addition of necessary packages, deploying appropriate config for them, and transfer of user data is the way. By default, regular user data is in separate filesystem – /home. That would not be affected by replacement of /. Services, like Apache and MariaDB have user data under /var, within / and do need backup or something, but for example SQL engine version changes do require database migration procedures that Leapp probably won’t do anyway.

The list of packages and config for them … Red Hat does now document how to manage such configuration with Ansible (the “System Roles”). That approach really helps with new installs.


What one can do when one’s system has a showstopper issue?

One can take the Rocky Linux 8 install image (USB) and boot it to “troubleshoot” mode.
Rather than starting the installer, it will seek existing Rocky from disks, mount those filesystems
and offer chroot into there. Then one can do forensics and possibly rescue.

Thanks for the tip! The user files that need to be carried over should be /etc/passwd, /etc/group, /etc/shadow, /etc/subuid and /etc/subgid right?

No user files are data like under /home or any other data like databases in say /var/lib/mysql or /var/lib/pgsql, or /var/www etc.

You do not copy /etc/shadow, /etc/passwd or any of those files.

One has to create the groups and users. The “Ansible playbook” below
makes sure (when run) that the entries on list local_users exits:
Groups
smta:x:1000:
atms:x:9000:
Users
smta:x:1000:1000:smta:/home/smta:/usr/bin/bash
atms:x:1001:9000:atms:/home/atms:/usr/bin/bash
and that the ‘smta’ is member of group ‘wheel’, which allows the use of sudo.

It does not set password (but could). If it is changed to set password, then
the passords of people would be in the play and you would know them.

One could add public ssh keys for users in the play too.

- hosts: all
  vars:
    has_homes: true
    local_users:
    - name: smta
      uid: 1000
      groups: [ wheel ]
    - name: atms
      uid: 1001
      gid: 9000
      groups: []
  tasks:
  - name: Create private groups
    group:
      name:    "{{ item.group | default(item.name) }}"
      gid:     "{{ item.gid | default(item.uid) | int }}"
    loop: "{{ local_users }}"
    loop_control:
      label: "{{ item.group | default(item.name) }}"
    when:
    - item.active | default(true) | bool

  - name: Create users
    ansible.builtin.user:
      create_home: "{{ has_homes }}"
      name:    "{{ item.name }}"
      uid:     "{{ item.uid | int }}"
      group:   "{{ item.group | default(item.name) }}"
      groups:  "{{ item.groups }}"
      comment: "{{ item.gecos  | default(item.name) }}"
      home:    "{{ item.base | default('/home') }}/{{ item.name }}"
      shell:   "{{ item.shell | default('/usr/bin/bash') }}"
    loop: "{{ local_users }}"
    loop_control:
      label: "{{ item.name }}"
    when:
    - item.active | default(true) | bool