Migrating users between Linux servers if the UIDs need to change?

I've been tasked with migrating information and accounts from one linux server to another. I feel confident administrating Linux servers, but I've never tried a move like this.

Googling around, I found this article. http://www.cyberciti.biz/faq/howto-move-migrate-user-accounts-old-to-new-server/

It was greatly helpful. However, I have a few questions still remaining...

  1. I still don't understand how shadow passwords are made. If I just drag and drop users from /etc/passwd and /etc/shadow, will it actually work? How do I ensure the password hashes are made the same? What about salts?

  2. If I need to refactor user / group IDs, will $ usermod -g (newgid) username on the to-move machine modify the id's on the to-move user's files?


For the first question, there is no salt issue if your shadow file is with $1$FZPUn/2R$JsQCE3TP3Uraez2P8ISIh0 password format (with a dollar, a number, a dollar at the beginning). Because, the salt ils the first part between the next dollars (FZPUn/2R in my example). The crypted password is on the rest. See man crypt, at the 'Glibc Notes' section for details.

So you can move your shadow file without risk.

For the second part, I prefer edit /etc/passwd file directly and change the groupe manualy. Your method is maybe the best (because of lock).

Don't forget files : if you change UID or GID, you must chown each to authorize your user to read his files !


Shadow passwords are what old password files used to be.

It's unfortunate the terminology that's used, but the "password file" (/etc/passwd) generally no longer contains password information. It contains user information (specifically GECOS)

Historically /etc/passwd contained a hash of your password also. However, /etc/passwd needs to be readable by certain system programs, because it contains important user information (UID, primary GID, home directory etc.)

So instead of break everything, the Unix Way is to allow backwards compatibility. So /etc/passwd was not changed and a new password file /etc/shadow was created and the password field in /etc/passwd was blanked.

/etc/shadow now only contains the minimal information needed for authentication (so that both /etc/passwd and /etc/shadow don't need to be accessed for login presumably).

The most important part of the shadow password file is the permissions which are much more restrictive.

$ ls -l /etc/shadow /etc/passwd
-rw-r--r-- 1 root root   2041 2009-08-18 13:24 /etc/passwd
-rw-r----- 1 root shadow 1213 2009-08-18 13:24 /etc/shadow

As you can see, everyone can read from /etc/passwd and /etc/shadow is only readable on my Ubuntu system by root and the shadow group (This is a Ubuntu-ism - plenty of systems only allow root to read, but 'shadow' is obviously a privileged system group).

Again, historically, your password was encrypted using DES but most modern distributions have shadow'ed passwords using the more secure (I say that tentatively now, but it's certainly more secure than DES) MD5 algorithm. Any password hash that begins with $1$ is an MD5 hash.

The salt as explained by another poster is contained within the hash itself, so these can be copied safely from one machine to another.

You shouldn't need to do much with refactoring user and group ids, unless you actually need to specify the target uid/gid. Presumably there's a conflict on the destination system or a different uid / gid numbering scheme, so this isn't normally necessary. In which case, you shouldn't need to get involved in the uid/gid muckyness here. usermod -g also takes a name as well as a number.

If you're just copying the passwd file in (i.e. not using the useradd / groupadd) tools, then you will just need to usermod -g all of the users with their primary groups).

If there is a UID / GID change, you'll probably also need to change the permissions on the users files. This is a little trickier, but I've included some code below. Hopefully it works ok!

#!/bin/bash

## Variables to change
HOMEDIR="/home"
OLDPASSWD="oldpasswd"
OLDGROUP="oldgroup"

## System binaries - shouldn't need to change
AWK="/usr/bin/awk"
GREP="/bin/grep"
FIND="/usr/bin/find"
XARGS="/usr/bin/xargs"
CHOWN="/bin/chown"
CHGRP="/bin/chgrp"

${AWK} -F":" '{print $1,$3}' < ${OLDPASSWD} | \
while read user uid; do
    if [ $? -ne 0 ]; then
        echo "EOF"
    fi

    echo "[uid: ${uid} -> ${user} on ${HOMEDIR}]"
    ${FIND} ${HOMEDIR} -uid ${uid} -print0 | \
            ${XARGS} --no-run-if-empty -0 ${CHOWN} ${user} 
done 

${AWK} -F":" '{print $1,$3}' < ${OLDGROUP} | \
while read group gid; do
    if [ $? -ne 0 ]; then
        echo "EOF"
    fi

    echo "[gid: ${gid} -> ${group} on ${HOMEDIR}]"
    ${FIND} ${HOMEDIR} -gid ${gid} -print0 | \
            ${XARGS} --no-run-if-empty -0 ${CHGRP} ${group} 
done 

You will need the old /etc/passwd and /etc/group from the machine you're migrating from. When you copy the users' content (if you're using tar use the 'p' flag to preserve permissions) the uid/gid should be retained when you extract. This probably means a bunch of files in each users home directory that they don't own.

This does two things:

  1. It runs through each line of the passwd file and grabs the OLD uid and the username. It finds every file in /home which is owned by the old uid and runs

    chown

  2. It runs through every group in the old group file and grabs the old gid and the group name. It finds every file in /home which is owned by the old gid and runs

    chgrp

You can edit the old passwd file to only do this for users that are in home

e.g.

grep "/home" oldpasswd > oldpasswd.filter

Or for only certain users in a particular UID range (100 and 200 in the example below).

awk -F":" '$3 > 100 && $3 < 200 {print $0}' oldpasswd > oldpasswd.filter

As you've realized, the tricky part here is relabelling all the files you have with the new UID/GID information. If you use usermod to change the UID, it will fix files owned by the user in their home directory, but that's as much as you get for free--it's only those files and there's no assist for gid changes. To make group changes or to sure you got all of the user's files (not just the ones in their home), you really need to run find across the whole filesystem to go looking for them. There's a good example at Changing UIDs and GIDs for a user.