SSH: How to change value in config file in one command

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. :)


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.


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:

SSHD_UsePAM=no
SSHD_UseDNS=no
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}
save
EOF

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",
}