Canonical Voices

Posts tagged with 'sysadmin'

Matt Fischer

Last year I worked on a project where I was playing around with system-wide default settings and locks and I thought I’d share a post based on some of my notes. Most all of what I will mention here is covered in depth by the dconf SysAdmin guide, so if you plan on using this, please read that guide as well. UPDATE: Gnome has moved all the dconf stuff into the Gnome SysAdmin guide, it’s a bit more scattered now, but there.

For most everyone, you have just one dconf database per user. It is a binary blob and it’s stored in ~/.config/dconf/user. Anytime you change a setting, this file gets updated. For system administrators who may want to set a company-wide default value, a new dconf database must be created.

Create a Profile

The first step in setting up other databases is to create a dconf profile file. By default you don’t need one since the system uses the default database, user.db, but to setup other databases you will. So create a file called /etc/dconf/profile/user and add the list of databases that you want. Note that this list is a hierarchy and that the user database should always be on top.

For this example, I will create a company database and a division database. The hierarchy implies that we will have company-wide settings, perhaps a wallpaper, settings on top that are specific to the division, perhaps the IP of a proxy server that’s geographically specific, and each user will have customized settings on top of that.

To create a profile, we’ll do the following:

mkdir -p /etc/dconf/profile

and edit /etc/dconf/profile/user, then add:



(Note: I am doing this on a relatively clean precise install using a user that has not changed their wallpaper setting, that is important later)

Once you have created the profile hierarchy, you need to create keyfiles that set the values for each database. For this example, we will just set specific wallpaper files for each hierarchy. This is done with key files:

mkdir -p /etc/dconf/db/division.d/

and edit /etc/dconf/db/division.d/division.key, add the following:


Next we’ll create the company key file:

sudo mkdir -p /etc/dconf/db/company.d/

and edit /etc/dconf/db/company.d/company.key, add the following:


Finally, you need to run sudo dconf update so that dconf sees these changes.

After running dconf update, you will see two changes. The first and most obvious change is that the background is now a bunch of Flocking birds, not the Precise default. The second change is that you will see two new binary dconf database files in /etc/dconf/db, one called company and one called division. If you don’t see these changes then you did something wrong, go back and check the steps.


Since I have no default set the division’s default takes precedence

The current user and any new users will inherit the Division default wallpaper, Flocking. However, the user still may change the wallpaper to anything they want, and if they change it, that change will be set in the user database, which takes precedence. So this method gives us a soft-default, a default until otherwise modified. If you are trying this test on a user who has already modified the wallpaper, you will notice that it didn’t change due to this precedence.

If we want to force all users, new and existing, to get a specific wallpaper, we need to use a lock.


For this example, let’s assume that the IS department for our division really really likes the Flocking picture and doesn’t want anyone to change it. In order to force this, we need to set a lock. A lock is simple to make, it just specifies the name of the key that is locked. A locked key takes precedence over all other set keys.

Before doing this, I will use the wallpaper picker and select a new wallpaper, this will take precedence, until the lock is created. I picked Bloom for my test.

I like flowers more than birds.

I like flowers more than birds.

Now it’s time to make the lock, because the IS department really doesn’t like flowers, so we create the lock as follows.

sudo mkdir -p /etc/dconf/db/division.d/locks/

and then edit /etc/dconf/db/division.d/locks/division.lock (note file name doesn’t really matter) and add the following line:


After saving the file, run sudo dconf update. Once doing so, I’m again looking at birds, even though I modified it in my user database to point to Bloom.

Lock file forces me to use the Division settings

Lock file forces me to use the Division settings

One interesting thing to note, any changes the user is making are still being set in their dconf user db, but the lock is overriding what is being seen from outside dconf. So if I change the wallpaper to London Eye in the wallpaper picker and then remove the lock by simply doing sudo rm division.lock && sudo dconf update, I immediately get the London Eye. So it’s important to keep this in mind, the user db is being written into, but the lock is in effect masking the user db value when the setting is read back.

London Eye wallpaper is shown after I remove the lock

London Eye wallpaper is shown after I remove the lock

Lock Hierarchy

Lock hierarchy is interesting, in that the lowermost lock takes precedence. What this means is that if we lock both the company and division wallpapers, we will see the company one. In the example below I set locks on the wallpaper key for both databases, and I end up seeing Murales, the company default.

Company setting takes precedence

Company setting takes precedence with both locked


Locks Without Keys

It is also possible to set a lock on a hierarchy without a corresponding default key. In this instance the system default is used and the user is unable to change the setting. For this example, I set a company lock but removed the company key. The resulting wallpaper is the system default.

System default wallpaper for Precise is seen

System default wallpaper for Precise is seen

What Value is Seen – A Quiz

If you’d like to test your knowledge of what key will take precedence when read from dconf, follow the quiz below, answers are at the bottom. For each scenario, see if you can figure out what wallpaper the user will see, assume the same database hierarchy as used in the example.

  1. User Wallpaper: unset, Division Wallpaper: Flock, Company Wallpaper: Murales
  2. User Wallpaper: London Eye, Division Wallpaper: Flock, Company Wallpaper: Murales
  3. User Wallpaper: London Eye, Division Wallpaper: Flock, Company Wallpaper: Murales, Lock file for Company Wallpaper setting
  4. User Wallpaper: London Eye, Division Wallpaper: Flock, Company Wallpaper: Murales, Lock file for Division and Company Wallpaper setting
  5. User Wallpaper: London Eye, Division Wallpaper: Flock, Company Wallpaper: unset, Lock file for Division and Company Wallpaper setting

Answers: Flock, London Eye, Murales, Murales, Default for Precise


Some notes about testing this if you are trying it:

    • Creating new users and logging in as them is a good way to see what settings are shown, the wallpaper is a great visual test as it’s easy to verify.
    • Do not do this on your development box. I screwed up my settings right before I was going to give a demo. I’d recommend a VM. If you do screw something up, check .xsession-errors, that’s where my problem was apparent.


If you’re a system administrator or you really like pictures of birds, dconf keyfiles and locks are the correct mechanism to make settings that are defaults, soft or hard. Hopefully this has been illustrative on how they work. I’d recommend playing with them in a VM and once you understand the hierarchies and locking, they should be pretty easy to use.

Read more
Matt Fischer

EDIT: As several people have pointed out, there is a script to already to this, pull-lp-source. Perfect! I’ve asked numerous people over the last year about whether there was a tool that could do this and nobody mentioned this one (even asked on AskUbuntu last week). So out of all this I end up with a link to a great new tool and got to write some python yesterday. pull-lp-source looks like it will meet all my needs.

During my work on bug triage and trying to become MOTU, I’ve found myself wanting to be able to pull source packages for a specified release, for example, download source for lxc on precise, even if I’m using raring. Although you can do this if you setup apt with all the releases and then use pinning, or doing a setup like this, I wanted an easier way. So I decided to glue together rmadison and dpkg-source and create a tool called “get_source”. This is how it works. -r <release> -p <package>

Pulling the source for bc on oneiric: -r oneiric -p bc

Grabbing lxc on precise: -r precise -p lxc

Seems pretty simple and it is!

The tool relies on outside helpers to do the hard work, namely rmadison and dpkg-source, so you’ll need those installed to use it. Please give it a try and send in feedback and fixes. If you’re a developer you’ll note that I even have unit-ish tests, please add more if you make some fixes for corner-cases.

bzr branch lp:~mfisch/+junk/get_source

How It Works

  1. Run rmadison and build a list of packages + versions per release
  2. Find the release we care about. We now know the package name, version, and release name.
  3. Using some hueristics, download the dsc file.
  4. Read and parse the dsc file to find the filenames for the orig file and diff and/or debdiff
  5. Download the orig and diff/debdiff files
  6. Use dpkg-source -x to extract it

Alternatives and Issues

When I started this, I figured it would be simple, but I was mistaken. There is lots of variation on filenames and locations in the archives, for example:

  1. I had originally planned to just go grab http://url/pool/main/<package first letter>/package/package_version.<extension>, but it’s not quite that simple. First, not all packages use standard names, some have a diff.gz, some a debian.tar.gz. Then some packages use xz and some use gz.  Native packages won’t have a diff at all (I think), and right now I know my code won’t support that.
  2. There’s also the question of package directory. alsa-base for example comes from the directory “alsa-driver”. I plan on grabbing this information from apt-cache show, but even that will not solve the issue if I’m on raring and the package was elsewhere in precise. This is also not yet supported in this version.
  3. Packages like angband have a version of 1:3.0.9-1, and the “1:” portion is not included in the filename. The code now supports this.

I found these cases by making this app work for a package and then randomly trying more and more packages to find and hopefully fix new cases. The worry I have is that there are hundreds more corner-cases that I don’t handle. Given all these issues, I’m still releasing this code for other people to test, but perhaps someone has simpler solutions to the problems above? Even better, maybe someone has already written a better tool, which I’ll gladly use!

Read more
Matt Fischer

Over the past week I’ve been playing with DHCP option tags, and using them to send data to DHCP client systems, and then do something with the data. I didn’t know much about DHCP option tags before doing this, I figure DHCP just gave you an IP address and maybe a nameserver. In reality, DHCP can be customized to send a couple hundred different settings, including where the IRC or SMTP servers are, VOIP settings, and lots more. What makes it really powerful is that you can use the unassigned options to create your own settings, and then do actions on the client when they get set. In this simple example, I’m going to send and set a new “message of the day” via dhcp. The message of the day is a (usually) short text message shown when you login via the terminal and is stored in /etc/motd. If you are trying this on a production system, you should back-up your /etc/motd first.

Server Setup

On the server, after installing dhcpd, edit /etc/dhcp/dhcpd.conf, create a valid subnet and then in the global space, add your new option. Since options 151-174 are unassigned, I will use option 151. You could also use a ‘site-local’ option between 224-254.

Add the following outside any subnet sections:
option motd code 151 = text;
option motd "Happy Easter from your DHCP server team";

Client Setup

On the client, manually run dhclient -d and make sure you’re getting a valid IP from the server. Once you know that is working, edit /etc/dhcp/dhclient.conf and add two parts, first you need to name the new option and second you need to request it:

Add this to the top, you may see another option code there, add it near that:
option motd code 151 = text;

Then look for the big request block, add your new option into that block:
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, domain-search, host-name,
netbios-name-servers, netbios-scope, interface-mtu,
rfc3442-classless-static-routes, ntp-servers,
dhcp6.domain-search, dhcp6.fqdn,, dhcp6.sntp-servers,

Now, let’s see if we get it. Edit /etc/dhcp/dhclient-exit-hooks.d/debug and switch RUN=”no” to RUN=”yes”. Then edit the large block of variables and add your new option, motd.

Re-run dhclient -d and then check /tmp/dhclient-script.debug, do you see your motd option? If so, your setup is correct. It should look liks this:

new_motd='Happy Easter from your DHCP server team'

Doing Something When You Get an Option

dhclient defines exit-hooks, one of which is the debug script you edited above. You can create your own shell script in /etc/dhcp/dhclient-exit-hooks.d/ and follow some of the other examples in there. DHCP options come in as variables, so in this case, the script would use ${new_motd}. From what I can tell everything in here has to be a shell script, a python script I tried did not work. Here is my script to set motd:

if [ -n "${new_motd+x} ]; then
echo ${new_motd} > /etc/motd

Re-run dhclient -d and you should see that the script has run and your message of the day is now a Happy Easter message.

What About NetworkManager?

If you are running NetworkManager on your system, and you probably are, then NetworkManager starts dhclient during boot and subverts the running of dhclient’s exit hook scripts. You can use NetworkManager’s own version of “exit hooks” which live in /etc/NetworkManager/dispatcher.d to respond to DHCP events. Scripts in that directory can be written directly in python. The scripts run from NetworkManager’s dispatcher use slightly different environment variables for DHCP options, they’re in all caps and are pre-pended with DHCP4_ (and presumably DHCP6_ if you’re serving IPv6 addresses).

if [ -n "${DHCP4_MOTD+x} ]; then
echo ${DHCP4_MOTD} > /etc/motd

See the man NetworkManager(8) for more details on actions that your scripts can respond to.

Options as Expressions

There are more advanced things you can do. For example, you set a setting on the server based on an expression, for example:

if option dhcp-user-class = "fortcollins-office" {
option smtp-server "";

You then configure the client to send up a dhcp-user-class of “fortcollins-office” for all your PCs in Fort Collins.

Using my example, you could change the holiday in the message based on the date that the lease was given out.

See man dhcp-eval(5) for more info on expressions.

Encapsulated Options

Another thing you can do is vendor encapsulated options. Vendor encapsulated options take a bunch of vendor specific info and encapsulate it into one option. This means that you can pack a bunch of data into one option. I am not sure if all dhcpd servers support this construct however.

Testing This
If you want to try DHCP options without messing up your network, the quickest way is to create two virtual machines, a client and a server, and give them each two NICs. One NIC on each machine should be on a private network, and the server should have a static IP on this private network NIC and serve DHCP on that interface. The other non-private NIC is used by you to copy files to and from your virtual machines, but is otherwise not specifically required. I did this setup using Ubuntu 12.04 precise and qemu and it works great.

Customized DHCP options let you transmit data to your DHCP clients and then write scripts to act on that data. Although my example is contrived, you could use DHCP to transmit useful system settings and then configure them via script.


Read more