How can I change the value of, let's say, PasswordAuthentication in /etc/ssh/sshd_config in commands?

As well, remove a # in front of the "key" I wish to value. These don't all have to be in one command. I setup quite a few servers, and remembering where everything is gets exhausting, so I want to get a series of commands I can copy paste and it does the work for me for future reference.

Sample values:

PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
UsePAM no
UseDNS no

Regular expressions and sed can help with things like this.

sed -re 's/^(PasswordAuthentication)([[:space:]]+)no/\1\2yes/' -i.`date -I` /etc/ssh/sshd_config

On my Debian system, this will toggle PasswordAuthentication no to PasswordAuthentication yes, regardless of the number of spaces between key and value.

It will replace the option in the file (in-place editing) while creating a backup of the original file, with a suffix named by the date (sshd_config.2014-05-28).

Switch places for yes and no to toggle the other way.

The expression for removing a leading # is something like this:

 sed -re 's/^(\#)(PasswordAuthentication)([[:space:]]+)(.*)/\2\3\4/' 

-and for inserting a leading #-sign:

 sed -re 's/^(PasswordAuthentication)([[:space:]]+)(.*)/#\1\2\3/' 

To toggle a line with an optional #-sign in front (Thanks Barlop):

sed -re 's/^(\#?)(PasswordAuthentication)([[:space:]]+)no/\2\3yes/' 

In all these expressions you can change PasswordAuthentication to any other option you want to change - probably even make it a key in a shell script, and make a "sshd option toggle tool".

Sed and regex is all fun and games, but I'm sure Valentin is right about configuration management is the way to go if you have lots of systems. Personally I just use etckeeper/bazaar on a couple of systems that very rarely change - it's not configuration management, but it gives me versioning, so I can get back a working config after I screwed up with regex and sed -i. :)

  • Can you modify your regex to include optional # sign when searching, but not in the replacement? I want to remove the # sign before the PasswordAuthentication, just incase it exists. – Brian Graham May 27 '14 at 22:46
  • Hm. It's easy to search for an optional character at the start of a line 's/^(\#?)/foo/' but it's another thing to conditionally leave it out. I would have to study the manuals of sed and regex(7), which is beyond the scope of this. :) But you can combine the two expressions here - first remove the comment-sign for KEY, then toggle KEY to yes or no. – Kenned May 27 '14 at 23:03
  • @Kenned You can by, in the search, capturing the part you want and the part you don't want, and in the replace, just including the part you want. – barlop May 29 '14 at 1:59
  • In case one needs to toggle yes/no setting, one can do so by sed '/^PasswordAuthentication /{s/yes/no/;t;s/no/yes/}' -i /etc/ssh/sshd_config and use it as sed '/^PasswordAuthentication /{s/yes/no/;t;s/no/yes/}' -i /etc/ssh/sshd_config && grep '^PasswordAuthentication ' /etc/ssh/sshd_config && /etc/init.d/ssh reload for example. – PF4Public May 5 '16 at 18:55

There is a number of options to choose from:

  • Puppet, Cfengine, Chef or any other configuration management tool
  • Augeas (augtool -> print /files/etc/ssh/sshd_config -> then use "set")
  • sed -i
  • and many more

After trying to guess where you want to go to, you probably want to consider using configuration management anyway.

  • Can you give me an example using sed? – Brian Graham May 27 '14 at 22:22
  • +1 for giving 3 possible solutions. And, @BrianGraham err brian it's really not hard to find out how to do a search and replace with sed. sed -i 's/a/b/' a.a (replaces 'a' with 'b' in file 'a.a'. More complex with a regex but then your question is how to do the regex, rather than sed or ssh – barlop May 27 '14 at 23:09

Augeas with its command line tool - augtool - can configure /etc/ssh/sshd_config. For example:

augtool --autosave 'set /files/etc/ssh/sshd_config/PasswordAuthentication yes'

To set all the values use:

augtool << EOF
set /files/etc/ssh/sshd_config/PermitRootLogin no
set /files/etc/ssh/sshd_config/ChallengeResponseAuthentication no
set /files/etc/ssh/sshd_config/PasswordAuthentication no
set /files/etc/ssh/sshd_config/UsePAM ${SSHD_UsePAM}
set /files/etc/ssh/sshd_config/UseDNS ${SSHD_UseDNS}
  • Just a note: that will not work if there's Match blocks in the file, as global parameters will need to be inserted before the first Match block. – raphink Jul 12 '14 at 16:51
  • @ℝaphink, doesn't this apply to all other answers as well? Could you also pastebin a configuration file like that? – Cristian Ciupitu Jul 12 '14 at 17:07
  • That is true. I'll post an answer using Puppet + augeasproviders for that. – raphink Jul 14 '14 at 16:28

sshd_config cannot be edited safely without being parsed entirely, because it can contain Match blocks.

Augeas is a good option to achieve that, but it's not very easy to manage inserting options in the right place when there are Match blocks already. One option is to use Puppet with the sshd_config Augeas-based provider:

sshd_config { "PermitRootLogin":
  ensure => present,
  value  => "yes",

This option gives you the advantage of using a strict parser (Augeas with the Sshd.lns lens) and an abstraction level (Puppet resource) which manages the complexity of setting parameters outside of Match blocks, but also inside of them:

sshd_config { "X11Forwarding":
  ensure    => present,
  condition => "Host foo User root",
  value     => "yes",
  • Could you please test if you can set the global PasswordAuthentication to no in this sshd_config? – Cristian Ciupitu Jul 14 '14 at 20:33
  • 1
    Yes I can confirm, just did it. – raphink Jul 17 '14 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.