diff --git a/build b/build
index fb01c565..d6c9a172 100755
--- a/build
+++ b/build
@@ -27,7 +27,7 @@
 #set -e
 
 basedir=${0%/*}
-version=$(git describe)
+version=$(cd "$basedir" && git describe)
 
 # Manpage and HTML
 A2XM="a2x -f manpage --no-xmllint -a encoding=UTF-8"
@@ -331,14 +331,17 @@ eof
         done
     ;;
         
-    web)
-        set -e
+    web-doc)
         rsync -av "${basedir}/docs/web/" "${WEBTOPDIR}"
 
         cd "${WEBDIR}" && git add "${WEBBASE}"
         cd "${WEBDIR}" && git commit -m "cdist update" "${WEBBASE}" "${WEBPAGE}"
         cd "${WEBDIR}" && make pub
+    ;;
 
+    web)
+        set -e
+        $0 web-doc
         # Fix ikiwiki, which does not like symlinks for pseudo security
         ssh tee.schottelius.org \
           "cd /home/services/www/nico/www.nico.schottelius.org/www/software/cdist/man &&
diff --git a/cdist/conf/type/__jail/gencode-remote b/cdist/conf/type/__jail/gencode-remote
index 4aff6509..1f326bf1 100755
--- a/cdist/conf/type/__jail/gencode-remote
+++ b/cdist/conf/type/__jail/gencode-remote
@@ -34,15 +34,8 @@ fi
 
 state="$(cat "$__object/parameter/state")"
 
-if [ -f "$__object/parameter/started" ]; then
-   started="$(cat "$__object/parameter/started")"
-else
-   if [ ! "$state" = "present" ]; then
-      started="false"
-   else
-      started="true"
-   fi
-fi
+started="true"
+[ -f "$__object/parameter/stopped" ] && started="false"
 
 if [ -f "$__object/parameter/ip" ]; then
    ip="$(cat "$__object/parameter/ip")"
@@ -66,8 +59,8 @@ if [ -f "$__object/parameter/interface" ]; then
    interface="$(cat "$__object/parameter/interface")"
 fi
 
-if [ -f "$__object/parameter/devfs-enable" ]; then
-   devfsenable="$(cat "$__object/parameter/devfs-enable")"
+if [ -f "$__object/parameter/devfs-disable" ]; then
+   devfsenable="false"
 else
    devfsenable="true"
 fi
@@ -82,12 +75,12 @@ fi
 #     is pointless. Treat this as an error.
 if [ -n "$devfsruleset" -a "$devfsenable" = "false" ]; then
    exec >&2
-   echo "Can't have --devfs-ruleset defined without --devfs-enable true."
+   echo "Can't have --devfs-ruleset defined with --devfs-disable"
    exit 1
 fi
 
 if [ -f "$__object/parameter/onboot" ]; then
-   onboot="$(cat "$__object/parameter/onboot")"
+   onboot="true"
 fi
 
 if [ -f "$__object/parameter/jaildir" ]; then
@@ -357,7 +350,3 @@ else   # The jail does not currently exist
       exit 0
    fi
 fi
-
-# Debug
-#set +x
-
diff --git a/cdist/conf/type/__jail/man.text b/cdist/conf/type/__jail/man.text
index 8682effe..b439e0f5 100644
--- a/cdist/conf/type/__jail/man.text
+++ b/cdist/conf/type/__jail/man.text
@@ -27,9 +27,6 @@ OPTIONAL PARAMETERS
 name::
    The name of the jail. Default is to use the object_id as the jail name.
 
-started::
-   Either "true" or "false." Defaults to true.
-
 ip::
    The ifconfig style IP/netmask combination to use for the jail guest. If
    the state parameter is "present," this parameter is required.
@@ -41,23 +38,26 @@ interface::
    The name of the physical interface on the jail server to bind the jail to.
    Defaults to the first interface found in the output of ifconfig -l.
 
-devfs-enable::
-   Whether to allow devfs mounting within the jail. Must be "true" or "false."
-   Defaults to true.
-
 devfs-ruleset::
    The name of the devfs ruleset to associate with the jail. Defaults to
    "jailrules." This ruleset must be copied to the server via another type.
    To use this option, devfs-enable must be "true."
 
-onboot::
-   Whether to add the jail to rc.conf's jail_list variable. Must be either
-   "true" or "false." Defaults to false.
-
 jaildir::
    The location on the remote server to use for hosting jail filesystems.
    Defaults to /usr/jail.
 
+BOOLEAN PARAMETERS
+------------------
+stopped::
+   Do not start the jail
+
+devfs-disable::
+   Whether to disallow devfs mounting within the jail
+
+onboot::
+   Whether to add the jail to rc.conf's jail_list variable. 
+
 
 CAVEATS
 -------
@@ -77,8 +77,8 @@ __jail www --state present --ip "192.168.1.2" --jailbase /my/jail/base.tgz
 # Remove the jail called www
 __jail www --state absent --jailbase /my/jail/base.tgz
 
-# Ensure that the jail called www is started
-__jail www --state present --started true \
+# The jail www should not be started
+__jail www --state present --stopped \
    --ip "192.168.1.2 netmask 255.255.255.0" \
    --jailbase /my/jail/base.tgz
 
@@ -88,10 +88,10 @@ __jail thisjail --state present --name www \
    --jailbase /my/jail/base.tgz
 
 # Go nuts
-__jail lotsofoptions --state present --name testjail --started true \
+__jail lotsofoptions --state present --name testjail \
    --ip "192.168.1.100 netmask 255.255.255.0" \
    --hostname "testjail.example.com" --interface "em0" \
-   --onboot yes --jailbase /my/jail/base.tgz --jaildir /jails
+   --onboot --jailbase /my/jail/base.tgz --jaildir /jails
 --------------------------------------------------------------------------------
 
 
diff --git a/cdist/conf/type/__jail/parameter/boolean b/cdist/conf/type/__jail/parameter/boolean
new file mode 100644
index 00000000..39144f6f
--- /dev/null
+++ b/cdist/conf/type/__jail/parameter/boolean
@@ -0,0 +1,3 @@
+onboot
+stopped
+devfs-disable
diff --git a/cdist/conf/type/__jail/parameter/optional b/cdist/conf/type/__jail/parameter/optional
index 1b5f0810..08ecd469 100644
--- a/cdist/conf/type/__jail/parameter/optional
+++ b/cdist/conf/type/__jail/parameter/optional
@@ -1,10 +1,7 @@
 name
-started
 ip
 hostname
 interface
-devfs-enable
 devfs-ruleset
-onboot
 jaildir
 jailbase
diff --git a/cdist/conf/type/__qemu_img/gencode-remote b/cdist/conf/type/__qemu_img/gencode-remote
index e5ff1b4f..2a76cf8f 100644
--- a/cdist/conf/type/__qemu_img/gencode-remote
+++ b/cdist/conf/type/__qemu_img/gencode-remote
@@ -3,7 +3,7 @@
 # not existing and state != absent
 #
 state="present"
-[ -f "$__object/parameter/state" ] state="$(cat "$__object/parameter/state")"
+[ -f "$__object/parameter/state" ] && state="$(cat "$__object/parameter/state")"
 [ "$state" = "absent" ] && exit 0
 
 exists="$(cat "$__object/explorer/exists")"
diff --git a/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group b/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group
deleted file mode 100644
index c79f8d9f..00000000
--- a/cdist/conf/type/__ssh_authorized_key/explorer/dstuser_group
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/sh
-
-# Get option dstuser if defined
-if [ -f "$__object/parameter/dstuser" ]; then
-   dstuser=`cat "$__object/parameter/dstuser"`
-else
-   dstuser="root"
-fi
-
-if id $dstuser >/dev/null 2>&1 ; then
-    id -ng $dstuser
-else
-   echo "$__object_id: Destination user $dstuser does not exist" >&2
-   exit 1
-fi
diff --git a/cdist/conf/type/__ssh_authorized_key/man.text b/cdist/conf/type/__ssh_authorized_key/man.text
deleted file mode 100644
index b372b354..00000000
--- a/cdist/conf/type/__ssh_authorized_key/man.text
+++ /dev/null
@@ -1,46 +0,0 @@
-cdist-type__ssh_authorized_key(7)
-=================================
-Aurélien Bondis <aurelien.bondis--@--gmail-DOT-com>
-
-
-NAME
-----
-cdist-type__ssh_authorized_key - Sends a user's public key to another user's authorized_keys
-
-
-DESCRIPTION
------------
-This type sends a rsa key. By default uses root's key and sends it to root's authorized_keys
-
-
-REQUIRED PARAMETERS
--------------------
-None.
-
-
-OPTIONAL PARAMETERS
--------------------
-srcuser:: the user to take the rsa public key from
-dstuser:: the user to give the rsa public key to
-
-
-EXAMPLES
---------
-
---------------------------------------------------------------------------------
-#deploy root's public key
-__ssh_authorized_key admin
-#deploy bob's public key to alice's authorized_keys
-__ssh_authorized_key --srcuser bob --dstuser alice
---------------------------------------------------------------------------------
-
-
-SEE ALSO
---------
-- cdist-type(7)
-
-
-COPYING
--------
-Free use of this software is
-granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__ssh_authorized_key/manifest b/cdist/conf/type/__ssh_authorized_key/manifest
deleted file mode 100755
index 86c58740..00000000
--- a/cdist/conf/type/__ssh_authorized_key/manifest
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-#
-# 2011 Aurélien Bondis  aurelien.bondis AT gmail DOT com
-#
-# This file is part of cdist.
-#
-# cdist is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# cdist is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with cdist. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# This type allows to send a public ssh key from a user to the
-# authorized_keys of another
-#
-#require="__package openssh-server --state present"
-# Get option srcuser if defined
-if [ -f "$__object/parameter/srcuser" ]; then
-   srcuser=`cat "$__object/parameter/srcuser"`
-fi
-# Get option dstuser if defined
-if [ -f "$__object/parameter/dstuser" ]; then
-   dstuser=`cat "$__object/parameter/dstuser"`
-else
-   dstuser="root"
-fi
-
-# retrieve destination group
-dstgroup=$(cat "$__object/explorer/dstuser_group")
-
-# if a source user is defined, use it's public key
-if [ "$srcuser" ]; then
-   srcrsa="/home/${srcuser}/.ssh/id_rsa.pub"
-# if no source user is defined we use root's public key
-else
-   srcrsa="/root/.ssh/id_rsa.pub"
-fi
-# if a destination user is defined, insert in it's authorized_keys
-if [ "$dstuser" ]; then
-   sshpath="/home/$dstuser/.ssh"
-# if no destination user is defined we use root's home
-else
-   sshpath="/root/.ssh"
-fi
-rsa=`cat $srcrsa`
-__directory $sshpath \
-    --owner $dstuser \
-    --group $dstgroup \
-    --mode 700
-# the file authorized_keys depends on the .ssh folder
-require="__directory${sshpath}" \
-    __file "$sshpath/authorized_keys" \
-    --mode 640 \
-    --owner $dstuser \
-    --group $dstgroup
-# the line added depends on authorized_keys existence
-require="__file${sshpath}/authorized_keys" __addifnosuchline sshkey --file \
- "$sshpath/authorized_keys" --line "$rsa"
diff --git a/cdist/conf/type/__ssh_authorized_key/parameter/optional b/cdist/conf/type/__ssh_authorized_key/parameter/optional
deleted file mode 100644
index 4903f5be..00000000
--- a/cdist/conf/type/__ssh_authorized_key/parameter/optional
+++ /dev/null
@@ -1,2 +0,0 @@
-srcuser
-dstuser
diff --git a/cdist/conf/type/__ssh_authorized_keys/explorer/entry b/cdist/conf/type/__ssh_authorized_keys/explorer/entry
new file mode 100755
index 00000000..9992d32d
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/explorer/entry
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$("$__type_explorer/passwd" | cut -d':' -f 6)"
+   file="$home/.ssh/authorized_keys"
+fi
+
+# no authorized_keys file, nothing we could do
+[ -f "$file" ] || exit 0
+
+# NOTE: keep variables in sync in manifest/explorer/gencode-*
+prefix="#cdist:$__object_name"
+suffix="#/cdist:$__object_name"
+awk -v prefix="$prefix" -v suffix="$suffix" '{
+   if (index($0,prefix)) {
+      triggered=1
+   }
+   if (triggered) {
+      if (index($0,suffix)) {
+            triggered=0
+      }
+      print
+   }
+}' "$file"
diff --git a/cdist/conf/type/__ssh_authorized_keys/explorer/passwd b/cdist/conf/type/__ssh_authorized_keys/explorer/passwd
new file mode 100755
index 00000000..e6352ee0
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/explorer/passwd
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+
+getent passwd "$owner" || true
diff --git a/cdist/conf/type/__ssh_authorized_keys/gencode-remote b/cdist/conf/type/__ssh_authorized_keys/gencode-remote
new file mode 100755
index 00000000..cc86cc19
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/gencode-remote
@@ -0,0 +1,82 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$(cut -d':' -f 6 "$__object/explorer/passwd")"
+   file="$home/.ssh/authorized_keys"
+fi 
+
+entry="$__object/files/entry"
+if [ ! -s "$__object/explorer/entry" ]; then
+   state_is='absent'
+else
+   state_is=$(diff -q "$entry" "$__object/explorer/entry" >/dev/null \
+      && echo present \
+      || echo changed
+   )
+fi
+
+state_should="$(cat "$__object/parameter/state" 2>/dev/null || echo present)"
+if [ "$state_should" = "$state_is" ]; then
+   # Nothing to do, move along
+   exit 0
+fi
+
+remove_entry() {
+   # NOTE: keep variables in sync in manifest/explorer/gencode-*
+   prefix="#cdist:$__object_name"
+   suffix="#/cdist:$__object_name"
+   cat << DONE
+tmpfile=\$(mktemp)
+awk -v prefix="$prefix" -v suffix="$suffix" '
+{
+   if (index(\$0,prefix)) {
+      triggered=1
+   }
+   if (triggered) {
+      if (index(\$0,suffix)) {
+         triggered=0
+      }
+   } else {
+      print
+   }
+}' "$file" > "\$tmpfile"
+mv -f "\$tmpfile" "$file"
+DONE
+}
+
+case "$state_should" in
+   present)
+      if [ "$state_is" = "changed" ]; then
+         remove_entry
+      fi
+      cat << DONE
+cat >> "$file" << ${__type##*/}_DONE
+$(cat "$entry")
+${__type##*/}_DONE
+DONE
+   ;;
+   absent)
+      remove_entry
+   ;;
+esac
diff --git a/cdist/conf/type/__ssh_authorized_keys/man.text b/cdist/conf/type/__ssh_authorized_keys/man.text
new file mode 100644
index 00000000..7177f26e
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/man.text
@@ -0,0 +1,101 @@
+cdist-type__ssh_authorized_keys(7)
+==================================
+Steven Armstrong <steven-cdist--@--armstrong.cc>
+
+
+NAME
+----
+cdist-type__ssh_authorized_keys - manage ssh authorized_keys files
+
+
+DESCRIPTION
+-----------
+Adds or removes ssh keys from a authorized_keys file.
+
+This type also manages the directory containing the authorized_keys
+file and sets strict ownership and permissions. You can disable this feature
+with the --noparent boolean parameter.
+
+The existence, ownership and permissions of the authorized_keys file itself are
+also managed. This can be disabled with the --nofile boolean parameter. It is
+then left to the user to ensure that the file exists and that ownership and 
+permissions work with ssh.
+
+
+REQUIRED PARAMETERS
+-------------------
+key::
+   the ssh key which shall be added to this authorized_keys file.
+   Must be a string and can be specified multiple times.
+
+
+OPTIONAL PARAMETERS
+-------------------
+owner::
+   the user owning the authorized_keys file, defaults to object_id.
+
+state::
+   if the given keys should be 'present' or 'absent', defaults to 'present'.
+
+file::
+   an alternative destination file, defaults to ~$owner/.ssh/authorized_keys
+
+comment::
+   an optional comment
+
+
+BOOLEAN PARAMETERS
+------------------
+noparent::
+   don't create or change ownership and permissions of the directory containing
+   the authorized_keys file
+
+nofile::
+   don't manage existence, ownership and permissions of the the authorized_keys
+   file
+
+
+EXAMPLES
+--------
+
+--------------------------------------------------------------------------------
+# add your ssh key to remote root's authorized_keys file
+__ssh_authorized_keys root \
+   --key "$(cat ~/.ssh/id_rsa.pub)"
+
+# allow key to login as user-name
+__ssh_authorized_keys user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+
+# same as above, but with explicit owner, two keys and a comment
+__ssh_authorized_keys some-fancy-id \
+   --owner user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..." \
+   --key "ssh-rsa AZXYAAB3NzaC1yc2..." \
+   --comment "allow the members of project foo to login"
+
+# same as above, but authorized_keys file in non standard location
+__ssh_authorized_keys some-fancy-id \
+   --file /etc/ssh/keys/user-name/authorized_keys \
+   --owner user-name \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+
+# same as above, but directory and authorized_keys file is created elswhere
+__ssh_authorized_keys some-fancy-id \
+   --file /etc/ssh/keys/user-name/authorized_keys \
+   --owner user-name \
+   --noparent \
+   --nofile \
+   --key "ssh-rsa AXYZAAB3NzaC1yc2..."
+--------------------------------------------------------------------------------
+
+
+SEE ALSO
+--------
+- cdist-type(7)
+
+
+COPYING
+-------
+Copyright \(C) 2012 Steven Armstrong. Free use of this software is
+granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__ssh_authorized_keys/manifest b/cdist/conf/type/__ssh_authorized_keys/manifest
new file mode 100755
index 00000000..268b1fbe
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/manifest
@@ -0,0 +1,74 @@
+#!/bin/sh
+#
+# 2012 Steven Armstrong (steven-cdist at armstrong.cc)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+owner="$(cat "$__object/parameter/owner" 2>/dev/null || echo "$__object_id")"
+state="$(cat "$__object/parameter/present" 2>/dev/null || echo "present")"
+if [ -f "$__object/parameter/file" ]; then
+   file="$(cat "$__object/parameter/file")"
+else
+   home="$(cut -d':' -f 6 "$__object/explorer/passwd")"
+   if [ -z "$home" ]; then
+      echo "Failed to get home directory from explorer." >&2
+      exit 1
+   fi
+   file="$home/.ssh/authorized_keys"
+fi
+
+if [ ! -f "$__object/parameter/noparent" -o ! -f "$__object/parameter/nofile" ]; then
+   group="$(cut -d':' -f 4 "$__object/explorer/passwd")"
+   if [ -z "$group" ]; then
+      echo "Failed to get owners group from explorer." >&2
+      exit 1
+   fi
+
+   if [ ! -f "$__object/parameter/noparent" ]; then
+      # Ensure that the directory in which the authorized_keys shall be exists and 
+      # has the right permissions.
+      ssh_directory="${file%/*}"
+      __directory "$ssh_directory" --state present --parents \
+         --owner "$owner" --group "$group" --mode 0700
+      export require="__directory/$ssh_directory"
+   fi
+   if [ ! -f "$__object/parameter/nofile" ]; then
+      # Ensure that authorized_keys file exists and has the right permissions.
+      __file "$file" \
+         --owner "$owner" \
+         --group "$group" \
+         --mode 0600 \
+         --state exists
+   fi
+fi
+
+# NOTE: keep variables in sync in manifest/explorer/gencode-*
+prefix="#cdist:$__object_name"
+suffix="#/cdist:$__object_name"
+
+mkdir "$__object/files"
+
+# Generate entry for inclusion in authorized_keys file
+entry="$__object/files/entry"
+echo "$prefix" > "$entry"
+if [ -f "$__object/parameter/comment" ]; then
+   echo "# $(cat "$__object/parameter/comment")" >> "$entry"
+fi
+cat "$__object/parameter/key" >> "$entry"
+# ensure we have a newline after keys
+echo >> "$entry"
+echo "$suffix" >> "$entry"
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/boolean b/cdist/conf/type/__ssh_authorized_keys/parameter/boolean
new file mode 100644
index 00000000..4bb126fe
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/boolean
@@ -0,0 +1,2 @@
+noparent
+nofile
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/optional b/cdist/conf/type/__ssh_authorized_keys/parameter/optional
new file mode 100644
index 00000000..bfbd72ab
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/optional
@@ -0,0 +1,4 @@
+owner
+state
+file
+comment
diff --git a/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple b/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple
new file mode 100644
index 00000000..06bfde49
--- /dev/null
+++ b/cdist/conf/type/__ssh_authorized_keys/parameter/required_multiple
@@ -0,0 +1 @@
+key
diff --git a/cdist/context.py b/cdist/context.py
index 767b17a8..e0391be8 100644
--- a/cdist/context.py
+++ b/cdist/context.py
@@ -38,7 +38,7 @@ class Context(object):
         remote_copy,
         remote_exec,
         initial_manifest=False,
-        add_conf_dirs=[],
+        add_conf_dirs=None,
         exec_path=sys.argv[0],
         debug=False):
 
diff --git a/cdist/core/cdist_object.py b/cdist/core/cdist_object.py
index 7e587bf3..90a21e59 100644
--- a/cdist/core/cdist_object.py
+++ b/cdist/core/cdist_object.py
@@ -186,8 +186,6 @@ class CdistObject(object):
         return os.path.join(self.path, "explorer")
 
     requirements = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'require'))
-    before = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'before'))
-    after = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'after'))
     autorequire = fsproperty.FileListProperty(lambda obj: os.path.join(obj.absolute_path, 'autorequire'))
     parameters = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.base_path, obj.parameter_path))
     explorers = fsproperty.DirectoryDictProperty(lambda obj: os.path.join(obj.base_path, obj.explorer_path))
diff --git a/cdist/core/explorer.py b/cdist/core/explorer.py
index 86ce52ac..d926552a 100644
--- a/cdist/core/explorer.py
+++ b/cdist/core/explorer.py
@@ -153,7 +153,7 @@ class Explorer(object):
                 destination = os.path.join(self.remote.type_path, cdist_type.explorer_path)
                 self.remote.mkdir(destination)
                 self.remote.transfer(source, destination)
-                self.remote.run(["chmod", "0700", "%s" % (destination)])
+                self.remote.run(["chmod", "0700", "%s/*" % (destination)])
                 self._type_explorers_transferred.append(cdist_type.name)
 
     def transfer_object_parameters(self, cdist_object):
diff --git a/cdist/emulator.py b/cdist/emulator.py
index bd3661d3..a9c760cb 100644
--- a/cdist/emulator.py
+++ b/cdist/emulator.py
@@ -23,7 +23,6 @@
 import argparse
 import logging
 import os
-import warnings
 import sys
 
 import cdist
@@ -93,12 +92,8 @@ class Emulator(object):
 
     def commandline(self):
         """Parse command line"""
-        self.meta_parameters = dict.fromkeys(('after', 'before'))
-        meta_parser = argparse.ArgumentParser(add_help=False)
-        for meta_parameter in self.meta_parameters.keys():
-            meta_parser.add_argument('--%s' % meta_parameter, action='append', required=False)
 
-        parser = argparse.ArgumentParser(add_help=False, parents=[meta_parser], argument_default=argparse.SUPPRESS)
+        parser = argparse.ArgumentParser(add_help=False, argument_default=argparse.SUPPRESS)
 
         for parameter in self.cdist_type.required_parameters:
             argument = "--" + parameter
@@ -124,11 +119,6 @@ class Emulator(object):
         self.args = parser.parse_args(self.argv[1:])
         self.log.debug('Args: %s' % self.args)
 
-        # Handle meta parameters
-        for meta_parameter in self.meta_parameters.keys():
-            if meta_parameter in self.args:
-                self.meta_parameters[meta_parameter] = getattr(self.args, meta_parameter)
-                delattr(self.args, meta_parameter)
 
     def setup_object(self):
         # Setup object_id - FIXME: unset / do not setup anymore!
@@ -185,18 +175,10 @@ class Emulator(object):
 
     def record_requirements(self):
         """record requirements"""
-        for key in ('before', 'after'):
-            if key in self.meta_parameters and self.meta_parameters[key]:
-                for value in self.meta_parameters[key]:
-                    self.log.debug("Recording requirement: %s %s %s", self.cdist_object.name, key, value)
-                    dependency_list = getattr(self.cdist_object, key)
-                    # append to the object.after or object.before lists
-                    dependency_list.append(value)
 
         if "require" in self.env:
-            warnings.warn("The 'require' envrionment variable is deprecated. Use the --before and --after meta parameters to define dependencies.", category=PendingDeprecationWarning, stacklevel=2)
-
             requirements = self.env['require']
+            self.log.debug("reqs = " + requirements)
             for requirement in requirements.split(" "):
                 # Ignore empty fields - probably the only field anyway
                 if len(requirement) == 0: continue
@@ -205,10 +187,11 @@ class Emulator(object):
                 cdist_object = self.cdist_object.object_from_name(requirement)
 
                 self.log.debug("Recording requirement: " + requirement)
+
                 # Save the sanitised version, not the user supplied one
                 # (__file//bar => __file/bar)
                 # This ensures pattern matching is done against sanitised list
-                self.cdist_object.after.append(cdist_object.name)
+                self.cdist_object.requirements.append(cdist_object.name)
 
     def record_auto_requirements(self):
         """An object shall automatically depend on all objects that it defined in it's type manifest.
diff --git a/cdist/exec/local.py b/cdist/exec/local.py
index 7ef11458..7f640411 100644
--- a/cdist/exec/local.py
+++ b/cdist/exec/local.py
@@ -23,6 +23,7 @@
 import io
 import os
 import sys
+import re
 import subprocess
 import shutil
 import logging
@@ -37,7 +38,7 @@ class Local(object):
     Directly accessing the local side from python code is a bug.
 
     """
-    def __init__(self, target_host, out_path, exec_path, add_conf_dirs=[], cache_dir=None):
+    def __init__(self, target_host, out_path, exec_path, add_conf_dirs=None, cache_dir=None):
 
         self.target_host = target_host
         self.out_path = out_path
@@ -92,6 +93,12 @@ class Local(object):
         if self.home_dir:
             self.conf_dirs.append(self.home_dir)
 
+        # Add directories defined in the CDIST_PATH environment variable
+        if 'CDIST_PATH' in os.environ:
+            cdist_path_dirs = re.split(r'(?<!\\):', os.environ['CDIST_PATH'])
+            cdist_path_dirs.reverse()
+            self.conf_dirs.extend(cdist_path_dirs)
+
         # Add user supplied directories
         if self._add_conf_dirs:
             self.conf_dirs.extend(self._add_conf_dirs)
diff --git a/cdist/resolver.py b/cdist/resolver.py
index d181d066..c1b2c292 100644
--- a/cdist/resolver.py
+++ b/cdist/resolver.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# 2011-2012 Steven Armstrong (steven-cdist at armstrong.cc)
+# 2011 Steven Armstrong (steven-cdist at armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -77,6 +77,7 @@ class DependencyResolver(object):
         lists of all dependencies including the key object itself.
         """
         if self._dependencies is None:
+            log.info("Resolving dependencies...")
             self._dependencies = d = {}
             self._preprocess_requirements()
             for name,cdist_object in self.objects.items():
@@ -109,21 +110,10 @@ class DependencyResolver(object):
                     raise RequirementNotFoundError(pattern)
 
     def _preprocess_requirements(self):
-        """Find all before, after and autorequire dependencies and merge them
-        to be just requirements for further processing.
+        """Find all autorequire dependencies and merge them to be just requirements
+        for further processing.
         """
         for cdist_object in self.objects.values():
-            if cdist_object.after:
-                cdist_object.requirements.extend(cdist_object.after)
-                # As we changed the object on disc, we have to ensure it is not 
-                # preprocessed again if someone would call us multiple times.
-                cdist_object.after = []
-            if cdist_object.before:
-                for other_object in self.find_requirements_by_name(cdist_object.before):
-                    other_object.requirements.append(cdist_object.name)
-                # As we changed the object on disc, we have to ensure it is not 
-                # preprocessed again if someone would call us multiple times.
-                cdist_object.before = []
             if cdist_object.autorequire:
                 # The objects (children) that this cdist_object (parent) defined
                 # in it's type manifest shall inherit all explicit requirements 
diff --git a/cdist/test/exec/local.py b/cdist/test/exec/local.py
index 687c13a5..6cb0c605 100644
--- a/cdist/test/exec/local.py
+++ b/cdist/test/exec/local.py
@@ -122,6 +122,25 @@ class LocalTestCase(test.CdistTestCase):
 
         self.assertTrue(os.path.isdir(our_type_dir))
 
+    def test_conf_dir_from_path_linking(self):
+        """Ensure that links are correctly created for types in conf directories which are defined in CDIST_PATH"""
+
+        test_type="__cdist_test_type"
+
+        os.environ['CDIST_PATH'] = conf_dir
+
+        link_test_local = local.Local(
+            target_host='localhost',
+            out_path=self.out_path,
+            exec_path=test.cdist_exec_path,
+        )
+
+        link_test_local._create_conf_path_and_link_conf_dirs()
+
+        our_type_dir = os.path.join(link_test_local.type_path, test_type)
+
+        self.assertTrue(os.path.isdir(our_type_dir))
+
     ### other tests
 
     def test_run_success(self):
diff --git a/cdist/test/object/__init__.py b/cdist/test/object/__init__.py
index 7bdc037e..3a91f709 100644
--- a/cdist/test/object/__init__.py
+++ b/cdist/test/object/__init__.py
@@ -87,7 +87,6 @@ class ObjectTestCase(test.CdistTestCase):
         self.cdist_object.code_local = ''
         self.cdist_object.code_remote = ''
         self.cdist_object.state = ''
-        self.cdist_object.requirements = []
 
     def test_name(self):
         self.assertEqual(self.cdist_object.name, '__third/moon')
diff --git a/docs/changelog b/docs/changelog
index 943d83e4..9efe27c9 100644
--- a/docs/changelog
+++ b/docs/changelog
@@ -4,13 +4,19 @@ Changelog
 	* Changes are always commented with their author in (braces)
 	* Exception: No braces means author == Nico Schottelius
 
-next:
-	* Core: Ensure global and type explorers are executable
+2.1.0:
+	* Core: Ensure global explorers are executable
+	* Core: Ensure type explorers are executable (Steven Armstrong)
 	* Type __rvm_gemset: Change parameter "default" to be boolean
 	* New Type: __user_groups (Steven Armstrong)
 	* Type __user: Remove --groups support (now provided by __user_groups)
 	* Type __apt_ppa: Bugfix: Installeded ppa detection (Steven Armstrong)
-	* Core: Support for --after and --before parameters
+	* Type __jail: Change optional parameter "started" to boolean "stopped" parameter,
+		change optional parameter "devfs-enable" to boolean "devfs-disable" parameter and
+		change optional parameter "onboot" to boolean.
+	* New Type: __ssh_authorized_keys (Steven Armstrong)
+	* Remove Type __ssh_authorized_key: Superseeded by __ssh_authorized_keys
+	* Support for CDIST_PATH (Steven Armstrong)
 
 2.1.0pre8: 2012-11-15
 	* Type cleanup: __apt_ppa, __apt_ppa_update_index, __file, 
diff --git a/docs/dev/logs/2012-11-21.idea-shell-testing b/docs/dev/logs/2012-11-21.idea-shell-testing
new file mode 100644
index 00000000..2a657053
--- /dev/null
+++ b/docs/dev/logs/2012-11-21.idea-shell-testing
@@ -0,0 +1,3 @@
+Use roundup for testing included types?
+
+    http://bmizerany.github.com/roundup/
diff --git a/docs/dev/logs/2012-11-21.roadmap-proposal b/docs/dev/logs/2012-11-21.roadmap-proposal
new file mode 100644
index 00000000..cd60ffe6
--- /dev/null
+++ b/docs/dev/logs/2012-11-21.roadmap-proposal
@@ -0,0 +1,6 @@
+Target version      proposed date       features
+2.1.                2012-12-01          initial support for before/after requirements
+2.2.                2013-03-01          initial notifications support,
+                                        replace require="" with before/after
+2.3.                2013-06-01          installation support: pre-os and install types
+2.4.                2013-09-01          performance speedup via parallelisation
diff --git a/docs/man/man1/cdist.text b/docs/man/man1/cdist.text
index b92fba18..c52e3696 100644
--- a/docs/man/man1/cdist.text
+++ b/docs/man/man1/cdist.text
@@ -14,7 +14,7 @@ cdist [-h] [-V]
 
 cdist banner
 
-cdist config [-h] [-d] [-V] [-c CDIST_HOME] [-i MANIFEST] [-p] [-s] host [host ...]
+cdist config [-h] [-d] [-V] [-c CONF_DIR] [-i MANIFEST] [-p] [-s] host [host ...]
 
 
 
@@ -43,9 +43,14 @@ Configure a system
 -h, --help::
     Show the help screen
 
--c CDIST_HOME, --cdist-home CDIST_HOME::
-    Instead of using the parent of the bin directory as cdist home,
-    use the specified directory
+-c CONF_DIR, --conf-dir CONF_DIR::
+    Add a configuration directory. Can be specified multiple times.
+    If configuration directories contain conflicting types, explorers or
+    manifests, then the last one found is used. Additionally this can also
+    be configured by setting the CDIST_PATH environment variable to a colon
+    delimited list of config directories. Directories given with the
+    --conf-dir argument have higher precedence over those set through the
+    environment variable.
 
 -d, --debug::
     Enable debug output
diff --git a/docs/man/man7/cdist-best-practice.text b/docs/man/man7/cdist-best-practice.text
index a8851f7f..818c423a 100644
--- a/docs/man/man7/cdist-best-practice.text
+++ b/docs/man/man7/cdist-best-practice.text
@@ -30,6 +30,15 @@ Host *
   ControlPersist 10
 --------------------------------------------------------------------------------
 
+SPEEDING UP SHELL EXECUTION
+----------------------------
+On the source host, ensure that /bin/sh is *not* bash: bash is quite slow for
+script execution. Instead, you could use dash after installing it:
+
+--------------------------------------------------------------------------------
+ln -sf /bin/dash /bin/sh
+--------------------------------------------------------------------------------
+
 
 MULTI MASTER OR ENVIRONMENT SETUPS
 ----------------------------------
diff --git a/docs/web/cdist.mdwn b/docs/web/cdist.mdwn
index ee24e910..74457fc8 100644
--- a/docs/web/cdist.mdwn
+++ b/docs/web/cdist.mdwn
@@ -11,6 +11,7 @@ cdist is an alternative to other configuration management systems like
 [cfengine](http://www.cfengine.org/)
 and [puppet](http://www.puppetlabs.com/).
 
+ * [[Why should I use cdist?|why]]
  * [[Documentation|documentation]]
  * [[Supported Operating Systems|os]]
  * [[Installation|install]]
diff --git a/docs/web/cdist/update.mdwn b/docs/web/cdist/update.mdwn
index 3331ec85..a50e7224 100644
--- a/docs/web/cdist/update.mdwn
+++ b/docs/web/cdist/update.mdwn
@@ -42,6 +42,8 @@ To upgrade to the lastet version do
  * The types **\_\_autofs**, **\_\_autofs_map** and **\_\_autofs_reload** have been removed
    (no maintainer, no users)
  * Type **\_\_user**: Parameter --groups removed (use the new \_\_user_groups type)
+ * Type **\_\_ssh_authorized_key** has been replaced by more flexible type 
+    **\_\_ssh_authorized_keys**
  * require="" is deprecated: Use --after and --before as parameters instead
 
 ### Updating from 1.7 to 2.0
diff --git a/docs/web/cdist/why.mdwn b/docs/web/cdist/why.mdwn
new file mode 100644
index 00000000..0fcdf5c5
--- /dev/null
+++ b/docs/web/cdist/why.mdwn
@@ -0,0 +1,68 @@
+[[!meta title="Why should I use cdist?"]]
+
+[[!toc]]
+
+There are several motivations to use cdist, these
+are probably the most popular ones.
+
+## Known language
+
+Cdist is being configured in
+[shell script](https://en.wikipedia.org/wiki/Shell_script).
+Shell script is used by UNIX system engineers for decades.
+So when cdist is introduced, your staff does not need to learn a new
+[DSL](https://en.wikipedia.org/wiki/Domain-specific_language)
+or programming language.
+
+## Powerful language
+
+Not only is shell scripting widely known by system engineers,
+but it is also a very powerful language. Here are some features
+which make daily work easy:
+
+ * Configuration can react dynamicly on explored values
+ * High level string manipulation (using sed, awk, grep)
+ * Conditional support (**if, case**)
+ * Loop support (**for, while**)
+ * Support for dependencies between cdist types
+
+## More than shell scripting
+
+If you compare regular shell scripting with cdist, there is one major
+difference: When using cdist types,
+the results are 
+[idempotent](https://en.wikipedia.org/wiki/Idempotence). 
+In practise that means it does not matter in which order you 
+call cdist types, the result is always the same.
+
+## Zero dependency configuration management
+
+Cdist requires very litte on a target system. Even better,
+in almost all cases all dependencies are usually fulfilled.
+Cdist does not require an agent or a high level programming
+languages on the target host: it will run on any host that
+has an **ssh server running** and a posix compatible shell
+(**/bin/sh**).
+
+## Push based distribution
+
+Cdist uses the push based model for configuration. In this
+scenario, one (or more) computers connect the target hosts
+and apply the configuration. That way the source host has
+very little requirements: Cdist can even run on a sysadmin
+notebook that is loosely connected to the network and has
+limited amount of resources.
+
+Furthermore, from a security point of view, only one machine 
+needs access to the target hosts. No target hosts will ever
+need to connect back to the source host, which contains the
+full configuration.
+
+## Highly scalable
+
+If at some point you manage more hosts than can be handled from
+a single source host, you can simply add more resources: Either
+add more cores to one host or add hosts.
+Cdist will utilise the given resources in parallel.
+
+[[!tag cdist unix]]