I tried to create a user with password via ssh (with root permission) like this:

ssh [email protected] useradd -p $(openssl passwd -1 1234) newuser

By doing so, I could successfully create an account named newuser, but I couldn't login with the expected password (which is 1234)

It makes no difference if I add double quotes:

ssh [email protected] "useradd -p $(openssl passwd -1 1234) newuser"

And then I was wondering if I can generate hashed password and save it as a variable locally, but still with no luck.

password=$(openssl passwd -1 1234)
ssh [email protected] "useradd -p $password newuser"

Is there something that I miss? Thanks in advance!

  • Passing passwords on the command-line is a bad idea because other users may see the command-line arguments. See heemayl's answer for that. Beyond that, this sounds like an XY Problem. What are you actually trying to achieve? What's the point of an account password that nobody knowns (or is supposed to know)? If the point is to create an account that doesn't accept log-ins via password just set no password at all which will leave password-based log-in disabled as Ubuntu's default policy. Apr 27, 2017 at 16:56

2 Answers 2


This is a classic quoting issue.

Problem: Without any quoting or double quoting the command substitution ($()) and variable expansion (the $s in the hashed password returned by openssl are being treated as variable indicator) are being done in the local environment, not on the remote shell.

Solution: use single quotes around the useradd command used with ssh on the local shell to prevent the command substitution and variable expansion on local environment, let the expansions take place on the remote non-login, non-interactive shell:

ssh [email protected] 'useradd -p "$(openssl passwd -1 1234)" newuser'

Note the quotings.

Security issues:

  • SSH root login should be disabled, if you must have it enabled only key-based authentication should be allowed

  • MD5 is already broken, and without a salt you are subjected to simple Rainbow table attack (does not even need brute forcing/dictionary attack); openssl passwd does generate a random salt though. Anyway, you should really consider using SHA-2 with salt-ing

  • Passwords passed as arguments to commands might be visible to other processes in the (remote) system; this depends on how your procfs is mounted (look at hidepid), and if the command is rewriting itself (it this case presumably it does not)

  • 1
    Works like a charm, and thank you for the additional information!
    – amigcamel
    Mar 30, 2017 at 6:43
  • 1
    the md5crypt password hash does have a salt...
    – ilkkachu
    Mar 30, 2017 at 13:00
  • @ilkkachu MD5 is not a secure hash. If you're interested, run a search on Information Security. Really you should use a compounded algorithm or cryptographic library, but SHA-2 is significantly better than MD5.
    – wizzwizz4
    Mar 30, 2017 at 18:50
  • 1
    @wizzwizz4 yes, that's well known, doesn't change the fact that the information in this answer is incorrect. :)
    – hobbs
    Mar 30, 2017 at 19:04
  • 2
    @wizzwizz4, the password hash (md5crypt) supported by crypt(3) in Linux and marked with the $1$ identifier is not the same as the plain MD5 hash algorithm, in the same way as the $5$ and $6$ password hashes aren't plain SHA-256 and SHA-512 either. The MD5-based method has a fixed number of iterations, which is the biggest issue with it.
    – ilkkachu
    Mar 30, 2017 at 19:05

As @heemayl noted, the MD5 password hash algorithm is aged, and current systems the newer SHA-2 based password hashes, that have a customisable work factor. But the OpenSSL command line tool doesn't seem to support those.

The chpasswd utility, however, will allow you to change the password of a user according to the system settings.

This should allow you to create the new user and change their password on the remote end.

echo "newuser:newpass" | ssh [email protected] 'useradd newuser; chpasswd' 

chpasswd takes the username and password from stdin, not the command line. This is actually an advantage since command line arguments are visible for all other processes on the system, so if run openssl passwd on the remote, the password would be momentarily visible to all processes on the system.

I'm not sure if there is a ready-made command line utility for generating password hashes known by the system crypt(3) function. Perl has the crypt function builtin, but a proper salt would still need to be generated.

Not the answer you're looking for? Browse other questions tagged .