How to Create a Linux User with Plaintext Password in a Bash Script Without Using crypt


2 views

When automating user creation in Linux systems, many administrators encounter this common frustration: the useradd command's -p option expects an already-encrypted password rather than plaintext. Running:

useradd -d /home/dummy -g idiots -m -p 12345689 dummy

creates the user but makes authentication impossible since 12345689 gets treated as literal encrypted password data.

Method 1: Using chpasswd

The most reliable approach combines useradd with chpasswd:

#!/bin/bash
USERNAME="dummy"
PASSWORD="12345689"
useradd -d /home/$USERNAME -g idiots -m $USERNAME
echo "$USERNAME:$PASSWORD" | chpasswd

Method 2: Leveraging openssl for Encryption

When you need the encryption step in your script:

#!/bin/bash
USERNAME="dummy"
PASSWORD="12345689"
ENCRYPTED=$(openssl passwd -1 "$PASSWORD")
useradd -d /home/$USERNAME -g idiots -m -p "$ENCRYPTED" $USERNAME

Method 3: Using expect for Interactive Tools

For systems requiring passwd interaction:

#!/bin/bash
USERNAME="dummy"
PASSWORD="12345689"
useradd -d /home/$USERNAME -g idiots -m $USERNAME
expect << EOF
spawn passwd $USERNAME
expect "New password:"
send "$PASSWORD\r"
expect "Retype new password:"
send "$PASSWORD\r"
expect eof
EOF

While these methods solve the technical problem, consider:

  • Never store plaintext passwords in version control
  • Use environment variables or secured credential stores
  • Consider SSH key authentication instead for automation
  • For production systems, use proper secrets management tools

For service accounts that shouldn't have password login:

useradd -r -s /usr/sbin/nologin -M service_account

This creates an account without a password or home directory, suitable for daemon processes.


When running useradd with the -p flag, the command expects an already-encrypted password string (typically from crypt or similar hashing functions). This creates a chicken-and-egg problem for automation scripts where you need to:

  • Create users programmatically
  • Set initial passwords without human intervention
  • Maintain script simplicity without external dependencies

The most robust approach uses chpasswd which accepts plaintext passwords in a pipeline:

#!/bin/bash
# Create user with temporary disabled password
useradd -d /home/dummy -g idiots -m -s /bin/bash dummy

# Set password using chpasswd
echo "dummy:12345689" | chpasswd

Why this works better:

  • No need to pre-compute password hashes
  • Handles password complexity rules automatically
  • Works across different Linux distributions

For systems where chpasswd isn't available, you can generate the encrypted password on-the-fly:

#!/bin/bash
# Generate encrypted password
ENCRYPTED_PW=$(openssl passwd -6 "12345689")

# Create user with pre-hashed password
useradd -d /home/dummy -g idiots -m -p "$ENCRYPTED_PW" dummy

When implementing this in production scripts:

  • Never store plaintext passwords in version control
  • Consider using SSH keys instead of passwords when possible
  • Set passwords to expire on first login (passwd -e dummy)
  • For Docker containers, use environment variables passed at runtime

Here's a robust implementation with error handling:

#!/bin/bash
USERNAME="dummy"
PASSWORD="ComplexPass123!"
GROUP="idiots"

# Check if user exists first
if id "$USERNAME" &>/dev/null; then
    echo "User $USERNAME already exists" >&2
    exit 1
fi

# Create user
if ! useradd -m -d "/home/$USERNAME" -g "$GROUP" -s /bin/bash "$USERNAME"; then
    echo "Failed to create user $USERNAME" >&2
    exit 1
fi

# Set password
if ! echo "$USERNAME:$PASSWORD" | chpasswd; then
    echo "Failed to set password for $USERNAME" >&2
    # Rollback user creation
    userdel -r "$USERNAME"
    exit 1
fi

echo "Successfully created user $USERNAME"