Overview:
Linux systems are mostly compatible with one another, even when their kernel versions are different. Hence, it is possible to migrate local user accounts from one system to the next with relative efficiency.
Although this can be procedural activities that Linux admins may sleep through with one eye open, one must stress the point of making backups prior to any system changes. Here’s an illustration of the ‘checkpoints’ taken to the test machine during this operation. Please perform due diligence as missteps can lead to dysfunctional target systems.
Moreover, the process of copying files from Source to Destination machines can vary. Option (a) is to copy .bak files as well as .tar.gz; and option (b) is to to perform raw copy of /home, /spool/mail, /spool/cron directories without dealing with tarballs. Both methods are given here, and one should only follow one path while ignoring the other.
Requirements:
- A complete system BACK UP is expected prior to performing this procedure.
- Thorough understanding of Linux users and permissions is required prior to attempting this migration.
- The admin is advised to ascertain that there is sufficient disk space at the source to store migrating files
- The destination machine is assumed to be a clean Linux OS, without any apps or users created prior
- The users database is not Active Directory or OpenLDAP integrated.
- There are no guarantees that this migration procedure will work on all systems. This information is provided only as educational materials. The author will not be liable for possible damages and adverse effects of executing these scripts.
Step 1:
Check the existing server to determine whether there’s enough space to store migrating files
coco@test-box:~# df -h | grep '^[/|F]'
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 380G 210G 150G 60% /
/dev/sda1 236M 100M 124M 45% /boot
Step 2:
Create export files (while login to Source machine)
# Optional: check for proftpd status and stop its daemon
service proftpd status
sudo service proftpd stop
# Check Linux version
lsb_release -a # case Debian/Ubuntu
cat /etc/redhat-release # case Redhat/Centos
### Extract source system users to generate 4 files: passwd.bak, group.bak, shadow.bak, gshadow.bak ###
sudo su # masquerade as root
### input root password ###
uidLowerBound=500 # set User IDs to exclude (500 for RHEL, 1000 for Debian)
exportDirectory=/root/export # set migration directory
mkdir $exportDirectory;
cd $exportDirectory;
# rm $exportDirectory/* # Optional: remove files inside export directory
# Use awk to filter out system accounts and exclude lower bound UIDs
for f in /etc/{passwd,group}; do awk -F: -vID=$uidLowerBound '$3>=ID && $1!="nfsnobody"' $f |sort -nt: -k3 > ${f#/etc/}.bak; done
while read line; do grep -w "^${line%%:*}" /etc/shadow; done <passwd.bak >shadow.bak
while read line; do grep -w "^${line%%:*}" /etc/gshadow; done <group.bak >gshadow.bak
Source: this snippet was retrieved from https://access.redhat.com/solutions/179753
# Create tarballs of users' directories
tar -zcvpf $exportDirectory/home.tar.gz /home # backup home - this is always necessary
tar -zcvpf $exportDirectory/mail.tar.gz /var/spool/mail # run ls /var/spool/mail to see if there are contents to export
tar -zcvpf $exportDirectory/cron.tar.gz /var/spool/cron # this is optional as cron should be out of scope of users migration
Create Import Directory (while login to Destination machine)
# While SSH into Destination machine
# Create import folder
importFolder=/root/import
sudo mkdir $importFolder
cd $importFolder
rm $importFolder/*
ip a # get IP address
Step 3:
Copy files over to destination
# Test ssh connections (While SSH into Source machine)
sshPort=22
adminUser=root
remoteMachine=500.500.500.500
ssh $adminUser@$remoteMachine -p$sshPort "echo 2>&1" && echo $remoteMachine SSH-SUCCESSFUL! || echo $remoteMachine SSH-FAILED!
# Don't use this command as it will yield false positives
# nc -zv $remoteMachine $sshPort
# Expected results
[coco@test-box home]# ssh $adminUser@$remoteMachine -p$sshPort "echo 2>&1" && echo $remoteMachine SSH-SUCCESSFUL! || echo $remoteMachine SSH-FAILED!
The authenticity of host '500.500.500.500 (500.500.500.500)' can't be established.
ECDSA key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '500.500.500.500' (ECDSA) to the list of known hosts.
# masquerade as root
sudo su
### input root password ###
# Recommended: use scp to copy compressed files
# Use this method if the source files are all inside the /root/export folder
adminUser=root
remoteMachine=500.500.500.500
sourceDirectory=/root/export
destinationDirectory=/root/import/ # the trailing slash is important!
scp -P $sshPort -r $sourceDirectory/* $adminUser@$remoteMachine:$destinationDirectory
# Optional: Use this method if there's a direct connection between old and new server without compressing any files to save disk space
# Raw copy /home, /var/spool/mail, /var/spool/cron directories
#scp -P $sshPort -r /home/* $adminUser@$remoteMachine:/home
#scp -P $sshPort -r /var/spool/mail/* $adminUser@$remoteMachine:/var/spool/mail
#scp -P $sshPort -r /var/spool/cron/* $adminUser@$remoteMachine:/var/spool/cron
Example: using WinSCP
Step 4:
Import users to destination Linux host (while SSH onto Destination)
Warning: these commands will over-write any users already present at the destination machine. It is highly advisable that this shall only be performed on a non-production machine. Again, backup, backup, and backup are three pervasive reminders.
sudo su # masquerade as root
### input root password ###
# Create a snapshot, checkpoint, or backup of the machine.
# Here’s an example in Hyper-V Manager: select the correct Host > pick correct VM Name > right-click > Checkpoint > OK
Hyper-V Snapshot
VMware Snapshot
# Extract the home directory contents
# format: tar -czvf name-of-archive.tar.gz /path/to/directory-or-file
# Read this:
importDirectory=/root/import # this should match the import directory in "Step 3"
cd $importDirectory;
tar -zxvf $importDirectory/home.tar.gz -C / # extract the tarball into intended destinations
tar -zxvf $importDirectory/mail.tar.gz -C / # z=call gunzip, x=extract, v=verbose, f=follow paths, -C=change directory and place extracted files there
tar -zxvf $importDirectory/cron.tar.gz -C /
# Make a backup of new server's users database
for f in /etc/{passwd,group,shadow,gshadow}; do cp $f $f.bak; done
# Import user accounts
for f in {passwd,group,shadow,gshadow}.bak; do cat $f >>/etc/${f%.bak}; done
Troubleshooting:
# Undo users database changes (requires that the .bak files exist)
for f in /etc/{passwd,group,shadow,gshadow}.bak;
do
originalName=${f::${#f}-4};
echo changing $originalName.bak to $originalName ...;
mv $originalName $originalName.bad; # change current file name to .bad
mv $f $originalName; # rename .bak file to its original name
done
# WARNING: this statement DELETES everything in the /home directory!
# How to purge all folders inside /home, except one
excludeUser=powow
regexException='^/home/$excludeUser\(/.*\)?'
# find /home -mindepth 1 ! -regex $regexException -delete
### Reset root password if it has been overwritten incidentally ###
# Case LILO
Boot: linux single
passwd
sync
reboot
# Case GRUB
Reboot > select correct kernel > press 'e' to edit > locate line starting with 'kernel' > append 'S' or 'Single' a the end of that line > press ENTER > press b to boot > type these commands:
mount -t proc proc /proc
mount -o remount,rw /
passwd
sync
reboot