Modifying cupsd.conf with augeas

By thomas, 12 July, 2016

Had a problem where I wanted to modify /etc/cups/cupsd.conf but wasn't sure who else might touch the file. I opted to use Augeas and quickly learned it wasn't as easy as I thought it might be...

The cupsd.conf configuration file uses a syntax similar to Apache configuration files, it uses the same Augeas lens (Httpd.lns). Changing directives is a bit of an issue, but I found the solution by reading the source for the Httpd.lns (/usr/share/augeas/lenses/dist/httpd.aug or /opt/puppetlabs/puppet/share/augeas/lenses/dist/httpd.aug)

What I wanted to do was turn off the port 631 listener, the line that starts with Listen localhost:631, in augtool this looks like the following:
[code type="shell"]
augtool> ls /files/etc/cups/cupsd.conf/
directive[1]/ = MaxLogSize
#comment[1] = Configuration file for the CUPS scheduler. See "man cupsd.conf" for a
#comment[2] = complete description of this file.
#comment[3] = Log general information in error_log - change "warn" to "debug"
#comment[4] = for troubleshooting...
directive[2]/ = LogLevel
directive[3] = PageLogFormat
#comment[5] = Only listen for connections from the local machine.
directive[4]/ = Listen
directive[5]/ = Listen
[/code]
So, this is where it gets a little weird, I just want to make sure that anything with a Listen *:631 matches, so I use regex.

augtool> get /files/etc/cups/cupsd.conf/directive[self::directive="Listen"]/arg[self::arg=~ regexp(".*:631")]
/files/etc/cups/cupsd.conf/directive[self::directive="Listen"]/arg[self::arg=~ regexp(".*:631")] = localhost:631

To remove that line, I just need to use rm:

augtool> rm /files/etc/cups/cupsd.conf/directive[self::directive="Listen"]/arg[self::arg=~ regexp(".*:631")]
rm : /files/etc/cups/cupsd.conf/directive[self::directive="Listen"]/arg[self::arg=~ regexp(".*:631")] 1
augtool> save
Saved 1 file(s)

Now when I view the cupsd.conf file I see the localhost:631 is gone but I still have a line with "Listen" on it.

# Only listen for connections from the local machine.
Listen
Listen /var/run/cups/cups.sock

That might work but it looks bad to me, so I opted to change my augeas code to remove all Listen lines and then add back the UNIX socket instead.

augtool> rm /files/etc/cups/cupsd.conf/directive[self::directive="Listen"]
rm : /files/etc/cups/cupsd.conf/directive[self::directive="Listen"] 3
augtool> set /files/etc/cups/cupsd.conf/directive[self::directive="Listen"] Listen
augtool> set /files/etc/cups/cupsd.conf/directive[self::directive="Listen"]/arg /var/run/cups/cups.sock
augtool> save
Saved 1 file(s)

Now when I look in the file, there's only one Listen line.

# grep Listen /etc/cups/cupsd.conf
Listen /var/run/cups/cups.sock

Going back and doing the same for Browsing and BrowseLocalProtocols, I ended up with the following Augeas resource for Puppet.

augeas { 'cups listen':
incl => '/etc/cups/cupsd.conf',
context => '/files/etc/cups/cupsd.conf',
lens => 'Cups.lns',
changes => [
# Do not listen to anything but the unix socket
"rm directive[self::directive='Listen']",
"set directive[self::directive='Listen'] Listen",
"set directive[self::directive='Listen']/arg /var/run/cups/cups.sock",
# Don't browse local printers
"set directive[self::directive='Browsing']/arg Off",
"rm directive[self::directive='BrowseLocalProtocols']",
"set directive[self::directive='BrowseLocalProtocols'] BrowseLocalProtocols",
"set directive[self::directive='BrowseLocalProtocols']/arg none",
],
require => Package['cups'],
notify => Service['cups'],
}