Batch-Create Linux Accounts Safely with newusers
newusers writes straight to /etc/passwd, /etc/shadow and /etc/group in one pass, fast for a dozen accounts, risky if one field is wrong. You will finish with a controlled batch file that creates the accounts, assigns their primary groups and home directories, and lets newusers set passwords through the system's PAM configuration. The examples match shadow-utils 4.13, installed here as passwd 1:4.13+dfsg1-4ubuntu3.2.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 20 minutes, including a careful review. You need root access, a maintenance plan for the account database, and a private working directory. This command changes /etc/passwd, /etc/shadow, /etc/group and potentially /etc/gshadow, do not experiment on a production host without a backup and a tested recovery route.
1. Check the Installed Command
Read the local help before you prepare any input, it is an ordinary, read-only check:
$ command -v newusers
/usr/sbin/newusers
$ newusers --help
Usage: newusers [options]
Options:
-b, --badname allow bad names
-h, --help display this help message and exit
-r, --system create system accounts
-R, --root CHROOT_DIR directory to chroot into
$ dpkg-query -W -f='${Package} ${Version}\n' passwd
passwd 1:4.13+dfsg1-4ubuntu3.2
Only the options shown here belong to this installed interface. Input can be a named file or standard input, and the command itself needs elevated privileges because it writes the system account databases.
Checkpoint
Confirm the package version and command path are the ones you actually intend to use, and stop if a configuration-management tool owns these files and would overwrite a manual change.
2. Understand the Seven Input Fields
Each input line has the same seven colon-separated fields as a password-file entry:
pw_name:pw_passwd:pw_uid:pw_gid:pw_gecos:pw_dir:pw_shell
For a new ordinary user, leave the UID empty, use the username as the GID field, describe the account in GECOS, choose an explicit home path, and pick a real shell, for example:
alice:$6$REPLACE_WITH_A_HASH: :alice:Alice Example:/home/alice:/bin/bash
There must be no space in the empty UID field, the compact form is:
alice:$6$REPLACE_WITH_A_HASH::alice:Alice Example:/home/alice:/bin/bash
Warning
The password field is live input for the account password, and the file holds unencrypted password material while you are preparing it. Never put a normal plaintext password here. The safest choice is a locked placeholder, with passwords set separately through your approved enrolment process. If your PAM policy allows it, a precomputed hash works too, but protect the file just as carefully either way.
The UID field accepts an empty value for automatic allocation, a number, or the name of an existing user whose UID should be reused. The GID field accepts an existing group name, a number, or a new group name: an unknown group name gets created, and a numeric GID with no matching group creates one named after the user.
3. Prepare a Private Batch File
Create the file somewhere only root can read. This example uses a locked password marker, so no usable password ever sits in the batch file:
# install -d -m 0700 /root/newusers-work
# install -m 0600 /dev/null /root/newusers-work/accounts.txt
# editor /root/newusers-work/accounts.txt
Put one line per account, no header:
alice:!: :alice:Alice Example:/home/alice:/bin/bash
bob:!: :bob:Bob Example:/home/bob:/bin/bash
Remove the spaces around the empty UID field before saving, the valid version is:
alice:!::alice:Alice Example:/home/alice:/bin/bash
bob:!::bob:Bob Example:/home/bob:/bin/bash
Review every username, group name, home path and shell. newusers never checks a shell for existence, so a typo can leave an account unable to start a login shell, and it never creates missing parent directories either, /home must already exist before /home/alice can be.
Warning
Do not email this file, paste it into a ticket, commit it to Git, or leave it readable by anyone else. Remove it once you have verified the accounts, following your organisation's retention rules.
4. Check the Target Paths Before Changing Accounts
These checks change nothing. Confirm the parent directory exists and the requested shells are actually present:
# test -d /home && echo '/home exists'
/home exists
# test -x /bin/bash && echo '/bin/bash is executable'
/bin/bash is executable
# getent passwd alice bob
An empty result from getent means those names are not currently known to the configured name service. If either name already exists, stop and decide whether you really meant an update, newusers will change an existing user's fields, it is not a create-only command.
5. Run the Batch With a Review Point
Take a backup through your normal system backup process before you write anything, then run the file as root:
# cp --preserve=mode,ownership,timestamps /root/newusers-work/accounts.txt /root/newusers-work/accounts.txt.before-run
# newusers /root/newusers-work/accounts.txt
# printf 'newusers exit status: %s\n' "$?"
newusers exit status: 0
Do not expect guaranteed terminal output, a successful run can be silent, the exit status is your first real check. Shadow runs a first pass for account and group changes, then a second pass for password updates through PAM, and a password-update failure is reported without necessarily stopping the other updates.
Tip
The database update is designed to avoid committing first-pass changes if an error happens before the final write, but that is not a substitute for a backup. A failed final write, a failed home-directory creation, or a later service policy can still leave you with something to repair.
Checkpoint
If the command reports an error, stop. Do not rerun it blindly, read the message, check the account databases with getent, and compare them against your backup.
6. Verify Identities, Groups and Homes
Check each account through the system's name-service view:
# getent passwd alice
alice:!:1001:1001:Alice Example:/home/alice:/bin/bash
# id alice
uid=1001(alice) gid=1001(alice) groups=1001(alice)
# stat -c '%U:%G %a %n' /home/alice
alice:alice 750 /home/alice
Your UID and mode can differ. On this host UID_MIN and GID_MIN are both 1000, and HOME_MODE is 0750, if HOME_MODE is unset the UMASK value shapes the home directory mode instead. Check the actual result rather than assuming a default.
If a home directory could not be created because its parent was missing, newusers just keeps going, the account can end up existing without its home. Create the parent, then create and chown the home deliberately, or fix the input and follow a documented recovery procedure. Changing a home path for an existing account never moves or copies the old contents.
7. Set or Recover Passwords Separately
A locked marker such as ! earns its keep when account creation and password delivery are separate stages. Confirm the account is locked, then use your approved password-setting workflow:
# passwd -S alice
alice L 2026-09-25 0 99999 7 -1
# passwd alice
The exact status date and fields will vary, L means a locked password in the common shadow implementation. The second command is interactive, needs elevated privileges, and only ever touches the password, never the UID, group, home or shell.
Warning
Do not re-enable a locked account just because a login test failed. Check the shell, PAM rules, account expiry, directory ownership and the authenticating service first. A batch file with a readable password is a credential exposure that deleting the file afterwards cannot undo.
8. Undo a Mistaken Run Carefully
There is no rollback switch for newusers. For an account created by mistake, stop dependent services first, preserve evidence if you need to, and follow your organisation's account-removal process rather than hand-editing /etc/passwd or /etc/shadow while an account-management tool is running.
Removing an account does not make its files safe to delete, and it can make ownership harder to interpret later. Find files owned by the old numeric UID, decide whether they actually belong to the account, then remove or reassign them. For an account whose UID or home was changed by mistake, restore from backup or reverse the specific change deliberately, newusers never moves old home contents for you.
Done means
- Command checked. The installed shadow-utils version and option syntax were confirmed.
- Batch file secured. It was private, reviewed, and free of ordinary plaintext passwords.
- Paths verified. Parent directories and shells existed before the run.
- Run confirmed. The command returned success and each account was checked with
getentandid. - Homes checked. Ownership and permissions were verified, including any failed home creation.
- Recovery planned. Password delivery, removal and recovery all have a separate documented path.