[lxc-devel] [lxd/master] Documentation update

stgraber on Github lxc-bot at linuxcontainers.org
Tue Mar 15 22:05:27 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160315/7d304808/attachment.bin>
-------------- next part --------------
From 36a6881506f25c09ce19b4d03ad6c57234aebf76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:31:37 -0400
Subject: [PATCH 01/12] specs: Clarify image handling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This adds some details on image caching and auto-update and clarifies
the way the image identifiers are generated.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/image-handling.md | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/specs/image-handling.md b/specs/image-handling.md
index 6a47440..5a81083 100644
--- a/specs/image-handling.md
+++ b/specs/image-handling.md
@@ -16,9 +16,26 @@ will be kept locally as a private image until either it's been unused
 images.remote\_cache\_expiry or until the image's expiry is reached
 whichever comes first.
 
-LXD keeps track of image usage by updating the last\_use\_date image
+LXD keeps track of image usage by updating the last\_used\_at image
 property every time a new container is spawned from the image.
 
+# Auto-update
+LXD can keep images up to date. By default, any image which comes from a
+remote server and was requested through an alias will be automatically
+updated by LXD. This can be changed with images.auto\_update\_cached.
+
+On startup and then every 3 hours (unless images.auto\_update\_interval
+is set), the LXD daemon will go look for more recent version of all the
+images in the store which are marked as auto-update and have a recorded
+source server.
+
+When a new image is found, it is downloaded into the image store, the
+aliases pointing to the old image are moved to the new one and the old
+image is removed from the store.
+
+The user can also request a particular image be kept up to date when
+manually copying an image from a remote server.
+
 # Image format
 LXD currently supports two LXD-specific image formats.
 
@@ -40,6 +57,8 @@ Tarball, can be compressed and contains:
  - metadata.yaml
  - templates/ (optional)
 
+In this mode, the image identifier is the SHA-256 of the tarball.
+
 ## Split tarballs
 Two (possibly compressed) tarballs. One for metadata, one for the rootfs.
 
@@ -49,6 +68,9 @@ metadata.tar contains:
 
 rootfs.tar contains a Linux root filesystem at its root.
 
+In this mode the image identifier is the SHA-256 of the concatenation of
+the metadata and rootfs tarball (in that order).
+
 ## Content
 The rootfs directory (or tarball) contains a full file system tree of what will become the container's /.
 

From a7c3d6bd4f35aa0b030f12f03a1ab74fe0658a67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:32:05 -0400
Subject: [PATCH 02/12] specs: Remove command-line-user-experience
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This document is pretty out of date and it's a pain to keep in sync with
the actual client. It's far better to just make sure that the help in
the client itself is kept up to date.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/command-line-user-experience.md | 680 ----------------------------------
 1 file changed, 680 deletions(-)
 delete mode 100644 specs/command-line-user-experience.md

diff --git a/specs/command-line-user-experience.md b/specs/command-line-user-experience.md
deleted file mode 100644
index d9b287e..0000000
--- a/specs/command-line-user-experience.md
+++ /dev/null
@@ -1,680 +0,0 @@
-# Introduction
-
-The "lxc" command is the main tool used by users to interact with LXD when
-running it outside of OpenStack. The command is available to all users and can
-be used to manage any local or remote resources provided they have the
-credentials to do so.
-
-# Remote operations
-
-The lxc command line tool is designed to manage LXD hosts as well as connect
-to a variety of remote resources.
-
-The list of remote servers and their credentials is only stored in the client,
-the servers don't know about each other nor do they have to. The client is the
-one initiating any cross-server communication by instructing the two servers to
-start talking to each other. Should that fail, for example because of a
-firewall between the two servers, the client will then act as a relay
-forwarding the data stream between the two servers.
-
-* * *
-
-# Resources
-The lxc command interacts with resources. Currently supported resources are:
- * containers
- * container snapshots
- * images
- * container hosts
-
-lxc defaults to interacting with the local LXD daemon, remote operations
-must be prefixed with the remote server's name followed by a colon.
-
-Some examples with the "info" command:
-
-Command                               | Result
-:------                               | :-----
-lxc info                              | Show some information on the local LXD server
-lxc info dakara:                      | Same but against the remote "dakara" server
-lxc info c1                           | Show information about the "c1" container
-lxc image info ubuntu/trusty/amd64    | Show information about the "ubuntu/trusty/amd64" image (alias)
-lxc info dakara:c2/yesterday          | Show information about the "yesterday" snapshot of container "c2" on remote host "dakara"
-
-
-This URI scheme is designed to be very specific (no ambiguity) and as short as
-possible.
-
-* * *
-
-# Commands
-## Overview
-
-Command     | Description
-:------     | :----------
-config      | Change container settings (quotas, notes, OS metadata, ...)
-copy        | Copy an existing container or container snapshot as a new container
-delete      | Delete a resource (container, snapshot, image, ...)
-exec        | Spawn a command within the container
-file        | Transfer files in and out of the container
-image       | Image handling
-info        | Show information about a container, container snapshot or remote server
-init        | Create a container without starting it
-launch      | Create and start a new container from an image
-list        | List all the containers
-move        | Move a container either to rename it or to migrate it
-profile     | Manage container configuration profiles.
-publish     | Make an image out of an existing container or container snapshot
-remote      | Remote server handling
-restart     | Restart a container
-restore     | Restore a snapshot of a container
-snapshot    | Make a snapshot (stateful or not) of a container
-start       | Start a container
-stop        | Stop a container
-
-* * *
-
-## config
-
-**Arguments**
-
-    edit [resource]
-    get [resource] <key>
-    set [resource] <key> <value>
-    show [resource]
-    unset [resource] <key>
-    device add <resource> <device name> <type> [key=value]...
-    device remove <resource> <device name>
-    device list <resource>
-    device show <resource>
-    trust add [remote] <certificate>
-    trust remove [remote] <fingerprint>
-    trust list [remote]
-
-**Description**
-
-Probably one of the most complex commands, it allows querying and
-setting all the configuration options available for containers and LXD hosts.
-
-The trust sub-command is there to manage the server's trust store. It
-can list the certificates which the server currently trusts, delete
-entries (based on their fingerprint) and add new entries using a
-provided certificate.
-
-The edit commands are there to offer a more convenient user interface by
-opening a text editor in which the current configuration is displayed
-alongside a set of useful examples. The user can then edit things in
-place and when saved, all changes will be committed.
-
-**Examples**
-
-Command                                                                         | Result
-:------                                                                         | :-----
-lxc config show                                                                 | Show the local server's configuration
-lxc config show dakara:                                                         | Show "dakara"'s server' configuration
-lxc config set core.trust\_password new-trust-password                          | Set the local server's trust password to "new-trust-password"
-lxc config set c1 limits.memory 2GB                                             | Set a memory limit of 2GB for container "c1"
-lxc config show c1                                                              | Show the configuration of the "c1" container, starting by the list of profiles it’s based on, then the container specific settings and finally the resulting overall configuration.
-lxc config trust add new-client-cert.crt                                        | Add new-client-cert.pem to the default remote's trust store (typically local LXD)
-lxc config trust add dakara: new-client-cert.crt                                | Add new-client-cert.pem to the "dakara"'s trust store
-lxc config trust list                                                           | List all the trusted certificates on the default remote
-lxc config trust list dakara:                                                   | List all the trusted certificates on "dakara"
-lxc config trust remove [name|\<cert fingerprint\>]                             | Remove a certificate from the default remote
-lxc config trust remove dakara: \<cert fingerprint\>                            | Remove a certificate from "dakara"'s trust store
-
-* * *
-
-## copy
-
-**Arguments**
-
-    <source container/snapshot> [container name]
-
-**Description**
-
-Creates a copy of an existing container or container snapshot as a new
-container. If the new container's name isn't specified, a random one
-will be generated.
-
-**Examples**
-
-Command                                 | Result
-:------                                 | :-----
-lxc copy c1 c2                          | Create a container called "c2" which is a copy of container "c1" with its hostname changed and a fresh MAC address
-lxc copy c1 dakara:                     | Copy container "c1" to remote host "dakara" still keeping the name "c1" on the target
-lxc copy c1 dakara:c2                   | Same as above but also rename the container and change its hostname
-
-
-* * *
-
-## delete
-
-**Arguments**
-
-    <container or snapshot name>
-
-**Description**
-Destroy a container or container snapshot and any attached data
-(configuration, snapshots, ...).
-
-This will destroy the resource (container) even if it is currently in use.
-
-**Examples**
-
-Command                         | Result
-:------                         | :-----
-lxc delete c1                   | Remove the c1 container, its configuration and any snapshot it may have
-lxc delete c1/yesterday         | Remove the "yesterday" snapshot of "c1"
-lxc delete dakara:c2/yesterday  | Remove the "yesterday" snapshot for "c2" on remote host "dakara"
-
-* * *
-
-## exec
-
-**Arguments**
-
-    <container> command...
-
-**Description**
-
-Execute a command inside the remote container.
-
-**Examples**
-
-Command                                                 | Result
-:------                                                 | :-----
-lxc exec c1 -- /bin/bash                                   | Spawn /bin/bash in local container c1
-tar cf - /opt/myapp \| lxc exec dakara:c2 -- tar xvf -    | Make a tarball of /opt/myapp with the stream going out to stdout, then have that piped into lxc exec connecting to a receiving tar command in container running on remote host "dakara"
-
-* * *
-
-## file
-
-**Arguments**
-
-    file push [--uid=UID] [--gid=GID] [--mode=MODE] <source> [<source>...] <target>
-    file pull <source> [<source>...] <target>
-
-**Description**
-Copies file to or from the container. Supports rewriting the uid/gid/mode.
-
-**Examples**
-
-Command                                                 | Result
-:------                                                 | :-----
-lxc file push --uid=0 --gid=0 test.sh dakara:c2/root/   | Push test.sh as /root/test.sh inside container "c2" on host "dakara", rewrite the uid/gid to 0/0
-lxc file pull dakara:c2/etc/hosts /tmp/                 | Grab /etc/hosts from container "c2" on "dakara" and write it as /tmp/hosts on the client
-
-* * *
-
-## image
-
-**Arguments**
-
-    image alias create <alias> <target>
-    image alias list [<remote>:]
-    image alias delete <alias>
-    image copy [<remote>:]<image> <remote>: [--alias=ALIAS].. [--copy-aliases] [--public]
-    image delete <image>
-    image edit <image>
-    image export <image> [target]
-    image import <tarball> [rootfs tarball] [target] [--public] [--created-at=ISO-8601] [--expires-at=ISO-8601] [--fingerprint=FINGERPRINT] [--alias=ALIAS].. [prop=value]
-    image info <image>
-    image list [filter]
-    image move <image> <remote:>
-    image set <image> <key> <value>
-    image show <image>
-    image unset <image> <key>
-
-**Description**
-Manage the LXD image store.
-
-Images can either be fed from an external tool using the API or manually
-imported into LXD using the import command. Attributes can then be set
-on them and images can be copied/moved to other LXD hosts.
-
-Images may also be copied or moved between hosts.
-
-The unique identifier of an image is its sha256, as a result, it's only
-possible to have one copy of any given image on a given LXD host.
-
-
-The "description" property is special in that if it's set, it'll appear in "lxc image list".
-
-Aliases are mappings between a user friendly name and an image.
-Aliases may contain any character except for colons.
-
-Images are typically referenced by their full or partial fingerprint, in most
-cases aliases may also be used and for listings, property filters can
-also be used.
-
-
-**Examples**
-
-Command                                                                                                                 | Result
-:------                                                                                                                 | :-----
-lxc image import centos-7-x86\_64.tar.gz --created-at=2014-12-10 --expires-at=2015-01-10 os=fedora release=7 arch=amd64 | Import a centos LXD image in the local LXD image store
-lxc image import debian-jessie\_amd64.tar.gz dakara:                                                                    | Import a debian LXD image in the lxc image store of remote host "dakara"
-lxc image import debian-jessie\_amd64.meta.tar.gz debian-jessie\_amd64.tar.g dakara:                                    | Import a debian LXD image in split format in the lxc image store of remote host "dakara"
-lxc image alias create centos/7 \<fingerprint\>                                                                         | Create an alias for centos/7 pointing to our centos 7 image
-
-**Example output (lxc image list)**
-
-    ALIAS                   FINGERPRINT     PUBLIC  DESCRIPTION                     UPLOAD DATE
-    -------------------------------------------------------------------------------------------
-    busybox-amd64           146246146827... yes     -                               Mar 12, 2015 at 10:41pm (CDT)
-    ubuntu/devel (3 more)   95830b5e4e04... yes     Ubuntu 15.04 (devel) x86 64bit  Mar 8, 2015 at 1:27am (CST)
-    -                       a1420943168a... no      Test image                      Mar 4, 2015 at 3:41pm (CST)
-
-**Example output (lxc image info)**
-
-    Fingerprint: 146246146827e213eff5c9b5243c8c28cf461184a507588d6c7abac192e600dd
-    Filename: ubuntu-vivid-amd64-default-20150308.tar.xz
-    Size: 65MB
-    Architecture: x86_64
-    Public: yes
-    Timestamps:
-        Created: 2015/03/08 10:50 UTC
-        Uploaded: 2015/03/09 16:00 UTC
-        Expires: never
-    Properties:
-        arch: x86_64
-        build: 20150308
-        description: Ubuntu 15.04 (devel) x86 64bit
-        os: Ubuntu
-        release: vivid, 15.04
-        variant: default
-    Aliases:
-        - ubuntu/devel
-        - ubuntu/vivid
-        - ubuntu/vivid/amd64
-
-* * *
-
-## info
-
-**Arguments**
-
-    [resource]
-
-**Description**
-
-Prints information about a container, snapshot or LXD host.
-
-**Examples**
-
-Command                                       | Result
-:------                                       | :-----
-lxc info                                      | Displays local host status
-lxc info dakara:                              | Displays the host status of remote host "dakara"
-lxc info c1                                   | Displays the status of local container "c1"
-lxc info dakara:c2                            | Displays the status of remote container "c2" on "dakara"
-lxc info dakara:c2/yesterday                  | Displays the status of snapshot "yesterday" for remote container "c2" on "dakara"
-
-* * *
-
-## init
-
-**Arguments**
-
-    <image> [container name] [--ephemeral|-e] [--profile|-p <profile>...]
-
-**Description**
-
-init is used to create a new container from an image, but not start it.
-
-If the container name isn't specified, a random one will be used.
-
-Passing --ephemeral will make LXD create a temporary container which
-will be destroyed when shutdown.
-
---profile is used to apply a configuration profile (or multiple ones if passed
-multiple times) to the newly created container, when passed with an existing
-container, it will only append the configuration profile for that run.
-
-**Examples**
-
-Command                                        | Result
-:------                                        | :-----
-lxc init ubuntu/trusty/amd64                   | Create a new local container based on the Ubuntu 14.04 amd64 image and with a random name
-lxc init ubuntu/precise/i386 dakara:           | Create a new remote container on "dakara" based on the local Ubuntu 14.04 i386 image and with a random name
-lxc init ubuntu c1 -p micro                    | Create a new local container called "c1" based on the Ubuntu image and run it with a "micro" profile
-
-* * *
-
-## launch
-
-**Arguments**
-
-    <image name> [container name] [--ephemeral|-e] [--profile|-p <profile>...]
-
-**Description**
-
-launch is used to create and start a new container from an image.
-
-If the container name isn't specified, a random one will be used.
-
-Passing --ephemeral will make LXD create a temporary container which
-will be destroyed when shutdown.
-
---profile is used to apply a configuration profile (or multiple ones if passed
-multiple times) to the newly created container, when passed with an existing
-container, it will only append the configuration profile for that run.
-
-**Examples**
-
-Command                                         | Result
-:------                                         | :-----
-lxc launch ubuntu/trusty/amd64                  | Create a new local container using a random name and based on the Ubuntu 14.04 amd64 image
-lxc launch ubuntu/precise/i386 dakara:          | Create a new remote container on "dakara" using a random name and based on the local Ubuntu 14.04 i386 image
-lxc launch ubuntu c1 -p with-nesting            | Create a new local container called "c1" based on the Ubuntu image and run it with a profile allowing container nesting
-
-## list
-**Arguments**
-
-    [resource] [filters] [format]
-
-**Description**
-
-Lists all the available containers. If a container is specified, then
-it'll list all the available snapshots for the container.
-
-Each comes with some minimal status information (status, addresses, ...)
-configurable if needed by passing a list of fields to display.
-
-For containers, a reasonable default would be to show the name, state, ipv4
-addresses, ipv6 addresses, memory and disk consumption.
-Snapshots would be displayed below their parent containers and would re-use the
-name, state and disk consumption field, the others wouldn’t be relevant and
-will be displayed as "-".
-
-The filters are:
- * A single keyword like "web" which will list any container with "web" in its name.
- * A key/value pair referring to a configuration item. For those, the namespace can be abreviated to the smallest unambiguous identifier:
-   * "user.blah=abc" will list all containers with the "blah" user property set to "abc"
-   * "u.blah=abc" will do the same
-   * "security.privileged=1" will list all privileged containers
-   * "s.privileged=1" will do the same
-
-Multiple filters may be passed, a container will then have to match them all to be listed.
-
-**Examples**
-
-Command             | Result
-:------             | :-----
-lxc list            | Show the list of local containers, snapshots and images
-lxc list dakara:    | Show the list of remote containers, snapshots and images on "dakara"
-lxc list c1         | Show the entry for the local container "c1" as well as any snapshot it may have
-
-**Example output**
-
-    NAME         STATE    IPV4       IPV6                                    MEMORY     DISK
-    -------------------------------------------------------------------------------------------
-    precise      STOPPED  -          -                                       -          UNKNOWN
-    precise-gui  RUNNING  10.0.3.59  2607:f2c0:f00f:2761:216:3eff:fe51:234f  4435.89MB  UNKNOWN
-    vivid        STOPPED  -          -                                       -          UNKNOWN
-
-* * *
-
-## move
-
-**Arguments**
-
-    <source resource> <destination resource>
-
-**Description**
-
-Moves a resource either locally (rename) or remotely (migration). If the
-container is running, this will do a live migration, otherwise it will simply
-move the on-disk container data.
-
-**Examples**
-
-Command                         | Result
-:------                         | :-----
-lxc move c1 c2                  | Rename container c1 to c2
-lxc move c1 dakara:             | Move c1 to "dakara". If the container is stopped, this simply moves the container and its configuration to "dakara". If it is running, this live migrates container c1 to "dakara". This will first stream the filesystem content over to "dakara", then dump the container state to disk, sync the state and the delta of the filesystem, restore the container on the remote host and then wipe it from the source host
-lxc move c1 dakara:c2           | Move c1 to "dakara" as "c2"
-
-* * *
-
-## profile
-
-**Arguments**
-
-    device add <profile name> <device name> <type> [key=value]...
-    device remove <profile name> <device name>
-    device list <profile name>
-    apply <resource> <profile name>[,<second profile name>, ...]
-    create <profile name>
-    copy <source profile name> <target profile name>
-    delete <profile name>
-    edit <profile name>
-    list [remote] [filters]
-    get <profile name> <key>
-    move <profile name> <new profile name>
-    set <profile name> <key> <value>
-    show <profile name>
-    unset <profile name> <key>
-
-This command supports profiles which are used to group configuration settings
-(configurations keys and devices) and then apply the resulting set to a given
-container.
-
-It’s possible to create, delete, list and setup profiles on a remote
-host. The one limitation is that a container can only reference local
-profiles, so profiles need to be copied across hosts or be moved around
-alongside the containers.
-
-Also note that removing a profile or moving it off the host will fail if any
-local container still references it.
-
-**Examples**
-
-Command                                                                  | Result
-:------                                                                  | :-----
-lxc profile create micro                                                 | Create a new "micro" profile.
-lxc profile set micro limits.memory 256MB                                | Restrict memory usage to 256MB
-lxc profile set micro limits.cpu 1                                      | Restrict CPU usage to a single core
-lxc profile copy micro dakara:                                           | Copy the resulting profile over to "dakara"
-lxc profile show micro                                                   | Show all the options associated with the "micro" profile and all the containers using it
-lxc profile unset dakara:nano limits.memory                              | Unset "limits.memory" for the "nano" profile on "dakara"
-lxc profile apply c1 micro,nesting                                       | Set the profiles for container "c1" to be "micro" followed by "nesting"
-lxc profile apply c1 ""                                                  | Unset any assigned profile for container "c1"
-
-
-* * *
-
-## publish
-
-**Arguments**
-
-    <resource> [target] [--public] [--expires-at=ISO-8601] [--alias=ALIAS].. [prop-key=prop-value]...
-
-**Description**
-Takes an existing container or container snapshot and makes a
-compressed image out of it. By default the image will be private, that is,
-it’ll only be accessible locally or remotely by authenticated clients. If --
-public is passed, then anyone can pull the image so long as LXD is running.
-
-It will also be possible for some image stores to allow users to push new
-images to them using that command, though the two image stores that will come
-pre-configured will be read-only.
-
-**Examples**
-
-Command                                         | Result
-:------                                         | :-----
-lxc publish c1/yesterday                        | Turn c1/yesterday into a private image for consumption by trusted LXD servers
-lxc publish c2 dakara: --public                 | Turn c2 into a public image on remote host "dakara"
-
-* * *
-
-## remote
-
-**Arguments**
-
-    add <name> <URI> [--always-relay] [--password=PASSWORD] [--accept-certificate] [--public]
-    remove <name>
-    list
-    rename <old name> <new name>
-    set-url <name> <new URI>
-    set-default <name>
-    get-default
-
-**Description**
-Manages remote LXD servers.
-
-Scheme                  | Description
-:-----                  | :----------
-unix://Unix             | socket (or abstract if leading @) access to LXD
-https://                | Communication with LXD over the network (https)
-
-By default lxc will have the following remotes defined:
-
-Name        | URI                                               | Description
-:---        | :--                                               | :----------
-local       | unix:///var/lib/lxd/sock                          | Communication to the local LXD daemon (hidden if not present)
-
-The default remote is "local", this allows simple operations with local
-resources without having to specify local: in front of all of their names. This
-behavior can be changed by using the set-default argument. On a system without
-a local LXD, the first manually added remote should be automatically set as
-default.
-
-Protocol auto-detection will happen so that adding a source solely based on its
-name will work too, assuming it doesn’t support multiple protocols.
-
-The "--always-relay" flag of "remote add" can mean one of two things:
- * If it's an image server, that this server is only reachable by the
-   client and that the client needs to act as a relay and transfer the
-   image over to the server.
- * If it's a LXD server, that this server has limited connectivity which
-   prevents it from accessing the image servers and that the client needs
-   to act as a relay for it.
-
-The "--accept-certificate" flag of "remote add" will automatically accept
-the remote's certificate without prompting the user to verify the certificate
-fingerprint.
-
-**Examples**
-
-Command                                                                  | Result
-:------                                                                  | :-----
-lxc remote add dakara dakara.local                                       | Add a new remote called "dakara" using its avahi DNS record and protocol auto-detection
-lxc remote add dakara dakara.local --password=BLAH                       | Add a new remote called "dakara" using its avahi DNS record and protocol auto-detection and providing the password in advance
-lxc remote add dakara dakara.local --password=BLAH --accept-certificate  | Add a new remote called "dakara" using its avahi DNS record and protocol auto-detection and providing the password in advance and also accepting the certificate without fingerprint verification
-lxc remote add vorash https://vorash.srv.dcmtl.stgraber.net              | Add remote "vorash" pointing to a remote lxc instance using the full URI
-lxc remote set-default vorash                                            | Mark it as the default remote
-lxc start c1                                                             | Start container "c1" on it
-
-* * *
-
-## restart
-
-**Arguments**
-
-    <resource> [--kill|-k] [--timeout|-t]
-
-**Description**
-
-Restarts the container. The flags have the same behavior as the 'stop' command.
-Restart will fail on ephemeral containers, as they cannot be booted after they
-are stopped.
-
-**Examples**
-
-Command                     | Result
-:------                     | :-----
-lxc restart c1              | Do a clean restart of local container "c1"
-lxc restart dakara:c1 -t 10 | Do a clean restart of remote container "c1" on "dakara" with a reduced timeout of 10s
-lxc restart dakara:c1 -k    | Kill and restart the remote container "c1" on "dakara"
- 
-* * *
-
-## restore
-
-**Arguments**
-
-    <resource> <snapshot name> [--stateful]
-
-**Description**
-
-Set the current state of a resource back to what it was when it
-was snapshotted. All snapshots are kept as they are, only the current state is
-discarded and replaced by that from the snapshot. This requires the container
-be stopped unless --stateful is passed and the snapshot contained a running
-container state in which case the container will be killed, reset to the
-snapshot and the container’s state restored.
-
-**Examples**
-
-Command                                         | Result
-:------                                         | :-----
-lxc restore c1 it-works                         | Restore the c1 container back to its "it-works" snapshot state
-lxc restore dakara:c1 pre-upgrade --stateful    | Restore a pre-dist-upgrade snapshot of container "c1" running on "dakara". Allows for a very fast recovery time in case of problem
-
-* * *
-
-## snapshot
-
-**Arguments**
-
-    <resource> [snapshot name] [--stateful] [--expire=ISO-8601]
-
-**Description**
-
-Makes a read-only snapshot of a resource (typically a container).
-For a container this will be a snapshot of the container’s filesystem,
-configuration and if --stateful is passed, its current running state.
-
-If the snapshot name isn't specified, a timestamp will be used.
-
-**Examples**
-
-Command                                         | Result
-:------                                         | :-----
-lxc snapshot c1 it-works                        | Create "it-works" snapshot of container c1
-lxc snapshot dakara:c1 pre-upgrade --stateful   | Make a pre-dist-upgrade snapshot of container "c1" running on "dakara". Allows for a very fast recovery time in case of problem
-
-* * *
-
-## start
-
-**Arguments**
-
-    <resource>
-
-**Description**
-
-start is used to start an existing container.
-
-
-**Examples**
-
-Command                                        | Result
-:------                                        | :-----
-lxc start c2                                   | Start local container "c2"
-lxc start dakara:c3                            | Start the "c3" container on remote host "dakara"
-
-* * *
-
-## stop
-
-**Arguments**
-
-    <resource> [--kill|-k] [--timeout|-t]
-
-**Description**
-
-Stops the container. By default does a clean shutdown by sending
-SIGPWR to the container’s init process if after 30s the container is still
-running, an error is displayed. The 30s timeout can be overridden using --
-timeout. Alternatively, --kill can be passed which will cause the container to
-be immediately killed (timeout is meaningless in this case).
-
-**Examples**
-
-Command                     | Result
-:------                     | :-----
-lxc stop c1                 | Do a clean shutdown of local container "c1"
-lxc stop dakara:c1 -t 10    | Do a clean shutdown of remote container "c1" on "dakara" with a reduced timeout of 10s
-lxc stop dakara:c1 -k       | Kill the remote container "c1" on "dakara"

From eb60538e31ea6cd253820be1376b50d35bf08d94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:36:53 -0400
Subject: [PATCH 03/12] specs: Remove dia database diagram
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Binary file and a bit of a pain to update.

We have database.md which explains everything, if we need a diagram
again, we should have it in svg and ideally have it generated from the
schema.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/database_schema.dia | Bin 2962 -> 0 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 specs/database_schema.dia

diff --git a/specs/database_schema.dia b/specs/database_schema.dia
deleted file mode 100644
index e5116edb41ff8f81a9dc934b1483500022f4b4f9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2962
zcmZ|Rc{~%28wc?C)|V;wnKM_7kX8xhrp;uGA(kVxq>*x)+t+fHBUjFaIkrVoattMD
znPb(eRWe68*Q~{eIevZn{`32zp7-nd=Xt%Jf1cO#$44zoc*nmb_!qmvF>JwD?)vJg
zhw~?WVTVV0<as>0lT>%{m1}p2kE@{aw}-tqf^U@#Z>;3)0ZjJ!>B;O{aw$aY6H>8%
zG`+N7Qk1YYP0<T91AD60FQpl2!^pD3;CbUpC)JOMTP)7loz20|Z8*yP4g1a0AQLnp
zWGHNNvC2$8v)`$kIXJl6-Y3ixzt?_Bd!UAyh`RNn6132&_PEtcZMVXp^#bi3j#~X<
zYO*EWE6gNI^`ni+I{H at a;97fki`VGQ*IL6~G*HZ?#6(?RHna0K)7=D2^?6}`bVy^(
zBjQyy274~QS|0ug`86nS<~~TrM?QAH?DX8YTF^W94p6C+>f>!yS-XOGUpMsTWL=j{
zVPiOA=z>wkEWZb_twkE~OC?t&tR0<b>PzLnJ2XpHN at yZ~2^&M<SOz0PSw|0o_R8}O
z(gI6uLwmk^T^MZWz{P1vM`Ws?<$`_IUC+wQXRKQcXx*bHy`^wGK6Q9-w6Z9aLrndw
zOc$T2Yll at fn%{VnUi<17ZYj at l4Ku{vnpeupAKc=B`Z=l<p*zRp#=ZreDRhs?QV^2N
z`LWiPJ^)e$uVv7KM(e8a^B?a<5gAeJg~*|WnhK at Jd5ye#@J9w)jN!)4R`Vw;$$D+D
z-Nwesq74q;mk6%$AA4`Hy%tLvUDwZxVKR5B>+Z~;h_fxq*_9uI%XIBUQ)0baA>*|A
zB;&3=`xjB8k1a3=69uuTK^lTL9e2wXt at hCh*ZEAgOEaA@<W^w&pcgni!{_!+e{?m~
z5z5;%>K5HsZrEEPeklKM$C_x6KCuGc(y4yMXSkf5dKxJ}2Uf^~+&4?r_LPoX%O|}!
z2<4R^r-$BSI}HO~bv3*9C=)qEhcHI(edMC2_rtS#EkK$OXZuAX8S3V&zx!C|nJ``?
zr)9k1xD$?1$J-k)Omo;TA5r!|g;dG5Gbij0H!P)gA6|~%$t%A&eJ?ifPRit^T-&9A
zErreu|J0HkYuNtL!>e}UkPoTSQ37es0em~r@?fy5?5)wj=nIuoS|;psu{{$f#qE}B
znn$n45Wk!UMMGD?37eiQ`;n<Hyecz?*}$G$O<AAmeo}TTqT!+LR9kpSKm6U$_NaH&
z&lCF9i;VfwFKkc at Gq&l={yz8tmfo-&J^D?<DY7hxI0O- at U#HRC25J?@nP_gpr7cNq
z8eB5x!iOW*!420UQu^K=W|i^MBQCnFp#2e9;vTetbh>))$deiG8RgBBG^9Lhwqwkk
z3rky(H=_l2 at S_D8bI?R^;}21#4uEDXW!K#PpoNNdyJ5KuJq_gHKIGckN;w5OcwBn*
z4dRolm7oV<@=0B%2Q1b7hZSxO8dWSc-m1fOM7n`Lr#+KIYK(7#6cd|YxX4PLlHmV|
zha`Up at s%tl=_MCd=I?95ZGAr*&u~pVti2Kpji(#E&09ABsLYg*IAwY3FIWErSH;;b
znw<w4Ah}l44_c{Fqc>3%_vI8RUPCMlJ34)4u;f)>p%cB>3dJop1-h($oyb)_cEz&j
za_jlV*?>WOx;z(X;G>Vxk%g5jhquhDGbSVk_2`d-RVKaz_gGB-?9aeG!K&D*#v12?
zjgWNb at HleV&GlsU=e%XyM7*NJNP&}8*LCv%xccY;)jTCiP4&5~7JpM9e{Q4lgdYWP
zJ_UDfR;}$It~)g9>&O*f;+Ot}FJu!^MYpN4a!F1+=d0-eD(~X_cU!%eadp$)qK6s>
zCRgqM8SGG~U0PeXQqC#-v4VSt7@?ry-gs2cIrNfmBN9{p*nu$~q5GJ>VmuAQ8py(9
z(i<e;>ebe^5j4rSx?!fxDsY|SLpu4bW=uv<Ar|#$MFosVi(O3ehBT=C2zY<LCQ>mq
zE0^>B*A5{)^FvkxG1R#|P%P7_>yC{lU0e0Cs6RE06yFY&!DubVfC)-90amcODg`4F
zOb&X-i+32HE#W(xEX|vBJ!xes@*19-of0mCui2-vYaR#z|NrRhA(eiilLEhVu)<~H
z10=f2rI$;YGM63Au4^s3vqrB{WaFV3_2aI^FP~?JXz14xg-DJzPjmi~3RWmT4@{qJ
z at M#rxy)2mTaC0h2rx>fVVMKQ&`ehoX=^UMF$m-K|sA>xBjlqRZy%y8VM&<gy#+UAn
z+Eskpglv}$%C7t at S;^W35%{f+{Sd$om;Wp(<AvQv1dMQL_cGwNX;O at se}L=BXCj=w
zkC9IS)7G1)FX=f(j4F**Q4>Jv>b`FS49bD2o^SS-GM!F7{RdWzoIXHJL#|K6FXUT>
zcdAyo12WH%7WT<dg_nAikM+6&lMeizN7{im0%rf|h{CvxY{v}OPoiH-H*FTsH?_?t
z73-p-a-77%eG1jbymmbjX?b%rOqk(gc1QY7e&3wdQOg5UORoUOn8rP%dwU`(2o5&y
z&*nPw0k>B^A7OIVwca491X`+FdT8>@+fh$gyFVI!??k;W_cZL=20%jOx2O>-H|vMa
zem(Lu0t$L?mshA%HFk+W1Jqyw4qWt{D>G`$9+6MwHZHB9=Qfg0`<K{o{>1kfN=j)!
z6D6gS4=L$l6%1UlOldBcT)ta(I?`q;*0eGG8e^4D)#sU(8xM~$tw%1{aoqNTp28Hc
zVyLc1-X*oQozj8%kg~h)Hw*TDadg38pV`yOYulfpFv-_*KVWsJIlxU}CI^FYLTrvk
zGV#|~3v8 at nd$FZ*+jCdB61n|$d+>sP5bB11nv6*LWl@=sN-DABL$IupC%4QCAa<Gp
z#4$|NFhVTCxA2^|yUTcUoRlhJ7oxV57`=MREzXtr)Vezah#F>K8;;cl9=|ewo!i5b
zmLnd#wRrbQVhqur*@+P+827+WToJ(QwJhtvnr|OB6!|TxzMqW14Z&YRX$t))TW6|!
zesblo{!VYGwQtOK`-V0#Hrar?9J?U(`2H-?Qm4 at SOt7NVqS`nc;kn-HS(IW7TVe<G
zy7rhmaYds=$bvAyjcb_+PpUsl&=xdxsae7W@*V|-Se9cZfnC^rv&>z*Rv7$ET=46l
zUm?$jFroV=9$$3T+eLn%R)on~T<yQC(agOY=iM|_R0;fyZmJ$<JzOL+bz56 at lN`;a
z+N<UC2_XX+j4riaw=MB@=vCjdSd-^jiC8Te#ZP|^t<(`<fOIS{$_4Njv+C2;oP2s#
z;@-9<W+kC&@Q`6e<dGn4HOHEgop6Ca=y+a9xS?3 at EHc%JSyLKc%#=xKwj at hp>@t%K
zovwDD6n)U8f&KXkka*&Ap(8?Vw at +l$>g at ZW{#*Adtp^lbfO*y#GElrTlmA+#N9k^z
z0Ndbu<5`pNY27!w{aISjCW|{HY!4^)T4rBG^s^!<AI;+~A%kZ|T`W|`<NCw#@Py5y
z&{K{@e6gln at O)`V^@0Qi)g}FLq<T+5eo|`JI4{Ew(;AW%UDW1$42|qohR%c#3?pZ6
l?1KEsv<n2qGyfUUR(=HYPW_vOV>ebT%<^pwci0K+_#Y*YzYqWb


From 74ceac592e84deb1d6a9d7a0cde7908d1c3d7eeb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:37:42 -0400
Subject: [PATCH 04/12] specs: Clarify the daemon spec
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/daemon-behavior.md | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/specs/daemon-behavior.md b/specs/daemon-behavior.md
index b1e798b..56f5bd2 100644
--- a/specs/daemon-behavior.md
+++ b/specs/daemon-behavior.md
@@ -1,6 +1,7 @@
 # Introduction
 
-This specification covers some of the daemon's behavior, such as reaction to given signals, crashes, ...
+This specification covers some of the daemon's behavior, such as
+reaction to given signals, crashes, ...
 
 # Startup
 On every start, LXD checks that its directory structure exists. If it
@@ -8,8 +9,8 @@ doesn't, it'll create the required directories, generate a keypair and
 initialize the database.
 
 Once the daemon is ready for work, LXD will scan the containers table
-for any container for which the stored power\_state differs from the
-current one. If a container's power\_state in the database is 1 and the
+for any container for which the stored power state differs from the
+current one. If a container's power state was recorded as running and the
 container isn't running, LXD will start it.
 
 # Signal handling

From 262d01f8937ca422ffe766536ee748780148aeba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:42:05 -0400
Subject: [PATCH 05/12] specs: Update /dev/lxd spec to match current state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/dev-lxd.md | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/specs/dev-lxd.md b/specs/dev-lxd.md
index d4c183b..be5b398 100644
--- a/specs/dev-lxd.md
+++ b/specs/dev-lxd.md
@@ -1,9 +1,6 @@
 # Introduction
 Communication between the hosted workload (container) and its host while
-not strictly needed is a pretty useful feature. This allows querying for
-configuration options, reporting errors back to the host as well as
-adding support for a range of new features by allowing events to be sent
-in either directions.
+not strictly needed is a pretty useful feature.
 
 In LXD, this feature is implemented through a /dev/lxd/sock node which is
 created and setup for all LXD containers.
@@ -42,7 +39,6 @@ authentication support in the /dev/lxd/sock API.
    * /1.0
      * /1.0/config
        * /1.0/config/{key}
-     * /1.0/events
      * /1.0/meta-data
 
 ## API details
@@ -51,6 +47,12 @@ authentication support in the /dev/lxd/sock API.
  * Description: List of supported APIs
  * Return: list of supported API endpoint URLs (by default ['/1.0'])
 
+Return value:
+
+    [
+        "/1.0"
+    ]
+
 ### /1.0
 #### GET
  * Description: Information about the 1.0 API
@@ -59,7 +61,7 @@ authentication support in the /dev/lxd/sock API.
 Return value:
 
     {
-        'api_compat': 0      # Used to determine API functionality
+        "api_version": "1.0"
     }
 
 ### /1.0/config
@@ -70,22 +72,24 @@ Return value:
 Note that the configuration key names match those in the container
 config, however not all configuration namespaces will be exported to
 /dev/lxd/sock.
-We'll initially only support the user namespace (user.\* keys).
+Currently only the user.\* keys are accessible to the container.
 
 At this time, there also aren't any container-writable namespace.
 
+Return value:
+
+    [
+        "/1.0/config/user.a"
+    ]
+
 ### /1.0/config/\<KEY\>
 #### GET
  * Description: Value of that key
  * Return: Plain-text value
 
-### /1.0/events
-#### GET
- * Description: event interface
- * Return: websocket upgrade (similar to /1.0/events on main API)
+Return value:
 
-#### POST
- * Description: post a new event
+    blah
 
 ### /1.0/meta-data
 #### GET

From fc0bb26a9040fe5448f163e03f2ae090ac13f559 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:44:56 -0400
Subject: [PATCH 06/12] specs: Update environment variables list
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/environment.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/specs/environment.md b/specs/environment.md
index b7a21b9..02823ec 100644
--- a/specs/environment.md
+++ b/specs/environment.md
@@ -5,6 +5,9 @@ the user's environment and to turn some advanced features on and off.
 # Common
 LXD\_DIR                        | The LXD data directory
 PATH                            | List of paths to look into when resolving binaries
+http\_proxy                     | Proxy server URL for HTTP
+https\_proxy                    | Proxy server URL for HTTPs
+no\_proxy                       | List of domains that don't require the use of a proxy
 
 # Client environment variable
 Name                            | Description
@@ -17,3 +20,4 @@ Name                            | Description
 :---                            | :----
 LXD\_SECURITY\_APPARMOR         | If set to "false", forces AppArmor off
 LXD\_LXC\_TEMPLATE\_CONFIG      | Path to the LXC template configuration directory
+LXD\_LVM\_LVSIZE                | Size of the default LVM LV (10Gib by default)

From fe875893772f4412eb3b92a60a68d540ee788f6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:51:26 -0400
Subject: [PATCH 07/12] specs: Update SSL spec to match current state
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/lxd-ssl-authentication.md | 28 ++++++++--------------------
 1 file changed, 8 insertions(+), 20 deletions(-)

diff --git a/specs/lxd-ssl-authentication.md b/specs/lxd-ssl-authentication.md
index 4f019dc..f648b8e 100644
--- a/specs/lxd-ssl-authentication.md
+++ b/specs/lxd-ssl-authentication.md
@@ -51,13 +51,13 @@ certificates for all the LXD daemons.
 Those certificates and keys are manually put in place on the various
 machines, replacing the automatically generated ones.
 
-The CA certificate is also added to all lxc clients and LXD daemons.
+The CA certificate is also added to all machines.
 A CRL may also accompany the CA certificate.
 
 In that mode, any connection to a LXD daemon will be done using the
 preseeded CA certificate. If the server certificate isn't signed by the
-CA, or if it has been revoked, the connection will simply fail with no
-way obvious way for the user to bypass this.
+CA, or if it has been revoked, the connection will simply go through the
+normal authentication mechanism.
 
 If the server certificate is valid and signed by the CA, then the
 connection continues without prompting the user for the certificate.
@@ -73,7 +73,7 @@ server and send by the client when adding itself.
 
 A remote add operation should therefore go like this:
  1. Call GET /1.0
- 2. If we're not in a PKI setup with a ca.crt, ask the user to confirm the fingerprint.
+ 2. If we're not in a PKI setup ask the user to confirm the fingerprint.
  3. Look at the dict we received back from the server. If "auth" is
     "untrusted", ask the user for the server's password and do a POST to
     /1.0/certificates, then call /1.0 again to check that we're indeed
@@ -91,16 +91,10 @@ In such cases the client will refuse to connect to the server since the
 certificate fringerprint will not match that in the config for this
 remote.
 
-This is a fatal error and so the client shouldn't attempt to recover
-from it. Instead it must print a message to the console saying that the
-server certificate changed and that this may either be due to the server
-having been reinstalled or because the communication is being
-intercepted.
-
-That message can also tell the user that if this is expected, they can
-resolve the situation by removing the remote and adding it again (the
-message should include the two commands required to achieve that in a
-copy/pastable manner).
+It is then up to the user to contact the server administrator to check
+if the certificate did in fact change. If it did, then the certificate
+can be replaced by the new one or the remote be removed altogether and
+re-added.
 
 
 ## Server trust relationship revoked
@@ -110,9 +104,3 @@ trusted.
 
 This happens if another trusted client or the local server administrator
 removed the trust entry on the server.
-
-As with the other failure scenario, this is a fatal error. A message
-must be displayed to the user explaining that this client isn't trusted
-by the server and that to re-establish the trust relationship, the user
-must remove the remote and add it again (and as above, provide the
-commands to do so).

From 6c581bbd365b57b1e0bb7ae60a0aeeb86349ba6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:52:16 -0400
Subject: [PATCH 08/12] specs: Re-format the migration document
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/migration.md | 45 ++++++++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/specs/migration.md b/specs/migration.md
index 5e75c4b..7dfe8d9 100644
--- a/specs/migration.md
+++ b/specs/migration.md
@@ -7,34 +7,41 @@ container, and a "sink", the host that's getting the container. Currently,
 in the 'pull' mode, the source sets up an operation, and the sink connects
 to the source and pulls the container.
 
-There are three websockets (channels) used in migration: 1. the control stream,
-2. the criu images stream, and 3. the filesystem stream. When a migration is
-initiated, information about the container, its configuration, etc. are sent
-over the control channel (a full description of this process is below), the
-criu images and container filesystem are synced over their respective channels,
-and the result of the restore operation is sent from the sink to the source
-over the control channel.
+There are three websockets (channels) used in migration:
+  1. the control stream
+  2. the criu images stream
+  3. the filesystem stream
+
+When a migration is initiated, information about the container, its
+configuration, etc. are sent over the control channel (a full
+description of this process is below), the criu images and container
+filesystem are synced over their respective channels, and the result of
+the restore operation is sent from the sink to the source over the
+control channel.
 
 In particular, the protocol that is spoken over the criu channel and filesystem
 channel can vary, depending on what is negotiated over the control socket. For
 example, both the source and the sink's LXD directory is on btrfs, the
 filesystem socket can speak btrfs-send/receive. Additionally, although we do a
 "stop the world" type migration right now, support for criu's p.haul protocol
-will happen over the criu socket.
+will happen over the criu socket at some later time.
 
 ## Control Socket
 
-Once all three websockets are connected between the two endpoints, the source
-sends a MigrationHeader (protobuf description found in
+Once all three websockets are connected between the two endpoints, the
+source sends a MigrationHeader (protobuf description found in
 `/lxd/migration/migrate.proto`). This header contains the container
-configuration which will be added to the new container (TODO: profiles?). There
-are also two fields indicating the filesystem and criu protocol to speak. For
-example, if a server is hosted on a btrfs filesystem, it can indicate that it
+configuration which will be added to the new container.
+
+There are also two fields indicating the filesystem and criu protocol to speak.
+For example, if a server is hosted on a btrfs filesystem, it can indicate that it
 wants to do a `btrfs send` instead of a simple rsync (similarly, it could
 indicate that it wants to speak the p.haul protocol, instead of just rsyncing
-the images over slowly). The sink then examines this message and responds with
-whatever it supports. Continuing our example, if the sink is not on a btrfs
-filesystem, it responds with the lowest common denominator (rsync, in this
-case), and the source is to send the root filesystem using rsync. Similarly
-with the criu connection; if the sink doesn't have support for the p.haul
-protocol (or whatever), we fall back to rsync.
+the images over slowly).
+
+The sink then examines this message and responds with whatever it
+supports. Continuing our example, if the sink is not on a btrfs
+filesystem, it responds with the lowest common denominator (rsync, in
+this case), and the source is to send the root filesystem using rsync.
+Similarly with the criu connection; if the sink doesn't have support for
+the p.haul protocol (or whatever), we fall back to rsync.

From 0f6d132c38df85f8fddbde8d7c9dd318911fd2d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:55:46 -0400
Subject: [PATCH 09/12] specs: Update requirements
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/requirements.md | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/specs/requirements.md b/specs/requirements.md
index 5d78d37..7d840f7 100644
--- a/specs/requirements.md
+++ b/specs/requirements.md
@@ -8,21 +8,21 @@ Both the golang and gccgo compilers are supported.
 The minimum supported kernel version is 3.13.
 
 LXD requires a kernel with support for:
- * Namespaces (pid, net, uts, ipc, mount and user)
- * Control Groups (cpuset, cpuacct, devices, memory and net\_cls)
+ * Namespaces (pid, net, uts, ipc and mount)
  * Seccomp
 
 The following optional features also require extra kernel options:
+ * Namespaces (user and cgroup)
  * AppArmor (including Ubuntu patch for mount mediation)
+ * Control Groups (blkio, cpuset, devices, memory, pids and net\_prio)
  * CRIU (exact details to be found with CRIU upstream)
 
 As well as any other kernel feature required by the LXC version in use.
 
 ## LXC
-LXD requires LXC 1.1.2 or higher with the following build options:
+LXD requires LXC 1.1.5 or higher with the following build options:
  * apparmor (if using LXD's apparmor support)
- * cgmanager
  * seccomp
 
 To run recent version of various distributions, including Ubuntu, LXCFS
-0.8 or higher should also be installed.
+should also be installed.

From 0bbecf600985164696f7a062418a80448106b606 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 17:58:00 -0400
Subject: [PATCH 10/12] specs: Update storage backend spec
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/storage-backends.md | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/specs/storage-backends.md b/specs/storage-backends.md
index 62a089c..4b4ce0e 100644
--- a/specs/storage-backends.md
+++ b/specs/storage-backends.md
@@ -41,17 +41,16 @@ rsync is used to transfer the container content across.
 
 ### LVM
 
- - LXD uses LVM with thinpool support to offer fast, scalable container and image storage.
  - A LVM VG must be created and then storage.lvm\_vg\_name set to point to it.
  - If a thinpool doesn't already exist, one will be created, the name of the thinpool can be set with storage.lvm\_thinpool\_name .
  - Uses LVs for images, then LV snapshots for containers and container snapshots.
- - The filesystem used for the LVs is ext4.
- - LVs are created with a default size of 100GiB.
+ - The filesystem used for the LVs is ext4 (can be configured to use xfs instead).
+ - LVs are created with a default size of 10GiB (can be configured through).
 
 ### ZFS
 
  - LXD can use any zpool or part of a zpool. storage.zfs\_pool\_name must be set to the path to be used.
- - ZFS doesn't have (and shouldn't be) mounted on /var/lib/lxd
+ - ZFS doesn't have to (and shouldn't be) mounted on /var/lib/lxd
  - Uses ZFS filesystems for images, then snapshots and clones to create containers and snapshots.
  - Due to the way copy-on-write works in ZFS, parent filesystems can't
    be removed until all children are gone. As a result, LXD will

From 57eb3855deb0e16ca30ba920d85665752630c656 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 18:00:36 -0400
Subject: [PATCH 11/12] specs: Update userns to match reality
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 specs/userns-idmap.md | 54 ++-------------------------------------------------
 1 file changed, 2 insertions(+), 52 deletions(-)

diff --git a/specs/userns-idmap.md b/specs/userns-idmap.md
index b985a82..a244f65 100644
--- a/specs/userns-idmap.md
+++ b/specs/userns-idmap.md
@@ -1,5 +1,4 @@
 # Introduction
-
 LXD runs safe containers. This is achieved mostly through the use of
 user namespaces which make it possible to run containers unprivileged,
 greatly limiting the attack surface.
@@ -45,55 +44,6 @@ on a host using an old version of shadow. In this mode, LXD will assume
 it can use any uids and gids above 65535 and will take the first 65536
 as its default map.
 
-# Multiple allocations
-There are a few reasons why you wouldn't want a single allocation for
-all of your containers:
- * ulimits (a container couldn't exhaust a ulimit and affect all others)
- * in the unlikely event where someone breaks out of a container, they
-   can then enter any of the others running with the same map. 
-
-And there's at least one reason why you'd want a shared allocation:
- * shared filesystems
-
-As a result, the plan is for the default profile to come with a 65536
-uid/gid allocation which will be used by all container running with the
-default profile.
-
-If you need to completely separate users, you can then create one
-profile per user and assign it a different allocation.
-
-# Changing the allocation of a used profile
-When changing the allocation of a profile which is in use, LXD will
-check whether the new allocation is smaller or larger than the previous
-one.
-
-If it's smaller and containers currently use the profile, the change
-will be simply be rejected.
-You'll have to move all the existing containers to different profiles
-before you can do the change.
-
-If the new allocation is of the same size or larger than the current one
-and some of the containers are currently running, the change will be
-rejected and you'll have to first stop all the affected containers
-before re-trying.
-
-Then if no containers are affected, the change will simply be committed,
-otherwise, a uid/gid remap of all affected containers will occur, then
-the change will be saved.
-
 # Varying ranges between hosts
-When migrating a container between host, the size of its current uid/gid
-allocation with its current profile will be checked against that it'll
-get on the remote server.
-
-If the allocation is smaller, the transfer will be aborted and the user
-will need to update the remote profile or switch the container to a
-different profile before attempting the transfer again.
-
-In the other cases, the source host uid and gid range will be compared
-to that of the destination host. If it happens to be identical, then the
-filesystem will be transferred as-is.
-
-Otherwise, the filesystem will be transferred and a uid/gid remap
-operation will then happen to convert all the uids and gids to the right
-range.
+The source map is sent when moving containers between hosts so that they
+can be remapped on the receiving host.

From 3a3c0401f62dabbba5514410cf7ed5833c6d4b19 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Tue, 15 Mar 2016 18:01:11 -0400
Subject: [PATCH 12/12] Move specs/ to doc/
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

As that stuff has been implemented, it's effectively documentation now.

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 doc/architectures.md            |   35 +
 doc/configuration.md            |  302 ++++++++
 doc/daemon-behavior.md          |   35 +
 doc/database.md                 |  300 ++++++++
 doc/dev-lxd.md                  |  103 +++
 doc/environment.md              |   23 +
 doc/image-handling.md           |  130 ++++
 doc/lxd-ssl-authentication.md   |  106 +++
 doc/migration.md                |   47 ++
 doc/requirements.md             |   28 +
 doc/rest-api.md                 | 1546 +++++++++++++++++++++++++++++++++++++++
 doc/storage-backends.md         |   65 ++
 doc/userns-idmap.md             |   49 ++
 specs/architectures.md          |   35 -
 specs/configuration.md          |  302 --------
 specs/daemon-behavior.md        |   35 -
 specs/database.md               |  300 --------
 specs/dev-lxd.md                |  103 ---
 specs/environment.md            |   23 -
 specs/image-handling.md         |  130 ----
 specs/lxd-ssl-authentication.md |  106 ---
 specs/migration.md              |   47 --
 specs/requirements.md           |   28 -
 specs/rest-api.md               | 1546 ---------------------------------------
 specs/storage-backends.md       |   65 --
 specs/userns-idmap.md           |   49 --
 26 files changed, 2769 insertions(+), 2769 deletions(-)
 create mode 100644 doc/architectures.md
 create mode 100644 doc/configuration.md
 create mode 100644 doc/daemon-behavior.md
 create mode 100644 doc/database.md
 create mode 100644 doc/dev-lxd.md
 create mode 100644 doc/environment.md
 create mode 100644 doc/image-handling.md
 create mode 100644 doc/lxd-ssl-authentication.md
 create mode 100644 doc/migration.md
 create mode 100644 doc/requirements.md
 create mode 100644 doc/rest-api.md
 create mode 100644 doc/storage-backends.md
 create mode 100644 doc/userns-idmap.md
 delete mode 100644 specs/architectures.md
 delete mode 100644 specs/configuration.md
 delete mode 100644 specs/daemon-behavior.md
 delete mode 100644 specs/database.md
 delete mode 100644 specs/dev-lxd.md
 delete mode 100644 specs/environment.md
 delete mode 100644 specs/image-handling.md
 delete mode 100644 specs/lxd-ssl-authentication.md
 delete mode 100644 specs/migration.md
 delete mode 100644 specs/requirements.md
 delete mode 100644 specs/rest-api.md
 delete mode 100644 specs/storage-backends.md
 delete mode 100644 specs/userns-idmap.md

diff --git a/doc/architectures.md b/doc/architectures.md
new file mode 100644
index 0000000..30af23c
--- /dev/null
+++ b/doc/architectures.md
@@ -0,0 +1,35 @@
+# Introduction
+LXD just like LXC can run on just about any architecture that's
+supported by the Linux kernel and by Go.
+
+Some objects in LXD are tied to an architecture, like the container,
+container snapshots and images.
+
+This document lists all the supported architectures, their unique
+identifier (used in the database), how they should be named and some
+notes.
+
+
+Please note that what LXD cares about is the kernel architecture, not
+the particular userspace flavor as determined by the toolchain.
+
+That means that LXD considers armv7 hard-float to be the same as armv7
+soft-float and refers to both as "armv7". If useful to the user, the
+exact userspace ABI may be set as an image and container property,
+allowing easy query.
+
+# Architectures
+
+ID    | Name          | Notes                           | Personalities
+:---  | :---          | :----                           | :------------
+1     | i686          | 32bit Intel x86                 |
+2     | x86\_64       | 64bit Intel x86                 | x86
+3     | armv7l        | 32bit ARMv7 little-endian       |
+4     | aarch64       | 64bit ARMv8 little-endian       | armv7 (optional)
+5     | ppc           | 32bit PowerPC big-endian        |
+6     | ppc64         | 64bit PowerPC big-endian        | powerpc
+7     | ppc64le       | 64bit PowerPC little-endian     |
+8     | s390x         | 64bit ESA/390 big-endian        |
+
+The architecture names above are typically aligned with the Linux kernel
+architecture names.
diff --git a/doc/configuration.md b/doc/configuration.md
new file mode 100644
index 0000000..7ad2d02
--- /dev/null
+++ b/doc/configuration.md
@@ -0,0 +1,302 @@
+# Introduction
+Current LXD stores the following kind of configurations:
+ - Server configuration (the LXD daemon itself)
+ - Container configuration
+
+The server configuration is a simple set of key and values.
+
+The container configuration is a bit more complex as it uses both
+key/value configuration and some more complex configuration structures
+for devices, network interfaces and storage volumes.
+
+# Server configuration
+## Key/value configuration
+The key/value configuration is namespaced with the following namespaces
+currently supported:
+ - core (core daemon configuration)
+ - images (image configuration)
+ - storage (storage configuration)
+
+Key                             | Type          | Default                   | Description
+:--                             | :---          | :------                   | :----------
+core.https\_address             | string        | -                         | Address to bind for the remote API
+core.https\_allowed\_origin     | string        | -                         | Access-Control-Allow-Origin http header value
+core.https\_allowed\_methods    | string        | -                         | Access-Control-Allow-Methods http header value
+core.https\_allowed\_headers    | string        | -                         | Access-Control-Allow-Headers http header value
+core.proxy\_https               | string        | -                         | https proxy to use, if any (falls back to HTTPS_PROXY environment variable)
+core.proxy\_http                | string        | -                         | http proxy to use, if any (falls back to HTTP_PROXY environment variable)
+core.proxy\_ignore\_hosts       | string        | -                         | hosts which don't need the proxy for use (similar format to NO_PROXY, e.g. 1.2.3.4,1.2.3.5, falls back to NO_PROXY environment varialbe)
+core.trust\_password            | string        | -                         | Password to be provided by clients to setup a trust
+storage.lvm\_vg\_name           | string        | -                         | LVM Volume Group name to be used for container and image storage. A default Thin Pool is created using 100% of the free space in the Volume Group, unless `storage.lvm_thinpool_name` is set.
+storage.lvm\_thinpool\_name     | string        | "LXDPool"                 | LVM Thin Pool to use within the Volume Group specified in `storage.lvm_vg_name`, if the default pool parameters are undesirable.
+storage.lvm\_fstype             | string        | ext4                      | Format LV with filesystem, for now it's value can be only ext4 (default) or xfs.
+storage.zfs\_pool\_name         | string        | -                         | ZFS pool name
+images.compression\_algorithm   | string        | gzip                      | Compression algorithm to use for new images (bzip2, gzip, lzma, xz or none)
+images.remote\_cache\_expiry    | integer       | 10                        | Number of days after which an unused cached remote image will be flushed
+images.auto\_update\_interval   | integer       | 6                         | Interval in hours at which to look for update to cached images (0 disables it)
+images.auto\_update\_cached     | boolean       | true                      | Whether to automatically update any image that LXD caches
+
+Those keys can be set using the lxc tool with:
+
+    lxc config set <key> <value>
+
+
+# Container configuration
+## Properties
+The following are direct container properties and can't be part of a profile:
+ - name
+ - architecture
+
+Name is the container name and can only be changed by renaming the container.
+
+## Key/value configuration
+The key/value configuration is namespaced with the following namespaces
+currently supported:
+ - boot (boot related options, timing, dependencies, ...)
+ - environment (environment variables)
+ - limits (resource limits)
+ - raw (raw container configuration overrides)
+ - security (security policies)
+ - user (storage for user properties, searchable)
+ - volatile (used internally by LXD to store settings that are specific to a specific container instance)
+
+The currently supported keys are:
+
+Key                         | Type      | Default       | Live update   | Description
+:--                         | :---      | :------       | :----------   | :----------
+boot.autostart              | boolean   | false         | n/a           | Always start the container when LXD starts
+boot.autostart.delay        | integer   | 0             | n/a           | Number of seconds to wait after the container started before starting the next one
+boot.autostart.priority     | integer   | 0             | n/a           | What order to start the containers in (starting with highest)
+environment.\*              | string    | -             | yes (exec)    | key/value environment variables to export to the container and set on exec
+limits.cpu                  | string    | - (all)       | yes           | Number or range of CPUs to expose to the container
+limits.cpu.allowance        | string    | 100%          | yes           | How much of the CPU can be used. Can be a percentage (e.g. 50%) for a soft limit or hard a chunk of time (25ms/100ms)
+limits.cpu.priority         | integer   | 10 (maximum)  | yes           | CPU scheduling priority compared to other containers sharing the same CPUs (overcommit)
+limits.disk.priority        | integer   | 5 (medium)    | yes           | When under load, how much priority to give to the container's I/O requests
+limits.memory               | string    | - (all)       | yes           | Percentage of the host's memory or fixed value in bytes (supports kB, MB, GB, TB, PB and EB suffixes)
+limits.memory.enforce       | string    | hard          | yes           | If hard, container can't exceed its memory limit. If soft, the container can exceed its memory limit when extra host memory is available.
+limits.memory.swap          | boolean   | true          | yes           | Whether to allow some of the container's memory to be swapped out to disk
+limits.memory.swap.priority | integer   | 10 (maximum)  | yes           | The higher this is set, the least likely the container is to be swapped to disk
+limits.network.priority     | integer   | 0 (minimum)   | yes           | When under load, how much priority to give to the container's network requests
+limits.processes            | integer   | - (max)       | yes           | Maximum number of processes that can run in the container
+linux.kernel\_modules       | string    | -             | yes           | Comma separated list of kernel modules to load before starting the container
+raw.apparmor                | blob      | -             | yes           | Apparmor profile entries to be appended to the generated profile
+raw.lxc                     | blob      | -             | no            | Raw LXC configuration to be appended to the generated one
+security.nesting            | boolean   | false         | yes           | Support running lxd (nested) inside the container
+security.privileged         | boolean   | false         | no            | Runs the container in privileged mode
+user.\*                     | string    | -             | n/a           | Free form user key/value storage (can be used in search)
+
+The following volatile keys are currently internally used by LXD:
+
+Key                         | Type      | Default       | Description
+:--                         | :---      | :------       | :----------
+volatile.\<name\>.hwaddr    | string    | -             | Network device MAC address (when no hwaddr property is set on the device itself)
+volatile.\<name\>.name      | string    | -             | Network device name (when no name propery is set on the device itself)
+volatile.base\_image        | string    | -             | The hash of the image the container was created from, if any.
+volatile.last\_state.idmap  | string    | -             | Serialized container uid/gid map
+volatile.last\_state.power  | string    | -             | Container state as of last host shutdown
+
+
+Additionally, those user keys have become common with images (support isn't guaranteed):
+
+Key                         | Type          | Default           | Description
+:--                         | :---          | :------           | :----------
+user.network\_mode          | string        | dhcp              | One of "dhcp" or "link-local". Used to configure network in supported images.
+user.meta-data              | string        | -                 | Cloud-init meta-data, content is appended to seed value.
+user.user-data              | string        | #!cloud-config    | Cloud-init user-data, content is used as seed value.
+user.vendor-data            | string        | #!cloud-config    | Cloud-init vendor-data, content is used as seed value.
+
+Note that while a type is defined above as a convenience, all values are
+stored as strings and should be exported over the REST API as strings
+(which makes it possible to support any extra values without breaking
+backward compatibility).
+
+Those keys can be set using the lxc tool with:
+
+    lxc config set <container> <key> <value>
+
+Volatile keys can't be set by the user and can only be set directly against a container.
+
+The raw keys allow direct interaction with the backend features that LXD
+itself uses, setting those may very well break LXD in non-obvious ways
+and should whenever possible be avoided.
+
+
+## Devices configuration
+LXD will always provide the container with the basic devices which are
+required for a standard POSIX system to work. These aren't visible in
+container or profile configuration and may not be overriden.
+
+Those includes:
+ - /dev/null (character device)
+ - /dev/zero (character device)
+ - /dev/full (character device)
+ - /dev/console (character device)
+ - /dev/tty (character device)
+ - /dev/random (character device)
+ - /dev/urandom (character device)
+ - lo (network interface)
+
+Anything else has to be defined in the container configuration or in one
+of its profiles. The default profile will typically contain a network
+interface to become eth0 in the container.
+
+To add extra devices to a container, device entries can be added
+directly to a container, or to a profile.
+
+Devices may be added or removed while the container is running.
+
+Every device entry is identified by a unique name. If the same name is
+used in a subsequent profile or in the container's own configuration,
+the whole entry is overriden by the new definition.
+
+Device entries are added through:
+    lxc config device add <container> <name> <type> [key=value]...
+    lxc profile device add <profile> <name> <type> [key=value]...
+
+### Device types
+LXD supports the following device types:
+
+ID (database)   | Name          | Description
+:--             | :--           | :--
+0               | none          | Inheritance blocker
+1               | nic           | Network interface
+2               | disk          | Mountpoint inside the container
+3               | unix-char     | Unix character device
+4               | unix-block    | Unix block device
+
+### Type: none
+A none type device doesn't have any property and doesn't create anything inside the container.
+
+It's only purpose it to stop inheritance of devices coming from profiles.
+
+To do so, just add a none type device with the same name of the one you wish to skip inheriting.
+It can be added in a profile being applied after the profile it originated from or directly on the container.
+
+### Type: nic
+LXD supports different kind of network devices:
+ - physical: Straight physical device passthrough from the host. The targeted device will vanish from the host and appear in the container.
+ - bridged: Uses an existing bridge on the host and creates a virtual device pair to connect the host bridge to the container.
+ - macvlan: Sets up a new network device based on an existing one but using a different MAC address.
+ - p2p: Creates a virtual device pair, putting one side in the container and leaving the other side on the host.
+
+Different network interface types have different additional properties, the current list is:
+
+Key             | Type      | Default           | Required  | Used by                       | Description
+:--             | :--       | :--               | :--       | :--                           | :--
+nictype         | string    | -                 | yes       | all                           | The device type, one of "physical", "bridged", "macvlan" or "p2p"
+limits.ingress  | string    | -                 | no        | bridged, p2p                  | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes)
+limits.egress   | string    | -                 | no        | bridged, p2p                  | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes)
+limits.max      | string    | -                 | no        | bridged, p2p                  | Same as modifying both limits.read and limits.write
+name            | string    | kernel assigned   | no        | all                           | The name of the interface inside the container
+host\_name      | string    | randomly assigned | no        | bridged, p2p, macvlan         | The name of the interface inside the host
+hwaddr          | string    | randomly assigned | no        | all                           | The MAC address of the new interface
+mtu             | integer   | parent MTU        | no        | all                           | The MTU of the new interface
+parent          | string    | -                 | yes       | physical, bridged, macvlan    | The name of the host device or bridge
+
+### Type: disk
+Disk entries are essentially mountpoints inside the container. They can
+either be a bind-mount of an existing file or directory on the host, or
+if the source is a block device, a regular mount.
+
+The following properties exist:
+
+Key             | Type      | Default           | Required  | Description
+:--             | :--       | :--               | :--       | :--
+limits.read     | string    | -                 | no        | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops")
+limits.write    | string    | -                 | no        | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops")
+limits.max      | string    | -                 | no        | Same as modifying both limits.read and limits.write
+path            | string    | -                 | yes       | Path inside the container where the disk will be mounted
+source          | string    | -                 | yes       | Path on the host, either to a file/directory or to a block device
+optional        | boolean   | false             | no        | Controls whether to fail if the source doesn't exist
+readonly        | boolean   | false             | no        | Controls whether to make the mount read-only
+size            | string    | -                 | no        | Disk size in bytes (supports kB, MB, GB, TB, PB and EB suffixes). This is only supported for the rootfs (/).
+recursive       | boolean   | false             | no        | Whether or not to recursively mount the source path
+
+If multiple disks, backed by the same block device, have I/O limits set,
+the average of the limits will be used.
+
+### Type: unix-char
+Unix character device entries simply make the requested character device
+appear in the container's /dev and allow read/write operations to it.
+
+The following properties exist:
+
+Key         | Type      | Default           | Required  | Description
+:--         | :--       | :--               | :--       | :--
+path        | string    | -                 | yes       | Path inside the container
+major       | int       | device on host    | no        | Device major number
+minor       | int       | device on host    | no        | Device minor number
+uid         | int       | 0                 | no        | UID of the device owner in the container
+gid         | int       | 0                 | no        | GID of the device owner in the container
+mode        | int       | 0660              | no        | Mode of the device in the container
+
+### Type: unix-block
+Unix block device entries simply make the requested character device
+appear in the container's /dev and allow read/write operations to it.
+
+The following properties exist:
+
+Key         | Type      | Default           | Required  | Description
+:--         | :--       | :--               | :--       | :--
+path        | string    | -                 | yes       | Path inside the container
+major       | int       | device on host    | no        | Device major number
+minor       | int       | device on host    | no        | Device minor number
+uid         | int       | 0                 | no        | UID of the device owner in the container
+gid         | int       | 0                 | no        | GID of the device owner in the container
+mode        | int       | 0660              | no        | Mode of the device in the container
+
+## Profiles
+Profiles can store any configuration that a container can (key/value or devices)
+and any number of profiles can be applied to a container.
+
+Profiles are applied in the order they are specified so the last profile
+to specify a specific key wins.
+
+In any case, resource-specific configuration always overrides that
+coming from the profiles.
+
+
+If not present, LXD will create a "default" profile which comes with a
+network interface connected to LXD's default bridge (lxcbr0).
+
+The "default" profile is set for any new container created which doesn't
+specify a different profiles list.
+
+## JSON representation
+A representation of a container using all the different types of
+configurations would look like:
+
+    {
+        'name': "my-container",
+        'profiles': ["default"],
+        'architecture': 'x86_64',
+        'config': {
+            'limits.cpu': '3',
+            'security.privileged': 'true'
+        },
+        'devices': {
+            'nic-lxcbr0': {
+                'type': 'none'
+            },
+            'nic-mybr0': {
+                'type': 'nic',
+                'mtu': '9000',
+                'parent': 'mybr0'
+            },
+            'rootfs': {
+                'type': 'disk',
+                'path': '/',
+                'source': 'UUID=8f7fdf5e-dc60-4524-b9fe-634f82ac2fb6'
+            },
+        },
+        'status': {
+                    'status': "Running",
+                    'status_code': 103,
+                    'ips': [{'interface': "eth0",
+                             'protocol': "INET6",
+                             'address': "2001:470:b368:1020:1::2"},
+                            {'interface': "eth0",
+                             'protocol': "INET",
+                             'address': "172.16.15.30"}]}
+    }
+
diff --git a/doc/daemon-behavior.md b/doc/daemon-behavior.md
new file mode 100644
index 0000000..56f5bd2
--- /dev/null
+++ b/doc/daemon-behavior.md
@@ -0,0 +1,35 @@
+# Introduction
+
+This specification covers some of the daemon's behavior, such as
+reaction to given signals, crashes, ...
+
+# Startup
+On every start, LXD checks that its directory structure exists. If it
+doesn't, it'll create the required directories, generate a keypair and
+initialize the database.
+
+Once the daemon is ready for work, LXD will scan the containers table
+for any container for which the stored power state differs from the
+current one. If a container's power state was recorded as running and the
+container isn't running, LXD will start it.
+
+# Signal handling
+## SIGINT, SIGQUIT, SIGTERM
+For those signals, LXD assumes that it's being temporarily stopped and
+will be restarted at a later time to continue handling the containers.
+
+The containers will keep running and LXD will close all connections and
+exit cleanly.
+
+## SIGPWR
+Indicates to LXD that the host is going down.
+
+LXD will attempt a clean shutdown of all the containers. After 30s, it
+will kill any remaining container.
+
+The container power\_state in the containers table is kept as it was so
+that LXD after the host is done rebooting can restore the containers as
+they were.
+
+## SIGUSR1
+Write a memory profile dump to the file specified with \-\-memprofile.
diff --git a/doc/database.md b/doc/database.md
new file mode 100644
index 0000000..fd7de4f
--- /dev/null
+++ b/doc/database.md
@@ -0,0 +1,300 @@
+# Introduction
+So first of all, why a database?
+
+Rather than keeping the configuration and state within each container's
+directory as is traditionally done by LXC, LXD has an internal database
+which stores all of that information. This allows very quick queries
+against all containers configuration.
+
+
+An example is the rather obvious question "what containers are using br0?".
+To answer that question without a database, LXD would have to iterate
+through every single container, load and parse its configuration and
+then look at what network devices are defined in there.
+
+While that may be quick with a few containers, imagine how many
+filesystem access would be required for 2000 containers. Instead with a
+database, it's only a matter of accessing the already cached database
+with a pretty simple query.
+
+
+# Database engine
+As this is a purely internal database with a single client and very
+little data, we'll be using sqlite3.
+
+We have no interest in replication or other HA features offered by the
+bigger database engines as LXD runs on each compute nodes and having the
+database accessible when the compute node itself isn't, wouldn't be
+terribly useful.
+
+
+# Design
+The design of the database is made to be as close as possible to the REST API.
+
+The main table and field names are exact match for the REST API.
+
+However this database isn't an exact match of the API, mostly because
+any runtime or external piece of information will not be stored in the
+database (as this would require constent polling and wouldn't gain us
+anything).
+
+We make no guarantee of stability for the database schema. This is a
+purely internal database which only LXD should ever use. Updating LXD
+may cause a schema update and data being shuffled. In those cases, LXD
+will make a copy of the old database as ".old" to allow for a revert.
+
+
+# Tables
+The list of tables is:
+
+ * certificates
+ * config
+ * containers
+ * containers\_config
+ * containers\_devices
+ * containers\_devices\_config
+ * containers\_profiles
+ * images
+ * images\_properties
+ * images\_aliases
+ * images\_source
+ * profiles
+ * profiles\_config
+ * profiles\_devices
+ * profiles\_devices\_config
+ * schema
+
+You'll notice that compared to the REST API, there are three main differences:
+
+ 1. The extra "\*\_config" tables which are there for key/value config storage.
+ 2. The extra "images\_properties" table which is there for key/value property storage.
+ 3. The extra "schema" table whish is used for database schema version tracking.
+ 4. There is no "snapshots" table. That's because snapshots are a copy
+    of a container at a given point in time, including its configuration and
+    on-disk state. So having snapshots in a separate table would only be needless duplication.
+
+# Notes on sqlite3
+sqlite3 only supports 5 storage classes: NULL, INTEGER, REAL, TEXT and BLOB
+There are then a set of aliases for each of those storage classes which is what we use below.
+
+# Schema
+## certificates
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+fingerprint     | VARCHAR(255)  | -             | NOT NULL          | HEX encoded certificate fingerprint
+type            | INTEGER       | -             | NOT NULL          | Certificate type (0 = client)
+name            | VARCHAR(255)  | -             | NOT NULL          | Certificate name (defaults to CN)
+certificate     | TEXT          | -             | NOT NULL          | PEM encoded certificate
+
+Index: UNIQUE ON id AND fingerprint
+
+
+## config (server configuration)
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
+value           | TEXT          | -             |                   | Configuration value (NULL for unset)
+
+Index: UNIQUE ON id AND key
+
+
+## containers
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+name            | VARCHAR(255)  | -             | NOT NULL          | Container name
+architecture    | INTEGER       | -             | NOT NULL          | Container architecture
+type            | INTEGER       | 0             | NOT NULL          | Container type (0 = container, 1 = container snapshot)
+ephemeral       | INTEGER       | 0             | NOT NULL          | Whether the container is ephemeral (0 = persistent, 1 = ephemeral)
+stateful        | INTEGER       | 0             | NOT NULL          | Whether the snapshot contains state (snapshot only)
+creation\_date  | DATETIME      | -             |                   | Image creation date (user supplied, 0 = unknown)
+
+Index: UNIQUE ON id AND name
+
+
+## containers\_config
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
+key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
+value           | TEXT          | -             |                   | Configuration value (NULL for unset)
+
+Index: UNIQUE ON id AND container\_id + key
+
+Foreign keys: container\_id REFERENCES containers(id)
+
+
+## containers\_devices
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
+name            | VARCHAR(255)  | -             | NOT NULL          | Container name
+type            | INTEGER       | 0             | NOT NULL          | Device type (see configuration.md)
+
+Index: UNIQUE ON id AND container\_id + name
+
+Foreign keys: container\_id REFERENCES containers(id)
+
+
+## containers\_devices\_config
+
+Column                  | Type          | Default       | Constraint        | Description
+:-----                  | :---          | :------       | :---------        | :----------
+id                      | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+container\_device\_id   | INTEGER       | -             | NOT NULL          | containers\_devices.id FK
+key                     | VARCHAR(255)  | -             | NOT NULL          | Configuration key
+value                   | TEXT          | -             |                   | Configuration value (NULL for unset)
+
+Index: UNIQUE ON id AND container\_device\_id + key
+
+Foreign keys: container\_device\_id REFERENCES containers\_devices(id)
+
+
+## containers\_profiles
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
+profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
+apply\_order    | INTEGER       | 0             | NOT NULL          | Profile ordering
+
+Index: UNIQUE ON id AND container\_id + profile\_id
+
+Foreign keys: container\_id REFERENCES containers(id) and profile\_id REFERENCES profiles(id)
+
+
+## images
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+cached          | INTEGER       | 0             | NOT NULL          | Whether this is a cached image
+fingerprint     | VARCHAR(255)  | -             | NOT NULL          | Tarball fingerprint
+filename        | VARCHAR(255)  | -             | NOT NULL          | Tarball filename
+size            | INTEGER       | -             | NOT NULL          | Tarball size
+public          | INTEGER       | 0             | NOT NULL          | Whether the image is public or not
+auto\_update    | INTEGER       | 0             | NOT NULL          | Whether to update from the source of this image
+architecture    | INTEGER       | -             | NOT NULL          | Image architecture
+creation\_date  | DATETIME      | -             |                   | Image creation date (user supplied, 0 = unknown)
+expiry\_date    | DATETIME      | -             |                   | Image expiry (user supplied, 0 = never)
+upload\_date    | DATETIME      | -             | NOT NULL          | Image entry creation date
+last\_use\_date | DATETIME      | -             |                   | Last time the image was used to spawn a container
+
+Index: UNIQUE ON id AND fingerprint
+
+
+## images\_aliases
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+name            | VARCHAR(255)  | -             | NOT NULL          | Alias name
+image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
+description     | VARCHAR(255)  | -             |                   | Description of the alias
+
+Index: UNIQUE ON id AND name
+
+Foreign keys: image\_id REFERENCES images(id)
+
+
+## images\_properties
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
+type            | INTEGER       | 0             | NOT NULL          | Property type (0 = string, 1 = text)
+key             | VARCHAR(255)  | -             | NOT NULL          | Property name
+value           | TEXT          | -             |                   | Property value (NULL for unset)
+
+Index: UNIQUE ON id
+
+Foreign keys: image\_id REFERENCES images(id)
+
+## images\_source
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
+server          | TEXT          | -             | NOT NULL          | Server URL
+protocol        | INTEGER       | 0             | NOT NULL          | Protocol to access the remote (0 = lxd, 1 = direct, 2 = simplestreams)
+alias           | VARCHAR(255)  | -             | NOT NULL          | What remote alias to use as the source
+certificate     | TEXT          | -             |                   | PEM encoded certificate of the server
+
+Index: UNIQUE ON id
+
+Foreign keys: image\_id REFERENCES images(id)
+
+## profiles
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+name            | VARCHAR(255)  | -             | NOT NULL          | Profile name
+description     | TEXT          | -             |                   | Description of the profile
+
+Index: UNIQUE on id AND name
+
+
+## profiles\_config
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
+key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
+value           | VARCHAR(255)  | -             |                   | Configuration value (NULL for unset)
+
+Index: UNIQUE ON id AND profile\_id + key
+
+Foreign keys: profile\_id REFERENCES profiles(id)
+
+
+## profiles\_devices
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
+name            | VARCHAR(255)  | -             | NOT NULL          | Container name
+type            | INTEGER       | 0             | NOT NULL          | Device type (see configuration.md)
+
+Index: UNIQUE ON id AND profile\_id + name
+
+Foreign keys: profile\_id REFERENCES profiles(id)
+
+
+## profiles\_devices\_config
+
+Column                  | Type          | Default       | Constraint        | Description
+:-----                  | :---          | :------       | :---------        | :----------
+id                      | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+profile\_device\_id     | INTEGER       | -             | NOT NULL          | profiles\_devices.id FK
+key                     | VARCHAR(255)  | -             | NOT NULL          | Configuration key
+value                   | TEXT          | -             |                   | Configuration value (NULL for unset)
+
+Index: UNIQUE ON id AND profile\_device\_id + key
+
+Foreign keys: profile\_device\_id REFERENCES profiles\_devices(id)
+
+
+## schema
+
+Column          | Type          | Default       | Constraint        | Description
+:-----          | :---          | :------       | :---------        | :----------
+id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
+version         | INTEGER       | -             | NOT NULL          | Schema version
+updated\_at     | DATETIME      | -             | NOT NULL          | When the schema update was done
+
+Index: UNIQUE ON id AND version
diff --git a/doc/dev-lxd.md b/doc/dev-lxd.md
new file mode 100644
index 0000000..be5b398
--- /dev/null
+++ b/doc/dev-lxd.md
@@ -0,0 +1,103 @@
+# Introduction
+Communication between the hosted workload (container) and its host while
+not strictly needed is a pretty useful feature.
+
+In LXD, this feature is implemented through a /dev/lxd/sock node which is
+created and setup for all LXD containers.
+
+This file is a Unix socket which processes inside the container can
+connect to. It's multi-threaded so multiple clients can be connected at the
+same time.
+
+# Implementation details
+LXD on the host binds /var/lib/lxd/devlxd and starts listening for new
+connections on it.
+
+This socket is then bind-mounted into every single container started by
+LXD at /dev/lxd/sock.
+
+The bind-mount is required so we can exceed 4096 containers, otherwise,
+LXD would have to bind a different socket for every container, quickly
+reaching the FD limit.
+
+# Authentication
+Queries on /dev/lxd/sock will only return information related to the
+requesting container. To figure out where a request comes from, LXD will
+extract the initial socket ucred and compare that to the list of
+containers it manages.
+
+# Protocol
+The protocol on /dev/lxd/sock is plain-text HTTP with JSON messaging, so very
+similar to the local version of the LXD protocol.
+
+Unlike the main LXD API, there is no background operation and no
+authentication support in the /dev/lxd/sock API.
+
+# REST-API
+## API structure
+ * /
+   * /1.0
+     * /1.0/config
+       * /1.0/config/{key}
+     * /1.0/meta-data
+
+## API details
+### /
+#### GET
+ * Description: List of supported APIs
+ * Return: list of supported API endpoint URLs (by default ['/1.0'])
+
+Return value:
+
+    [
+        "/1.0"
+    ]
+
+### /1.0
+#### GET
+ * Description: Information about the 1.0 API
+ * Return: dict
+
+Return value:
+
+    {
+        "api_version": "1.0"
+    }
+
+### /1.0/config
+#### GET
+ * Description: List of configuration keys
+ * Return: list of configuration keys URL
+
+Note that the configuration key names match those in the container
+config, however not all configuration namespaces will be exported to
+/dev/lxd/sock.
+Currently only the user.\* keys are accessible to the container.
+
+At this time, there also aren't any container-writable namespace.
+
+Return value:
+
+    [
+        "/1.0/config/user.a"
+    ]
+
+### /1.0/config/\<KEY\>
+#### GET
+ * Description: Value of that key
+ * Return: Plain-text value
+
+Return value:
+
+    blah
+
+### /1.0/meta-data
+#### GET
+ * Description: Container meta-data compatible with cloud-init
+ * Return: cloud-init meta-data
+
+Return value:
+
+    #cloud-config
+    instance-id: abc
+    local-hostname: abc
diff --git a/doc/environment.md b/doc/environment.md
new file mode 100644
index 0000000..02823ec
--- /dev/null
+++ b/doc/environment.md
@@ -0,0 +1,23 @@
+# Introduction
+The LXD client and daemon respect some environment variables to adapt to
+the user's environment and to turn some advanced features on and off.
+
+# Common
+LXD\_DIR                        | The LXD data directory
+PATH                            | List of paths to look into when resolving binaries
+http\_proxy                     | Proxy server URL for HTTP
+https\_proxy                    | Proxy server URL for HTTPs
+no\_proxy                       | List of domains that don't require the use of a proxy
+
+# Client environment variable
+Name                            | Description
+:---                            | :----
+EDITOR                          | What text editor to use
+VISUAL                          | What text editor to use (if EDITOR isn't set)
+
+# Server environment variable
+Name                            | Description
+:---                            | :----
+LXD\_SECURITY\_APPARMOR         | If set to "false", forces AppArmor off
+LXD\_LXC\_TEMPLATE\_CONFIG      | Path to the LXC template configuration directory
+LXD\_LVM\_LVSIZE                | Size of the default LVM LV (10Gib by default)
diff --git a/doc/image-handling.md b/doc/image-handling.md
new file mode 100644
index 0000000..5a81083
--- /dev/null
+++ b/doc/image-handling.md
@@ -0,0 +1,130 @@
+# Introduction
+LXD uses an image based workflow. It comes with a built-in image store
+where the user or external tools can import images.
+
+Containers are then started from those images.
+
+It's possible to spawn remote containers using local images or local
+containers using remote images. In such cases, the image may be cached
+on the target LXD.
+
+# Caching
+When spawning a container from a remote image, the remote image is
+downloaded into the local image store with the cached bit set. The image
+will be kept locally as a private image until either it's been unused
+(no new container spawned) for the number of days set in
+images.remote\_cache\_expiry or until the image's expiry is reached
+whichever comes first.
+
+LXD keeps track of image usage by updating the last\_used\_at image
+property every time a new container is spawned from the image.
+
+# Auto-update
+LXD can keep images up to date. By default, any image which comes from a
+remote server and was requested through an alias will be automatically
+updated by LXD. This can be changed with images.auto\_update\_cached.
+
+On startup and then every 3 hours (unless images.auto\_update\_interval
+is set), the LXD daemon will go look for more recent version of all the
+images in the store which are marked as auto-update and have a recorded
+source server.
+
+When a new image is found, it is downloaded into the image store, the
+aliases pointing to the old image are moved to the new one and the old
+image is removed from the store.
+
+The user can also request a particular image be kept up to date when
+manually copying an image from a remote server.
+
+# Image format
+LXD currently supports two LXD-specific image formats.
+
+The first is a unified tarball, where a single tarball
+contains both the container rootfs and the needed metadata.
+
+The second is a split model, using two tarballs instead, one containing
+the rootfs, the other containing the metadata.
+
+The former is what's produced by LXD itself and what people should be
+using for LXD-specific images.
+
+The latter is designed to allow for easy image building from existing
+non-LXD rootfs tarballs already available today.
+
+## Unified tarball
+Tarball, can be compressed and contains:
+ - rootfs/
+ - metadata.yaml
+ - templates/ (optional)
+
+In this mode, the image identifier is the SHA-256 of the tarball.
+
+## Split tarballs
+Two (possibly compressed) tarballs. One for metadata, one for the rootfs.
+
+metadata.tar contains:
+ - metadata.yaml
+ - templates/ (optional)
+
+rootfs.tar contains a Linux root filesystem at its root.
+
+In this mode the image identifier is the SHA-256 of the concatenation of
+the metadata and rootfs tarball (in that order).
+
+## Content
+The rootfs directory (or tarball) contains a full file system tree of what will become the container's /.
+
+The templates directory contains pongo2-formatted templates of files inside the container.
+
+metadata.yaml contains information relevant to running the image under
+LXD, at the moment, this contains:
+
+    architecture: x86_64
+    creation_date: 1424284563
+    properties:
+      description: Ubuntu 14.04 LTS Intel 64bit
+      os: Ubuntu
+      release:
+        - trusty
+        - 14.04
+    templates:
+      /etc/hosts:
+        when:
+          - create
+          - rename
+        template: hosts.tpl
+        properties:
+          foo: bar
+      /etc/hostname:
+        when:
+          - start
+        template: hostname.tpl
+      /etc/network/interfaces:
+        when:
+          - create
+        template: interfaces.tpl
+        create_only: true
+
+The architecture and creation\_date fields are mandatory, the properties
+are just a set of default properties for the image. The os, release,
+name and description fields while not mandatory in any way, should be
+pretty common.
+
+For templates, the "when" key can be one or more of:
+ - create (run at the time a new container is created from the image)
+ - copy (run when a container is created from an existing one)
+ - start (run every time the container is started)
+
+The templates will always receive the following context:
+ - trigger: name of the event which triggered the template (string)
+ - path: path of the file being templated (string)
+ - container: key/value map of container properties (name, architecture, privileged and ephemeral) (map[string]string)
+ - config: key/value map of the container's configuration (map[string]string)
+ - devices: key/value map of the devices assigned to this container (map[string]map[string]string)
+ - properties: key/value map of the template properties specified in metadata.yaml (map[string]string)
+
+The "create\_only" key can be set to have LXD only only create missing files but not overwrite an existing file.
+
+As a general rule, you should never template a file which is owned by a
+package or is otherwise expected to be overwritten by normal operation
+of the container.
diff --git a/doc/lxd-ssl-authentication.md b/doc/lxd-ssl-authentication.md
new file mode 100644
index 0000000..f648b8e
--- /dev/null
+++ b/doc/lxd-ssl-authentication.md
@@ -0,0 +1,106 @@
+# Introduction
+Local communications over the UNIX socket happen over a cleartext HTTP
+socket and access is restricted by socket ownership and mode.
+
+Remote communications with the LXD daemon happen using JSON over HTTPS.
+The supported protocol must be TLS1.2 or better.
+All communications must use perfect forward secrecy and ciphers must be
+limited to strong elliptic curve ones (such as ECDHE-RSA or
+ECDHE-ECDSA).
+
+Any generated key should be at least 4096bit RSA and when using
+signatures, only SHA-2 signatures should be trusted.
+
+Since we control both client and server, there is no reason to support
+any backward compatibility to broken protocol or ciphers.
+
+Both the client and the server will generate a keypair the first time
+they're launched. The server will use that for all https connections to
+the LXD socket and the client will use its certificate as a client
+certificate for any client-server communication.
+
+# Adding a remote with a default setup
+In the default setup, when the user adds a new server with "lxc remote
+add", the server will be contacted over HTTPs, its certificate
+downloaded and the fingerprint will be shown to the user.
+
+The user will then be asked to confirm that this is indeed the server's
+fingerprint which they can manually check by connecting to or asking
+someone with access to the server to run the status command and compare
+the fingerprints.
+
+After that, the user must enter the trust password for that server, if
+it matches, the client certificate is added to the server's trust store
+and the client can now connect to the server without having to provide
+any additional credentials.
+
+This is a workflow that's very similar to that of ssh where an initial
+connection to an unknown server triggers a prompt.
+
+A possible extension to that is to support something similar to ssh's
+fingerprint in DNS feature where the certificate fingerprint is added as
+a TXT record, then if the domain is signed by DNSSEC, the client will
+automatically accept the fingerprint if it matches that in the DNS
+record.
+
+# Adding a remote with a PKI based setup
+In the PKI setup, a system administrator is managing a central PKI, that
+PKI then issues client certificates for all the lxc clients and server
+certificates for all the LXD daemons.
+
+Those certificates and keys are manually put in place on the various
+machines, replacing the automatically generated ones.
+
+The CA certificate is also added to all machines.
+A CRL may also accompany the CA certificate.
+
+In that mode, any connection to a LXD daemon will be done using the
+preseeded CA certificate. If the server certificate isn't signed by the
+CA, or if it has been revoked, the connection will simply go through the
+normal authentication mechanism.
+
+If the server certificate is valid and signed by the CA, then the
+connection continues without prompting the user for the certificate.
+
+After that, the user must enter the trust password for that server, if
+it matches, the client certificate is added to the server's trust store
+and the client can now connect to the server without having to provide
+any additional credentials.
+
+# Password prompt
+To establish a new trust relationship, a password must be set on the
+server and send by the client when adding itself.
+
+A remote add operation should therefore go like this:
+ 1. Call GET /1.0
+ 2. If we're not in a PKI setup ask the user to confirm the fingerprint.
+ 3. Look at the dict we received back from the server. If "auth" is
+    "untrusted", ask the user for the server's password and do a POST to
+    /1.0/certificates, then call /1.0 again to check that we're indeed
+    trusted.
+ 4. Remote is now ready
+
+# Failure scenarios
+## Server certificate changes
+This will typically happen in two cases:
+
+ * The server was fully reinstalled and so changed certificate
+ * The connection is being intercepted (MITM)
+
+In such cases the client will refuse to connect to the server since the
+certificate fringerprint will not match that in the config for this
+remote.
+
+It is then up to the user to contact the server administrator to check
+if the certificate did in fact change. If it did, then the certificate
+can be replaced by the new one or the remote be removed altogether and
+re-added.
+
+
+## Server trust relationship revoked
+In this case, the server still uses the same certificate but all API
+calls return a 403 with an error indicating that the client isn't
+trusted.
+
+This happens if another trusted client or the local server administrator
+removed the trust entry on the server.
diff --git a/doc/migration.md b/doc/migration.md
new file mode 100644
index 0000000..7dfe8d9
--- /dev/null
+++ b/doc/migration.md
@@ -0,0 +1,47 @@
+# Live Migration in LXD
+
+## Overview
+
+Migration has two pieces, a "source", that is, the host that already has the
+container, and a "sink", the host that's getting the container. Currently,
+in the 'pull' mode, the source sets up an operation, and the sink connects
+to the source and pulls the container.
+
+There are three websockets (channels) used in migration:
+  1. the control stream
+  2. the criu images stream
+  3. the filesystem stream
+
+When a migration is initiated, information about the container, its
+configuration, etc. are sent over the control channel (a full
+description of this process is below), the criu images and container
+filesystem are synced over their respective channels, and the result of
+the restore operation is sent from the sink to the source over the
+control channel.
+
+In particular, the protocol that is spoken over the criu channel and filesystem
+channel can vary, depending on what is negotiated over the control socket. For
+example, both the source and the sink's LXD directory is on btrfs, the
+filesystem socket can speak btrfs-send/receive. Additionally, although we do a
+"stop the world" type migration right now, support for criu's p.haul protocol
+will happen over the criu socket at some later time.
+
+## Control Socket
+
+Once all three websockets are connected between the two endpoints, the
+source sends a MigrationHeader (protobuf description found in
+`/lxd/migration/migrate.proto`). This header contains the container
+configuration which will be added to the new container.
+
+There are also two fields indicating the filesystem and criu protocol to speak.
+For example, if a server is hosted on a btrfs filesystem, it can indicate that it
+wants to do a `btrfs send` instead of a simple rsync (similarly, it could
+indicate that it wants to speak the p.haul protocol, instead of just rsyncing
+the images over slowly).
+
+The sink then examines this message and responds with whatever it
+supports. Continuing our example, if the sink is not on a btrfs
+filesystem, it responds with the lowest common denominator (rsync, in
+this case), and the source is to send the root filesystem using rsync.
+Similarly with the criu connection; if the sink doesn't have support for
+the p.haul protocol (or whatever), we fall back to rsync.
diff --git a/doc/requirements.md b/doc/requirements.md
new file mode 100644
index 0000000..7d840f7
--- /dev/null
+++ b/doc/requirements.md
@@ -0,0 +1,28 @@
+# Requirements
+## Go
+
+LXD requires Go 1.5 or higher.
+Both the golang and gccgo compilers are supported.
+
+## Kernel requirements
+The minimum supported kernel version is 3.13.
+
+LXD requires a kernel with support for:
+ * Namespaces (pid, net, uts, ipc and mount)
+ * Seccomp
+
+The following optional features also require extra kernel options:
+ * Namespaces (user and cgroup)
+ * AppArmor (including Ubuntu patch for mount mediation)
+ * Control Groups (blkio, cpuset, devices, memory, pids and net\_prio)
+ * CRIU (exact details to be found with CRIU upstream)
+
+As well as any other kernel feature required by the LXC version in use.
+
+## LXC
+LXD requires LXC 1.1.5 or higher with the following build options:
+ * apparmor (if using LXD's apparmor support)
+ * seccomp
+
+To run recent version of various distributions, including Ubuntu, LXCFS
+should also be installed.
diff --git a/doc/rest-api.md b/doc/rest-api.md
new file mode 100644
index 0000000..96a3429
--- /dev/null
+++ b/doc/rest-api.md
@@ -0,0 +1,1546 @@
+# Introduction
+All the communications between LXD and its clients happen using a
+RESTful API over http which is then encapsulated over either SSL for
+remote operations or a unix socket for local operations.
+
+Not all of the REST interface requires authentication:
+
+ * GET to / is allowed for everyone (lists the API endpoints)
+ * GET to /1.0 is allowed for everyone (but result varies)
+ * POST to /1.0/certificates is allowed for everyone with a client certificate
+ * GET to /1.0/images/\* is allowed for everyone but only returns public images for unauthenticated users
+
+Unauthenticated endpoints are clearly identified as such below.
+
+# API versioning
+The list of supported major API versions can be retrieved using GET /.
+
+The reason for a major API bump is if the API breaks backward compatibility.
+
+Feature additions done without breaking backward compatibility only
+result in addition to api\_extensions which can be used by the client
+to check if a given feature is supported by the server.
+
+# Return values
+There are three standard return types:
+ * Standard return value
+ * Background operation
+ * Error
+
+### Standard return value
+For a standard synchronous operation, the following dict is returned:
+
+    {
+        "type": "sync",
+        "status": "Success",
+        "status_code": 200,
+        "metadata": {}                          # Extra resource/action specific metadata
+    }
+
+HTTP code must be 200.
+
+### Background operation
+When a request results in a background operation, the HTTP code is set to 202 (Accepted)
+and the Location HTTP header is set to the operation URL.
+
+The body is a dict with the following structure:
+
+    {
+        "type": "async",
+        "status": "OK",
+        "status_code": 100,
+        "operation": "/1.0/containers/<id>",                    # URL to the background operation
+        "metadata": {}                                          # Operation metadata (see below)
+    }
+
+The operation metadata structure looks like:
+
+    {
+        "id": "a40f5541-5e98-454f-b3b6-8a51ef5dbd3c",           # UUID of the operation
+        "class": "websocket",                                   # Class of the operation (task, websocket or token)
+        "created_at": "2015-11-17T22:32:02.226176091-05:00",    # When the operation was created
+        "updated_at": "2015-11-17T22:32:02.226176091-05:00",    # Last time the operation was updated
+        "status": "Running",                                    # String version of the operation's status
+        "status_code": 103,                                     # Integer version of the operation's status (use this rather than status)
+        "resources": {                                          # Dictionary of resource types (container, snapshots, images) and affected resources
+          "containers": [
+            "/1.0/containers/test"
+          ]
+        },
+        "metadata": {                                           # Metadata specific to the operation in question (in this case, exec)
+          "fds": {
+            "0": "2a4a97af81529f6608dca31f03a7b7e47acc0b8dc6514496eb25e325f9e4fa6a",
+            "control": "5b64c661ef313b423b5317ba9cb6410e40b705806c28255f601c0ef603f079a7"
+          }
+        },
+        "may_cancel": false,                                    # Whether the operation can be canceled (DELETE over REST)
+        "err": ""                                               # The error string should the operation have failed
+    }
+
+The body is mostly provided as a user friendly way of seeing what's
+going on without having to pull the target operation, all information in
+the body can also be retrieved from the background operation URL.
+
+### Error
+There are various situations in which something may immediately go
+wrong, in those cases, the following return value is used:
+
+    {
+        "type": "error",
+        "error": "Failure",
+        "error_code": 400,
+        "metadata": {}                      # More details about the error
+    }
+
+HTTP code must be one of of 400, 401, 403, 404, 409, 412 or 500.
+
+# Status codes
+The LXD REST API often has to return status information, be that the
+reason for an error, the current state of an operation or the state of
+the various resources it exports.
+
+To make it simple to debug, all of those are always doubled. There is a
+numeric representation of the state which is guaranteed never to change
+and can be relied on by API clients. Then there is a text version meant
+to make it easier for people manually using the API to figure out what's
+happening.
+
+In most cases, those will be called status and status\_code, the former
+being the user-friendly string representation and the latter the fixed
+numeric value.
+
+The codes are always 3 digits, with the following ranges:
+ * 100 to 199: resource state (started, stopped, ready, ...)
+ * 200 to 399: positive action result
+ * 400 to 599: negative action result
+ * 600 to 999: future use
+
+## List of current status codes
+
+Code  | Meaning
+:---  | :------
+100   | Operation created
+101   | Started
+102   | Stopped
+103   | Running
+104   | Cancelling
+105   | Pending
+106   | Starting
+107   | Stopping
+108   | Aborting
+109   | Freezing
+110   | Frozen
+111   | Thawed
+200   | Success
+400   | Failure
+401   | Cancelled
+
+
+# Recursion
+To optimize queries of large lists, recursion is implemented for collections.
+A "recursion" argument can be passed to a GET query against a collection.
+
+The default value is 0 which means that collection member URLs are
+returned. Setting it to 1 will have those URLs be replaced by the object
+they point to (typically a dict).
+
+Recursion is implemented by simply replacing any pointer to an job (URL)
+by the object itself.
+
+# Async operations
+Any operation which may take more than a second to be done must be done
+in the background, returning a background operation ID to the client.
+
+The client will then be able to either poll for a status update or wait
+for a notification using the long-poll API.
+
+# Notifications
+A websocket based API is available for notifications, different notification
+types exist to limit the traffic going to the client.
+
+It's recommended that the client always subscribes to the operations
+notification type before triggering remote operations so that it doesn't
+have to then poll for their status.
+
+# API structure
+ * /
+   * /1.0
+     * /1.0/certificates
+       * /1.0/certificates/\<fingerprint\>
+     * /1.0/containers
+       * /1.0/containers/\<name\>
+         * /1.0/containers/\<name\>/exec
+         * /1.0/containers/\<name\>/files
+         * /1.0/containers/\<name\>/snapshots
+         * /1.0/containers/\<name\>/snapshots/\<name\>
+         * /1.0/containers/\<name\>/state
+         * /1.0/containers/\<name\>/logs
+         * /1.0/containers/\<name\>/logs/\<logfile\>
+     * /1.0/events
+     * /1.0/images
+       * /1.0/images/\<fingerprint\>
+         * /1.0/images/\<fingerprint\>/export
+       * /1.0/images/aliases
+         * /1.0/images/aliases/\<name\>
+     * /1.0/networks
+       * /1.0/networks/\<name\>
+     * /1.0/operations
+       * /1.0/operations/\<uuid\>
+         * /1.0/operations/\<uuid\>/wait
+         * /1.0/operations/\<uuid\>/websocket
+     * /1.0/profiles
+       * /1.0/profiles/\<name\>
+
+# API details
+## /
+### GET
+ * Description: List of supported APIs
+ * Authentication: guest
+ * Operation: sync
+ * Return: list of supported API endpoint URLs
+
+Return value:
+
+    [
+        "/1.0"
+    ]
+
+## /1.0/
+### GET
+ * Description: Server configuration and environment information
+ * Authentication: guest, untrusted or trusted
+ * Operation: sync
+ * Return: Dict representing server state
+
+Return value (if trusted):
+
+    {
+        "api_extensions": [],                           # List of API extensions added after the API was marked stable
+        "api_status": "development",                    # API implementation status (one of, development, stable or deprecated)
+        "api_version": "1.0",                           # The API version as a string
+        "auth": "trusted",                              # Authentication state, one of "guest", "untrusted" or "trusted"
+        "config": {                                     # Host configuration
+            "core.trust_password": true,
+            "core.https_address": "[::]:8443"
+        },
+        "environment": {                                # Various information about the host (OS, kernel, ...)
+            "addresses": [
+                "1.2.3.4:8443",
+                "[1234::1234]:8443"
+            ],
+            "architectures": [
+                "x86_64",
+                "i686"
+            ],
+            "certificate": "PEM certificate",
+            "driver": "lxc",
+            "driver_version": "1.0.6",
+            "kernel": "Linux",
+            "kernel_architecture": "x86_64",
+            "kernel_version": "3.16",
+            "server": "lxd",
+            "server_pid": 10224,
+            "server_version": "0.8.1"}
+            "storage": "btrfs",
+            "storage_version": "3.19",
+        },
+        "public": false,                                # Whether the server should be treated as a public (read-only) remote by the client
+    }
+
+Return value (if guest or untrusted):
+
+    {
+        "api_extensions": [],                   # List of API extensions added after the API was marked stable
+        "api_status": "development",            # API implementation status (one of, development, stable or deprecated)
+        "api_version": "1.0",                   # The API version as a string
+        "auth": "guest",                        # Authentication state, one of "guest", "untrusted" or "trusted"
+        "public": false,                        # Whether the server should be treated as a public (read-only) remote by the client
+    }
+
+### PUT
+ * Description: Updates the server configuration or other properties
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (replaces any existing config with the provided one):
+
+    {
+        "config": {
+            "core.trust_password": "my-new-password",
+            "storage.zfs_pool_name": "lxd"
+        }
+    }
+
+## /1.0/certificates
+### GET
+ * Description: list of trusted certificates
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs for trusted certificates
+
+Return:
+
+    [
+        "/1.0/certificates/3ee64be3c3c7d617a7470e14f2d847081ad467c8c26e1caad841c8f67f7c7b09"
+    ]
+
+### POST
+ * Description: add a new trusted certificate
+ * Authentication: trusted or untrusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "type": "client",                       # Certificate type (keyring), currently only client
+        "certificate": "PEM certificate",       # If provided, a valid x509 certificate. If not, the client certificate of the connection will be used
+        "name": "foo"                           # An optional name for the certificate. If nothing is provided, the host in the TLS header for the request is used.
+        "password": "server-trust-password"     # The trust password for that server (only required if untrusted)
+    }
+
+## /1.0/certificates/\<fingerprint\>
+### GET
+ * Description: trusted certificate information
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing a trusted certificate
+
+Output:
+
+    {
+        "type": "client",
+        "certificate": "PEM certificate"
+        "fingerprint": "SHA256 Hash of the raw certificate"
+    }
+
+### DELETE
+ * Description: Remove a trusted certificate
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
+
+## /1.0/containers
+### GET
+ * Description: List of containers
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs for containers this server publishes
+
+Return value:
+
+    [
+        "/1.0/containers/blah",
+        "/1.0/containers/blah1"
+    ]
+
+### POST
+ * Description: Create a new container
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (container based on a local image with the "ubuntu/devel" alias):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
+                   "alias": "ubuntu/devel"},                                # Name of the alias
+    }
+
+Input (container based on a local image identified by its fingerprint):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
+                   "fingerprint": "SHA-256"},                               # Fingerprint
+    }
+
+Input (container based on most recent match based on image properties):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
+                   "properties": {                                          # Properties
+                        "os": "ubuntu",
+                        "release": "14.04",
+                        "architecture": "x86_64"
+                    }},
+    }
+
+Input (container without a pre-populated rootfs, useful when attaching to an existing one):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "none"},                                         # Can be: "image", "migration", "copy" or "none"
+    }
+
+Input (using a public remote image):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
+                   "mode": "pull",                                          # One of "local" (default) or "pull"
+                   "server": "https://10.0.2.3:8443",                       # Remote server (pull mode only)
+                   "protocol": "lxd",                                       # Protocol (one of lxd or simplestreams, defaults to lxd)
+                   "certificate": "PEM certificate",                        # Optional PEM certificate. If not mentioned, system CA is used.
+                   "alias": "ubuntu/devel"},                                # Name of the alias
+    }
+
+
+Input (using a private remote image after having obtained a secret for that image):
+
+    {
+        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                            # List of profiles
+        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                      # Config override.
+        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
+                   "mode": "pull",                                          # One of "local" (default) or "pull"
+                   "server": "https://10.0.2.3:8443",                       # Remote server (pull mode only)
+                   "secret": "my-secret-string",                            # Secret to use to retrieve the image (pull mode only)
+                   "certificate": "PEM certificate",                        # Optional PEM certificate. If not mentioned, system CA is used.
+                   "alias": "ubuntu/devel"},                                # Name of the alias
+    }
+
+Input (using a remote container, sent over the migration websocket):
+
+    {
+        "name": "my-new-container",                                                     # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                                        # List of profiles
+        "ephemeral": true,                                                              # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                                  # Config override.
+        "source": {"type": "migration",                                                 # Can be: "image", "migration", "copy" or "none"
+                   "mode": "pull",                                                      # Only "pull" is supported for now
+                   "operation": "https://10.0.2.3:8443/1.0/operations/<UUID>",          # Full URL to the remote operation (pull mode only)
+                   "certificate": "PEM certificate",                                    # Optional PEM certificate. If not mentioned, system CA is used.
+                   "base-image": "<fingerprint>",                                       # Optional, the base image the container was created from
+                   "secrets": {"control": "my-secret-string",                           # Secrets to use when talking to the migration source
+                               "criu":    "my-other-secret",
+                               "fs":      "my third secret"},
+    }
+
+Input (using a local container):
+
+    {
+        "name": "my-new-container",                                                     # 64 chars max, ASCII, no slash, no colon and no comma
+        "architecture": "x86_64",
+        "profiles": ["default"],                                                        # List of profiles
+        "ephemeral": true,                                                              # Whether to destroy the container on shutdown
+        "config": {"limits.cpu": "2"},                                                  # Config override.
+        "source": {"type": "copy",                                                      # Can be: "image", "migration", "copy" or "none"
+                   "source": "my-old-container"}                                        # Name of the source container
+    }
+
+
+## /1.0/containers/\<name\>
+### GET
+ * Description: Container information
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict of the container configuration and current state.
+
+Output:
+
+    {
+        "architecture": "x86_64",
+        "config": {
+            "limits.cpu": "3",
+            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
+            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
+        },
+        "created_at": "2016-02-16T01:05:05Z",
+        "devices": {
+            "rootfs": {
+                "path": "/",
+                "type": "disk"
+            }
+        },
+        "ephemeral": false,
+        "expanded_config": {    # the result of expanding profiles and adding the container's local config
+            "limits.cpu": "3",
+            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
+            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
+        },
+        "expanded_devices": {   # the result of expanding profiles and adding the container's local devices
+            "eth0": {
+                "name": "eth0",
+                "nictype": "bridged",
+                "parent": "lxcbr0",
+                "type": "nic"
+            },
+            "root": {
+                "path": "/",
+                "type": "disk"
+            }
+        },
+        "name": "my-container",
+        "profiles": [
+            "default"
+        ],
+        "stateful": false,      # If true, indicates that the container has some stored state that can be restored on startup
+        "status": "Running",
+        "status_code": 103
+    }
+
+
+### PUT
+ * Description: update container configuration or restore snapshot
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (update container configuration):
+
+    {
+        "architecture": "x86_64",
+        "config": {
+            "limits.cpu": "4",
+            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
+            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
+        },
+        "devices": {
+            "rootfs": {
+                "path": "/",
+                "type": "disk"
+            }
+        },
+        "ephemeral": true,
+        "profiles": [
+            "default"
+        ]
+    }
+
+
+Takes the same structure as that returned by GET but doesn't allow name
+changes (see POST below) or changes to the status sub-dict (since that's
+read-only).
+
+Input (restore snapshot):
+
+    {
+        "restore": "snapshot-name"
+    }
+
+### POST
+ * Description: used to rename/migrate the container
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Renaming to an existing name must return the 409 (Conflict) HTTP code.
+
+Input (simple rename):
+
+    {
+        "name": "new-name"
+    }
+
+Input (migration across lxd instances):
+    {
+        "migration": true
+    }
+
+The migration does not actually start until someone (i.e. another lxd instance)
+connects to all the websockets and begins negotiation with the source.
+
+Output in metadata section (for migration):
+
+    {
+        "control": "secret1",       # Migration control socket
+        "criu": "secret2",          # State transfer socket (only if live migrating)
+        "fs": "secret3"             # Filesystem transfer socket
+    }
+
+These are the secrets that should be passed to the create call.
+
+### DELETE
+ * Description: remove the container
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
+
+## /1.0/containers/\<name\>/state
+### GET
+ * Description: current state
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing current state
+
+    {
+        "type": "sync",
+        "status": "Success",
+        "status_code": 200,
+        "metadata": {
+            "status": "Running",
+            "status_code": 103,
+            "disk": {
+                "root": {
+                    "usage": 422330368
+                }
+            },
+            "memory": {
+                "usage": 51126272,
+                "usage_peak": 70246400,
+                "swap_usage": 0,
+                "swap_usage_peak": 0
+            },
+            "network": {
+                "eth0": {
+                    "addresses": [
+                        {
+                            "family": "inet",
+                            "address": "10.0.3.27",
+                            "netmask": "24",
+                            "scope": "global"
+                        },
+                        {
+                            "family": "inet6",
+                            "address": "fe80::216:3eff:feec:65a8",
+                            "netmask": "64",
+                            "scope": "link"
+                        }
+                    ],
+                    "counters": {
+                        "bytes_received": 33942,
+                        "bytes_sent": 30810,
+                        "packets_received": 402,
+                        "packets_sent": 178
+                    },
+                    "hwaddr": "00:16:3e:ec:65:a8",
+                    "host_name": "vethBWTSU5",
+                    "mtu": 1500,
+                    "state": "up",
+                    "type": "broadcast"
+                },
+                "lo": {
+                    "addresses": [
+                        {
+                            "family": "inet",
+                            "address": "127.0.0.1",
+                            "netmask": "8",
+                            "scope": "local"
+                        },
+                        {
+                            "family": "inet6",
+                            "address": "::1",
+                            "netmask": "128",
+                            "scope": "local"
+                        }
+                    ],
+                    "counters": {
+                        "bytes_received": 86816,
+                        "bytes_sent": 86816,
+                        "packets_received": 1226,
+                        "packets_sent": 1226
+                    },
+                    "hwaddr": "",
+                    "host_name": "",
+                    "mtu": 65536,
+                    "state": "up",
+                    "type": "loopback"
+                },
+                "lxcbr0": {
+                    "addresses": [
+                        {
+                            "family": "inet",
+                            "address": "10.0.3.1",
+                            "netmask": "24",
+                            "scope": "global"
+                        },
+                        {
+                            "family": "inet6",
+                            "address": "fe80::68d4:87ff:fe40:7769",
+                            "netmask": "64",
+                            "scope": "link"
+                        }
+                    ],
+                    "counters": {
+                        "bytes_received": 0,
+                        "bytes_sent": 570,
+                        "packets_received": 0,
+                        "packets_sent": 7
+                    },
+                    "hwaddr": "6a:d4:87:40:77:69",
+                    "host_name": "",
+                    "mtu": 1500,
+                    "state": "up",
+                    "type": "broadcast"
+               },
+               "zt0": {
+                    "addresses": [
+                        {
+                            "family": "inet",
+                            "address": "29.17.181.59",
+                            "netmask": "7",
+                            "scope": "global"
+                        },
+                        {
+                            "family": "inet6",
+                            "address": "fd80:56c2:e21c:0:199:9379:e711:b3e1",
+                            "netmask": "88",
+                            "scope": "global"
+                        },
+                        {
+                            "family": "inet6",
+                            "address": "fe80::79:e7ff:fe0d:5123",
+                            "netmask": "64",
+                            "scope": "link"
+                        }
+                    ],
+                    "counters": {
+                        "bytes_received": 0,
+                        "bytes_sent": 806,
+                        "packets_received": 0,
+                        "packets_sent": 9
+                    },
+                    "hwaddr": "02:79:e7:0d:51:23",
+                    "host_name": "",
+                    "mtu": 2800,
+                    "state": "up",
+                    "type": "broadcast"
+                }
+            },
+            "pid": 13663,
+            "processes": 32
+        }
+    }
+
+
+### PUT
+ * Description: change the container state
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input:
+
+    {
+        "action": "stop",       # State change action (stop, start, restart, freeze or unfreeze)
+        "timeout": 30,          # A timeout after which the state change is considered as failed
+        "force": true,          # Force the state change (currently only valid for stop and restart where it means killing the container)
+        "stateful": true        # Whether to store or restore runtime state before stopping or startiong (only valid for stop and start, defaults to false)
+    }
+
+## /1.0/containers/\<name\>/files
+### GET (?path=/path/inside/the/container)
+ * Description: download a file from the container
+ * Authentication: trusted
+ * Operation: sync
+ * Return: Raw file or standard error
+
+The following headers will be set (on top of standard size and mimetype headers):
+ * X-LXD-uid: 0
+ * X-LXD-gid: 0
+ * X-LXD-mode: 0700
+
+This is designed to be easily usable from the command line or even a web
+browser.
+
+### POST (?path=/path/inside/the/container)
+ * Description: upload a file to the container
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+ * Standard http file upload
+
+The following headers may be set by the client:
+ * X-LXD-uid: 0
+ * X-LXD-gid: 0
+ * X-LXD-mode: 0700
+
+This is designed to be easily usable from the command line or even a web
+browser.
+
+## /1.0/containers/\<name\>/snapshots
+### GET
+ * Description: List of snapshots
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs for snapshots for this container
+
+Return value:
+
+    [
+        "/1.0/containers/blah/snapshots/snap0"
+    ]
+
+### POST
+ * Description: create a new snapshot
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input:
+
+    {
+        "name": "my-snapshot",          # Name of the snapshot
+        "stateful": true                # Whether to include state too
+    }
+
+## /1.0/containers/\<name\>/snapshots/\<name\>
+### GET
+ * Description: Snapshot information
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing the snapshot
+
+Return:
+
+    {
+        "architecture": "x86_64",
+        "config": {
+            "security.nesting": "true",
+            "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
+            "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8",
+            "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]",
+        },
+        "created_at": "2016-03-08T23:55:08Z",
+        "devices": {
+            "eth0": {
+                "name": "eth0",
+                "nictype": "bridged",
+                "parent": "lxcbr0",
+                "type": "nic"
+            },
+            "root": {
+                "path": "/",
+                "type": "disk"
+            },
+        },
+        "ephemeral": false,
+        "expanded_config": {
+            "security.nesting": "true",
+            "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
+            "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8",
+            "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]",
+        },
+        "expanded_devices": {
+            "eth0": {
+                "name": "eth0",
+                "nictype": "bridged",
+                "parent": "lxcbr0",
+                "type": "nic"
+            },
+            "root": {
+                "path": "/",
+                "type": "disk"
+            },
+        },
+        "name": "zerotier/blah",
+        "profiles": [
+            "default"
+        ],
+        "stateful": false
+    }
+
+### POST
+ * Description: used to rename/migrate the snapshot
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (rename the snapshot):
+
+    {
+        "name": "new-name"
+    }
+
+Input (setup the migration source):
+
+    {
+        "migration": true,
+    }
+
+Return (with migration=true):
+
+    {
+        "control": "secret1",       # Migration control socket
+        "fs": "secret3"             # Filesystem transfer socket
+    }
+
+Renaming to an existing name must return the 409 (Conflict) HTTP code.
+
+### DELETE
+ * Description: remove the snapshot
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
+
+## /1.0/containers/\<name\>/exec
+### POST
+ * Description: run a remote command
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation + optional websocket information or standard error
+
+Input (run bash):
+
+    {
+        "command": ["/bin/bash"],       # Command and arguments
+        "environment": {},              # Optional extra environment variables to set
+        "wait-for-websocket": false,    # Whether to wait for a connection before starting the process
+        "interactive": true             # Whether to allocate a pts device instead of PIPEs
+    }
+
+`wait-for-websocket` indicates whether the operation should block and wait for
+a websocket connection to start (so that users can pass stdin and read
+stdout), or simply run to completion with /dev/null as stdin and stdout.
+
+If interactive is set to true, a single websocket is returned and is mapped to a
+pts device for stdin, stdout and stderr of the execed process.
+
+If interactive is set to false (default), three pipes will be setup, one
+for each of stdin, stdout and stderr.
+
+Depending on the state of the interactive flag, one or three different
+websocket/secret pairs will be returned, which are valid for connecting to this
+operations /websocket endpoint.
+
+Return (with wait-for-websocket=true and interactive=false):
+
+    {
+        "fds": {
+            "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21",
+            "1": "464dcf9f8fdce29d0d6478284523a9f26f4a31ae365d94cd38bac41558b797cf",
+            "2": "25b70415b686360e3b03131e33d6d94ee85a7f19b0f8d141d6dca5a1fc7b00eb",
+            "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5"
+        }
+    }
+
+Return (with wait-for-websocket=true and interactive=true):
+
+    {
+        "fds": {
+            "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21",
+            "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5"
+        }
+    }
+
+
+When the exec command finishes, its exit status is available from the
+operation's metadata:
+
+    {
+        "return": 0
+    }
+
+## /1.0/containers/\<name\>/logs
+### GET
+* Description: Returns a list of the log files available for this container.
+  Note that this works on containers that have been deleted (or were never
+  created) to enable people to get logs for failed creations.
+* Authentication: trusted
+* Operation: Sync
+* Return: a list of the available log files
+
+Return:
+
+    [
+        "/1.0/containers/blah/logs/forkstart.log",
+        "/1.0/containers/blah/logs/lxc.conf",
+        "/1.0/containers/blah/logs/lxc.log"
+    ]
+
+## /1.0/containers/\<name\>/logs/\<logfile\>
+### GET
+* Description: returns the contents of a particular log file.
+* Authentication: trusted
+* Operation: N/A
+* Return: the contents of the log file
+
+### DELETE
+* Description: delete a particular log file.
+* Authentication: trusted
+* Operation: Sync
+* Return: empty response or standard error
+
+## /1.0/events
+This URL isn't a real REST API endpoint, instead doing a GET query on it
+will upgrade the connection to a websocket on which notifications will
+be sent.
+
+### GET (?type=operation,logging)
+ * Description: websocket upgrade
+ * Authentication: trusted
+ * Operation: sync
+ * Return: none (never ending flow of events)
+
+Supported arguments are:
+ * type: comma separated list of notifications to subscribe to (defaults to all)
+
+The notification types are:
+ * operation (notification about creation, updates and termination of all background operations)
+ * logging (every log entry from the server)
+
+This never returns. Each notification is sent as a separate JSON dict:
+
+    {
+        "timestamp": "2015-06-09T19:07:24.379615253-06:00",                # Current timestamp
+        "type": "operation",                                               # Notification type
+        "metadata": {}                                                     # Extra resource or type specific metadata
+    }
+
+    {
+        "timestamp": "2016-02-17T11:44:28.572721913-05:00",
+        "type": "logging",
+        "metadata": {
+            "context": {
+                "ip": "@",
+                "method": "GET"
+                "url": "/1.0/containers/xen/snapshots",
+            },
+            "level": "info",
+            "message": "handling"
+        }
+    }
+
+
+## /1.0/images
+### GET
+ * Description: list of images (public or private)
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: list of URLs for images this server publishes
+
+Return:
+
+    [
+        "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473",
+        "/1.0/images/97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
+        "/1.0/images/a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
+        "/1.0/images/c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f"
+    ]
+
+### POST
+ * Description: create and publish a new image
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input (one of):
+ * Standard http file upload
+ * Source image dictionary (transfers a remote image)
+ * Source container dictionary (makes an image out of a local container)
+ * Remote image URL dictionary (downloads a remote image)
+
+In the http file upload case, The following headers may be set by the client:
+ * X-LXD-fingerprint: SHA-256 (if set, uploaded file must match)
+ * X-LXD-filename: FILENAME (used for export)
+ * X-LXD-public: true/false (defaults to false)
+ * X-LXD-properties: URL-encoded key value pairs without duplicate keys (optional properties)
+
+In the source image case, the following dict must be used:
+
+    {
+        "filename": filename,                   # Used for export (optional)
+        "public": true,                         # Whether the image can be downloaded by untrusted users (defaults to false
+        "properties": {                         # Image properties (optional, applied on top of source properties)
+            "os": "Ubuntu"
+        },
+        "source": {
+            "type": "image",
+            "mode": "pull",                     # Only pull is supported for now
+            "server": "https://10.0.2.3:8443",  # Remote server (pull mode only)
+            "protocol": "lxd",                  # Protocol (one of lxd or simplestreams, defaults to lxd)
+            "secret": "my-secret-string",       # Secret (pull mode only, private images only)
+            "certificate": "PEM certificate",   # Optional PEM certificate. If not mentioned, system CA is used.
+            "fingerprint": "SHA256",            # Fingerprint of the image (must be set if alias isn't)
+            "alias": "ubuntu/devel",            # Name of the alias (must be set if fingerprint isn't)
+        }
+    }
+
+In the source container case, the following dict must be used:
+
+    {
+        "filename": filename,     # Used for export (optional)
+        "public":   true,         # Whether the image can be downloaded by untrusted users  (defaults to false)
+        "properties": {           # Image properties (optional)
+            "os": "Ubuntu"
+        },
+        "source": {
+            "type": "container",  # One of "container" or "snapshot"
+            "name": "abc"
+        }
+    }
+
+In the remote image URL case, the following dict must be used:
+
+    {
+        "filename": filename,                           # Used for export (optional)
+        "public":   true,                               # Whether the image can be downloaded by untrusted users  (defaults to false)
+        "properties": {                                 # Image properties (optional)
+            "os": "Ubuntu"
+        },
+        "source": {
+            "type": "url",
+            "url": "https://www.some-server.com/image"  # URL for the image
+        }
+    }
+
+
+After the input is received by LXD, a background operation is started
+which will add the image to the store and possibly do some backend
+filesystem-specific optimizations.
+
+## /1.0/images/\<fingerprint\>
+### GET (optional ?secret=SECRET)
+ * Description: Image description and metadata
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: dict representing an image properties
+
+Output:
+
+    {
+        "aliases": [
+            {
+                "name": "trusty",
+                "description": "",
+            }
+        ],
+        "architecture": "x86_64",
+        "auto_update": true,
+        "cached": false,
+        "fingerprint": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473",
+        "filename": "ubuntu-trusty-14.04-amd64-server-20160201.tar.xz",
+        "properties": {
+            "architecture": "x86_64",
+            "description": "Ubuntu 14.04 LTS server (20160201)",
+            "os": "ubuntu",
+            "release": "trusty"
+        },
+        "update_source": {
+            "server": "https://10.1.2.4:8443",
+            "protocol": "lxd",
+            "certificate": "PEM certificate",
+            "alias": "ubuntu/trusty/amd64"
+        },
+        "public": false,
+        "size": 123792592,
+        "created_at": "2016-02-01T21:07:41Z",
+        "expires_at": "1970-01-01T00:00:00Z",
+        "last_used_at": "1970-01-01T00:00:00Z",
+        "uploaded_at": "2016-02-16T00:44:47Z"
+    }
+
+### DELETE
+ * Description: Remove an image
+ * Authentication: trusted
+ * Operation: async
+ * Return: background operaton or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
+
+### PUT
+ * Description: Updates the image properties
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "auto_update": true,
+        "properties": {
+            "architecture": "x86_64",
+            "description": "Ubuntu 14.04 LTS server (20160201)",
+            "os": "ubuntu",
+            "release": "trusty"
+        },
+        "public": true,
+    }
+
+## /1.0/images/\<fingerprint\>/export
+### GET (optional ?secret=SECRET)
+ * Description: Download the image tarball
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: Raw file or standard error
+
+The secret string is required when an untrusted LXD is spawning a new
+container from a private image stored on a different LXD.
+
+Rather than require a trust relationship between the two LXDs, the
+client will POST to /1.0/images/\<fingerprint\>/export to get a secret
+token which it'll then pass to the target LXD. That target LXD will then
+GET the image as a guest, passing the secret token.
+
+
+## /1.0/images/\<fingerprint\>/secret
+### POST
+ * Description: Generate a random token and tell LXD to expect it be used by a guest
+ * Authentication: guest or trusted
+ * Operation: async
+ * Return: background operation or standard error
+
+Input:
+
+    {
+    }
+
+Return:
+
+    {
+        "secret": "52e9ec5885562aa24d05d7b4846ebb8b5f1f7bf5cd6e285639b569d9eaf54c9b"
+    }
+
+Standard backround operation with "secret" set to the generated secret
+string in metadata.
+
+The secret is automatically invalidated 5s after an image URL using it
+has been accessed. This allows to both retried the image information and
+then hit /export with the same secret.
+
+## /1.0/images/aliases
+### GET
+ * Description: list of aliases (public or private based on image visibility)
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: list of URLs for aliases this server knows about
+
+Return:
+
+    [
+        "/1.0/images/aliases/sl6",
+        "/1.0/images/aliases/trusty",
+        "/1.0/images/aliases/xenial"
+    ]
+
+### POST
+ * Description: create a new alias
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "description": "The alias description",
+        "target": "SHA-256",
+        "name": "alias-name"
+    }
+
+## /1.0/images/aliases/\<name\>
+### GET
+ * Description: Alias description and target
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: dict representing an alias description and target
+
+Output:
+    {
+        "name": "test",
+        "description": "my description",
+        "target": "c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f"
+    }
+
+### PUT
+ * Description: Updates the alias target or description
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "description": "New description",
+        "target": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473"
+    }
+
+### POST
+ * Description: rename an alias
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "name": "new-name"
+    }
+
+Renaming to an existing name must return the 409 (Conflict) HTTP code.
+
+### DELETE
+ * Description: Remove an alias
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (none at present):
+
+    {
+    }
+
+## /1.0/networks
+### GET
+ * Description: list of networks
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs for networks that are current defined on the host
+
+    [
+        "/1.0/networks/eth0",,
+        "/1.0/networks/lxcbr0"
+    ]
+
+## /1.0/networks/\<name\>
+### GET
+ * Description: information about a network
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing a network
+
+    {
+        "name": "lxcbr0",
+        "type": "bridge",
+        "used_by": [
+            "/1.0/containers/blah"
+        ]
+    }
+
+## /1.0/operations
+### GET
+ * Description: list of operations
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs for operations that are currently going on/queued
+
+    [
+        "/1.0/operations/c0fc0d0d-a997-462b-842b-f8bd0df82507",
+        "/1.0/operations/092a8755-fd90-4ce4-bf91-9f87d03fd5bc"
+    ]
+
+## /1.0/operations/\<uuid\>
+### GET
+ * Description: background operation
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing a background operation
+
+Return:
+
+    {
+        "id": "b8d84888-1dc2-44fd-b386-7f679e171ba5",
+        "class": "token",                                                                       # One of "task" (background task), "websocket" (set of websockets and crendentials) or "token" (temporary credentials)
+        "created_at": "2016-02-17T16:59:27.237628195-05:00",                                    # Creation timestamp
+        "updated_at": "2016-02-17T16:59:27.237628195-05:00",                                    # Last update timestamp
+        "status": "Running",
+        "status_code": 103,
+        "resources": {                                                                          # List of affected resources
+            "images": [
+                "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473"
+            ]
+        },
+        "metadata": {                                                                           # Extra information about the operation (action, target, ...)
+            "secret": "c9209bee6df99315be1660dd215acde4aec89b8e5336039712fc11008d918b0d"
+        },
+        "may_cancel": true,                                                                     # Whether it's possible to cancel the operation (DELETE)
+        "err": ""
+    }
+
+### DELETE
+ * Description: cancel an operation. Calling this will change the state to "cancelling" rather than actually removing the entry.
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
+
+## /1.0/operations/\<uuid\>/wait
+### GET (optional ?timeout=30)
+ * Description: Wait for an operation to finish
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict of the operation after it's reached its final state
+
+Input (wait indefinitely for a final state): no argument
+
+Input (similar but times out after 30s): ?timeout=30
+
+## /1.0/operations/\<uuid\>/websocket
+### GET (?secret=SECRET)
+ * Description: This connection is upgraded into a websocket connection
+   speaking the protocol defined by the operation type. For example, in the
+   case of an exec operation, the websocket is the bidirectional pipe for
+   stdin/stdout/stderr to flow to and from the process inside the container.
+   In the case of migration, it will be the primary interface over which the
+   migration information is communicated. The secret here is the one that was
+   provided when the operation was created. Guests are allowed to connect
+   provided they have the right secret.
+ * Authentication: guest or trusted
+ * Operation: sync
+ * Return: websocket stream or standard error
+
+## /1.0/profiles
+### GET
+ * Description: List of configuration profiles
+ * Authentication: trusted
+ * Operation: sync
+ * Return: list of URLs to defined profiles
+
+Return:
+
+    [
+        "/1.0/profiles/default"
+    ]
+
+
+### POST
+ * Description: define a new profile
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "name": "my-profilename",
+        "description": "Some description string",
+        "config": {
+            "limits.memory": "2GB"
+        },
+        "devices": {
+            "kvm": {
+                "type": "unix-char",
+                "path": "/dev/kvm"
+            }
+        }
+    }
+
+## /1.0/profiles/\<name\>
+### GET
+ * Description: profile configuration
+ * Authentication: trusted
+ * Operation: sync
+ * Return: dict representing the profile content
+
+Output:
+
+    {
+        "name": "test",
+        "description": "Some description string",
+        "config": {
+            "limits.memory": "2GB"
+        },
+        "devices": {
+            "kvm": {
+                "path": "/dev/kvm",
+                "type": "unix-char"
+            }
+        }
+    }
+
+### PUT
+ * Description: update the profile
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input:
+
+    {
+        "config": {
+            "limits.memory": "4GB"
+        },
+        "description": "Some description string",
+        "devices": {
+            "kvm": {
+                "path": "/dev/kvm",
+                "type": "unix-char"
+            }
+        }
+    }
+
+Same dict as used for initial creation and coming from GET. The name
+property can't be changed (see POST for that).
+
+
+### POST
+ * Description: rename a profile
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (rename a profile):
+
+    {
+        "name": "new-name"
+    }
+
+
+HTTP return value must be 204 (No content) and Location must point to
+the renamed resource.
+
+Renaming to an existing name must return the 409 (Conflict) HTTP code.
+
+
+### DELETE
+ * Description: remove a profile
+ * Authentication: trusted
+ * Operation: sync
+ * Return: standard return value or standard error
+
+Input (none at present):
+
+    {
+    }
+
+HTTP code for this should be 202 (Accepted).
diff --git a/doc/storage-backends.md b/doc/storage-backends.md
new file mode 100644
index 0000000..4b4ce0e
--- /dev/null
+++ b/doc/storage-backends.md
@@ -0,0 +1,65 @@
+# Storage Backends and supported functions
+## Feature comparison
+
+LXD supports using plain dirs, Btrfs, LVM, and ZFS for storage of images and containers.  
+Where possible, LXD tries to use the advanced features of each system to optimize operations.
+
+Feature                                     | Directory | Btrfs | LVM   | ZFS
+:---                                        | :---      | :---  | :---  | :---
+Optimized image storage                     | no        | yes   | yes   | yes
+Optimized container creation                | no        | yes   | yes   | yes
+Optimized snapshot creation                 | no        | yes   | yes   | yes
+Optimized image transfer                    | no        | yes   | no    | yes
+Optimized container transfer                | no        | yes   | no    | yes
+Copy on write                               | no        | yes   | yes   | yes
+Block based                                 | no        | no    | yes   | no
+Instant cloning                             | no        | yes   | yes   | yes
+Nesting support                             | yes       | yes   | no    | no
+Restore from older snapshots (not latest)   | yes       | yes   | yes   | no
+Storage quotas                              | no        | yes   | no    | yes
+
+## Mixed storage
+When switching storage backend after some containers or images already exist, LXD will create any new container  
+using the new backend and converting older images to the new backend as needed.
+
+## Non-optimized container transfer
+When the filesystem on the source and target hosts differs or when there is no faster way,  
+rsync is used to transfer the container content across.
+
+## Notes
+### Directory
+
+ - The directory backend is the fallback backend when nothing else is configured or detected.
+ - While this backend is fully functional, it's also much slower than
+   all the others due to it having to unpack images or do instant copies of
+   containers, snapshots and images.
+
+### Btrfs
+
+ - The btrfs backend is automatically used if /var/lib/lxd is on a btrfs filesystem.
+ - Uses a subvolume per container, image and snapshot, creating btrfs snapshots when creating a new object.
+
+### LVM
+
+ - A LVM VG must be created and then storage.lvm\_vg\_name set to point to it.
+ - If a thinpool doesn't already exist, one will be created, the name of the thinpool can be set with storage.lvm\_thinpool\_name .
+ - Uses LVs for images, then LV snapshots for containers and container snapshots.
+ - The filesystem used for the LVs is ext4 (can be configured to use xfs instead).
+ - LVs are created with a default size of 10GiB (can be configured through).
+
+### ZFS
+
+ - LXD can use any zpool or part of a zpool. storage.zfs\_pool\_name must be set to the path to be used.
+ - ZFS doesn't have to (and shouldn't be) mounted on /var/lib/lxd
+ - Uses ZFS filesystems for images, then snapshots and clones to create containers and snapshots.
+ - Due to the way copy-on-write works in ZFS, parent filesystems can't
+   be removed until all children are gone. As a result, LXD will
+   automatically rename any removed but still referenced object to a random
+   deleted/ path and keep it until such time the references are gone and it
+   can safely be removed.
+ - ZFS as it is today doesn't support delegating part of a pool to a
+   container user. Upstream is actively working on this.
+ - ZFS doesn't support restoring from snapshots other than the latest
+   one. You can however create new containers from older snapshots which
+   makes it possible to confirm the snapshots is indeed what you want to
+   restore before you remove the newer snapshots.
diff --git a/doc/userns-idmap.md b/doc/userns-idmap.md
new file mode 100644
index 0000000..a244f65
--- /dev/null
+++ b/doc/userns-idmap.md
@@ -0,0 +1,49 @@
+# Introduction
+LXD runs safe containers. This is achieved mostly through the use of
+user namespaces which make it possible to run containers unprivileged,
+greatly limiting the attack surface.
+
+User namespaces work by mapping a set of uids and gids on the host to a
+set of uids and gids in the container.
+
+
+For example, we can define that the host uids and gids from 100000 to
+165535 may be used by LXD and should be mapped to uid/gid 0 through
+65535 in the container.
+
+As a result a process running as uid 0 in the container will actually be
+running as uid 100000.
+
+Allocations should always be of at least 65536 uids and gids to cover
+the POSIX range including root (0) and nobody (65534).
+
+
+To simplify things, at this point, we will only deal with identical
+allocations for uids and gids and only support a single contiguous range
+per container.
+
+# Kernel support
+User namespaces require a kernel >= 3.12, LXD will start even on older
+kernels but will refuse to start containers.
+
+# Allowed ranges
+On most hosts, LXD will check /etc/subuid and /etc/subgid for
+allocations for the "lxd" user and on first start, set the default
+profile to use the first 65536 uids and gids from that range.
+
+If the range is shorter than 65536 (which includes no range at all),
+then LXD will fail to create or start any container until this is corrected.
+
+If some but not all of /etc/subuid, /etc/subgid, newuidmap (path lookup)
+and newgidmap (path lookup) can't be found on the system, LXD will fail
+the startup of any container until this is corrected as this shows a
+broken shadow setup.
+
+If none of those 4 files can be found, then LXD will assume it's running
+on a host using an old version of shadow. In this mode, LXD will assume
+it can use any uids and gids above 65535 and will take the first 65536
+as its default map.
+
+# Varying ranges between hosts
+The source map is sent when moving containers between hosts so that they
+can be remapped on the receiving host.
diff --git a/specs/architectures.md b/specs/architectures.md
deleted file mode 100644
index 30af23c..0000000
--- a/specs/architectures.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Introduction
-LXD just like LXC can run on just about any architecture that's
-supported by the Linux kernel and by Go.
-
-Some objects in LXD are tied to an architecture, like the container,
-container snapshots and images.
-
-This document lists all the supported architectures, their unique
-identifier (used in the database), how they should be named and some
-notes.
-
-
-Please note that what LXD cares about is the kernel architecture, not
-the particular userspace flavor as determined by the toolchain.
-
-That means that LXD considers armv7 hard-float to be the same as armv7
-soft-float and refers to both as "armv7". If useful to the user, the
-exact userspace ABI may be set as an image and container property,
-allowing easy query.
-
-# Architectures
-
-ID    | Name          | Notes                           | Personalities
-:---  | :---          | :----                           | :------------
-1     | i686          | 32bit Intel x86                 |
-2     | x86\_64       | 64bit Intel x86                 | x86
-3     | armv7l        | 32bit ARMv7 little-endian       |
-4     | aarch64       | 64bit ARMv8 little-endian       | armv7 (optional)
-5     | ppc           | 32bit PowerPC big-endian        |
-6     | ppc64         | 64bit PowerPC big-endian        | powerpc
-7     | ppc64le       | 64bit PowerPC little-endian     |
-8     | s390x         | 64bit ESA/390 big-endian        |
-
-The architecture names above are typically aligned with the Linux kernel
-architecture names.
diff --git a/specs/configuration.md b/specs/configuration.md
deleted file mode 100644
index 7ad2d02..0000000
--- a/specs/configuration.md
+++ /dev/null
@@ -1,302 +0,0 @@
-# Introduction
-Current LXD stores the following kind of configurations:
- - Server configuration (the LXD daemon itself)
- - Container configuration
-
-The server configuration is a simple set of key and values.
-
-The container configuration is a bit more complex as it uses both
-key/value configuration and some more complex configuration structures
-for devices, network interfaces and storage volumes.
-
-# Server configuration
-## Key/value configuration
-The key/value configuration is namespaced with the following namespaces
-currently supported:
- - core (core daemon configuration)
- - images (image configuration)
- - storage (storage configuration)
-
-Key                             | Type          | Default                   | Description
-:--                             | :---          | :------                   | :----------
-core.https\_address             | string        | -                         | Address to bind for the remote API
-core.https\_allowed\_origin     | string        | -                         | Access-Control-Allow-Origin http header value
-core.https\_allowed\_methods    | string        | -                         | Access-Control-Allow-Methods http header value
-core.https\_allowed\_headers    | string        | -                         | Access-Control-Allow-Headers http header value
-core.proxy\_https               | string        | -                         | https proxy to use, if any (falls back to HTTPS_PROXY environment variable)
-core.proxy\_http                | string        | -                         | http proxy to use, if any (falls back to HTTP_PROXY environment variable)
-core.proxy\_ignore\_hosts       | string        | -                         | hosts which don't need the proxy for use (similar format to NO_PROXY, e.g. 1.2.3.4,1.2.3.5, falls back to NO_PROXY environment varialbe)
-core.trust\_password            | string        | -                         | Password to be provided by clients to setup a trust
-storage.lvm\_vg\_name           | string        | -                         | LVM Volume Group name to be used for container and image storage. A default Thin Pool is created using 100% of the free space in the Volume Group, unless `storage.lvm_thinpool_name` is set.
-storage.lvm\_thinpool\_name     | string        | "LXDPool"                 | LVM Thin Pool to use within the Volume Group specified in `storage.lvm_vg_name`, if the default pool parameters are undesirable.
-storage.lvm\_fstype             | string        | ext4                      | Format LV with filesystem, for now it's value can be only ext4 (default) or xfs.
-storage.zfs\_pool\_name         | string        | -                         | ZFS pool name
-images.compression\_algorithm   | string        | gzip                      | Compression algorithm to use for new images (bzip2, gzip, lzma, xz or none)
-images.remote\_cache\_expiry    | integer       | 10                        | Number of days after which an unused cached remote image will be flushed
-images.auto\_update\_interval   | integer       | 6                         | Interval in hours at which to look for update to cached images (0 disables it)
-images.auto\_update\_cached     | boolean       | true                      | Whether to automatically update any image that LXD caches
-
-Those keys can be set using the lxc tool with:
-
-    lxc config set <key> <value>
-
-
-# Container configuration
-## Properties
-The following are direct container properties and can't be part of a profile:
- - name
- - architecture
-
-Name is the container name and can only be changed by renaming the container.
-
-## Key/value configuration
-The key/value configuration is namespaced with the following namespaces
-currently supported:
- - boot (boot related options, timing, dependencies, ...)
- - environment (environment variables)
- - limits (resource limits)
- - raw (raw container configuration overrides)
- - security (security policies)
- - user (storage for user properties, searchable)
- - volatile (used internally by LXD to store settings that are specific to a specific container instance)
-
-The currently supported keys are:
-
-Key                         | Type      | Default       | Live update   | Description
-:--                         | :---      | :------       | :----------   | :----------
-boot.autostart              | boolean   | false         | n/a           | Always start the container when LXD starts
-boot.autostart.delay        | integer   | 0             | n/a           | Number of seconds to wait after the container started before starting the next one
-boot.autostart.priority     | integer   | 0             | n/a           | What order to start the containers in (starting with highest)
-environment.\*              | string    | -             | yes (exec)    | key/value environment variables to export to the container and set on exec
-limits.cpu                  | string    | - (all)       | yes           | Number or range of CPUs to expose to the container
-limits.cpu.allowance        | string    | 100%          | yes           | How much of the CPU can be used. Can be a percentage (e.g. 50%) for a soft limit or hard a chunk of time (25ms/100ms)
-limits.cpu.priority         | integer   | 10 (maximum)  | yes           | CPU scheduling priority compared to other containers sharing the same CPUs (overcommit)
-limits.disk.priority        | integer   | 5 (medium)    | yes           | When under load, how much priority to give to the container's I/O requests
-limits.memory               | string    | - (all)       | yes           | Percentage of the host's memory or fixed value in bytes (supports kB, MB, GB, TB, PB and EB suffixes)
-limits.memory.enforce       | string    | hard          | yes           | If hard, container can't exceed its memory limit. If soft, the container can exceed its memory limit when extra host memory is available.
-limits.memory.swap          | boolean   | true          | yes           | Whether to allow some of the container's memory to be swapped out to disk
-limits.memory.swap.priority | integer   | 10 (maximum)  | yes           | The higher this is set, the least likely the container is to be swapped to disk
-limits.network.priority     | integer   | 0 (minimum)   | yes           | When under load, how much priority to give to the container's network requests
-limits.processes            | integer   | - (max)       | yes           | Maximum number of processes that can run in the container
-linux.kernel\_modules       | string    | -             | yes           | Comma separated list of kernel modules to load before starting the container
-raw.apparmor                | blob      | -             | yes           | Apparmor profile entries to be appended to the generated profile
-raw.lxc                     | blob      | -             | no            | Raw LXC configuration to be appended to the generated one
-security.nesting            | boolean   | false         | yes           | Support running lxd (nested) inside the container
-security.privileged         | boolean   | false         | no            | Runs the container in privileged mode
-user.\*                     | string    | -             | n/a           | Free form user key/value storage (can be used in search)
-
-The following volatile keys are currently internally used by LXD:
-
-Key                         | Type      | Default       | Description
-:--                         | :---      | :------       | :----------
-volatile.\<name\>.hwaddr    | string    | -             | Network device MAC address (when no hwaddr property is set on the device itself)
-volatile.\<name\>.name      | string    | -             | Network device name (when no name propery is set on the device itself)
-volatile.base\_image        | string    | -             | The hash of the image the container was created from, if any.
-volatile.last\_state.idmap  | string    | -             | Serialized container uid/gid map
-volatile.last\_state.power  | string    | -             | Container state as of last host shutdown
-
-
-Additionally, those user keys have become common with images (support isn't guaranteed):
-
-Key                         | Type          | Default           | Description
-:--                         | :---          | :------           | :----------
-user.network\_mode          | string        | dhcp              | One of "dhcp" or "link-local". Used to configure network in supported images.
-user.meta-data              | string        | -                 | Cloud-init meta-data, content is appended to seed value.
-user.user-data              | string        | #!cloud-config    | Cloud-init user-data, content is used as seed value.
-user.vendor-data            | string        | #!cloud-config    | Cloud-init vendor-data, content is used as seed value.
-
-Note that while a type is defined above as a convenience, all values are
-stored as strings and should be exported over the REST API as strings
-(which makes it possible to support any extra values without breaking
-backward compatibility).
-
-Those keys can be set using the lxc tool with:
-
-    lxc config set <container> <key> <value>
-
-Volatile keys can't be set by the user and can only be set directly against a container.
-
-The raw keys allow direct interaction with the backend features that LXD
-itself uses, setting those may very well break LXD in non-obvious ways
-and should whenever possible be avoided.
-
-
-## Devices configuration
-LXD will always provide the container with the basic devices which are
-required for a standard POSIX system to work. These aren't visible in
-container or profile configuration and may not be overriden.
-
-Those includes:
- - /dev/null (character device)
- - /dev/zero (character device)
- - /dev/full (character device)
- - /dev/console (character device)
- - /dev/tty (character device)
- - /dev/random (character device)
- - /dev/urandom (character device)
- - lo (network interface)
-
-Anything else has to be defined in the container configuration or in one
-of its profiles. The default profile will typically contain a network
-interface to become eth0 in the container.
-
-To add extra devices to a container, device entries can be added
-directly to a container, or to a profile.
-
-Devices may be added or removed while the container is running.
-
-Every device entry is identified by a unique name. If the same name is
-used in a subsequent profile or in the container's own configuration,
-the whole entry is overriden by the new definition.
-
-Device entries are added through:
-    lxc config device add <container> <name> <type> [key=value]...
-    lxc profile device add <profile> <name> <type> [key=value]...
-
-### Device types
-LXD supports the following device types:
-
-ID (database)   | Name          | Description
-:--             | :--           | :--
-0               | none          | Inheritance blocker
-1               | nic           | Network interface
-2               | disk          | Mountpoint inside the container
-3               | unix-char     | Unix character device
-4               | unix-block    | Unix block device
-
-### Type: none
-A none type device doesn't have any property and doesn't create anything inside the container.
-
-It's only purpose it to stop inheritance of devices coming from profiles.
-
-To do so, just add a none type device with the same name of the one you wish to skip inheriting.
-It can be added in a profile being applied after the profile it originated from or directly on the container.
-
-### Type: nic
-LXD supports different kind of network devices:
- - physical: Straight physical device passthrough from the host. The targeted device will vanish from the host and appear in the container.
- - bridged: Uses an existing bridge on the host and creates a virtual device pair to connect the host bridge to the container.
- - macvlan: Sets up a new network device based on an existing one but using a different MAC address.
- - p2p: Creates a virtual device pair, putting one side in the container and leaving the other side on the host.
-
-Different network interface types have different additional properties, the current list is:
-
-Key             | Type      | Default           | Required  | Used by                       | Description
-:--             | :--       | :--               | :--       | :--                           | :--
-nictype         | string    | -                 | yes       | all                           | The device type, one of "physical", "bridged", "macvlan" or "p2p"
-limits.ingress  | string    | -                 | no        | bridged, p2p                  | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes)
-limits.egress   | string    | -                 | no        | bridged, p2p                  | I/O limit in bit/s (supports kbit, Mbit, Gbit suffixes)
-limits.max      | string    | -                 | no        | bridged, p2p                  | Same as modifying both limits.read and limits.write
-name            | string    | kernel assigned   | no        | all                           | The name of the interface inside the container
-host\_name      | string    | randomly assigned | no        | bridged, p2p, macvlan         | The name of the interface inside the host
-hwaddr          | string    | randomly assigned | no        | all                           | The MAC address of the new interface
-mtu             | integer   | parent MTU        | no        | all                           | The MTU of the new interface
-parent          | string    | -                 | yes       | physical, bridged, macvlan    | The name of the host device or bridge
-
-### Type: disk
-Disk entries are essentially mountpoints inside the container. They can
-either be a bind-mount of an existing file or directory on the host, or
-if the source is a block device, a regular mount.
-
-The following properties exist:
-
-Key             | Type      | Default           | Required  | Description
-:--             | :--       | :--               | :--       | :--
-limits.read     | string    | -                 | no        | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops")
-limits.write    | string    | -                 | no        | I/O limit in byte/s (supports kB, MB, GB, TB, PB and EB suffixes) or in iops (must be suffixed with "iops")
-limits.max      | string    | -                 | no        | Same as modifying both limits.read and limits.write
-path            | string    | -                 | yes       | Path inside the container where the disk will be mounted
-source          | string    | -                 | yes       | Path on the host, either to a file/directory or to a block device
-optional        | boolean   | false             | no        | Controls whether to fail if the source doesn't exist
-readonly        | boolean   | false             | no        | Controls whether to make the mount read-only
-size            | string    | -                 | no        | Disk size in bytes (supports kB, MB, GB, TB, PB and EB suffixes). This is only supported for the rootfs (/).
-recursive       | boolean   | false             | no        | Whether or not to recursively mount the source path
-
-If multiple disks, backed by the same block device, have I/O limits set,
-the average of the limits will be used.
-
-### Type: unix-char
-Unix character device entries simply make the requested character device
-appear in the container's /dev and allow read/write operations to it.
-
-The following properties exist:
-
-Key         | Type      | Default           | Required  | Description
-:--         | :--       | :--               | :--       | :--
-path        | string    | -                 | yes       | Path inside the container
-major       | int       | device on host    | no        | Device major number
-minor       | int       | device on host    | no        | Device minor number
-uid         | int       | 0                 | no        | UID of the device owner in the container
-gid         | int       | 0                 | no        | GID of the device owner in the container
-mode        | int       | 0660              | no        | Mode of the device in the container
-
-### Type: unix-block
-Unix block device entries simply make the requested character device
-appear in the container's /dev and allow read/write operations to it.
-
-The following properties exist:
-
-Key         | Type      | Default           | Required  | Description
-:--         | :--       | :--               | :--       | :--
-path        | string    | -                 | yes       | Path inside the container
-major       | int       | device on host    | no        | Device major number
-minor       | int       | device on host    | no        | Device minor number
-uid         | int       | 0                 | no        | UID of the device owner in the container
-gid         | int       | 0                 | no        | GID of the device owner in the container
-mode        | int       | 0660              | no        | Mode of the device in the container
-
-## Profiles
-Profiles can store any configuration that a container can (key/value or devices)
-and any number of profiles can be applied to a container.
-
-Profiles are applied in the order they are specified so the last profile
-to specify a specific key wins.
-
-In any case, resource-specific configuration always overrides that
-coming from the profiles.
-
-
-If not present, LXD will create a "default" profile which comes with a
-network interface connected to LXD's default bridge (lxcbr0).
-
-The "default" profile is set for any new container created which doesn't
-specify a different profiles list.
-
-## JSON representation
-A representation of a container using all the different types of
-configurations would look like:
-
-    {
-        'name': "my-container",
-        'profiles': ["default"],
-        'architecture': 'x86_64',
-        'config': {
-            'limits.cpu': '3',
-            'security.privileged': 'true'
-        },
-        'devices': {
-            'nic-lxcbr0': {
-                'type': 'none'
-            },
-            'nic-mybr0': {
-                'type': 'nic',
-                'mtu': '9000',
-                'parent': 'mybr0'
-            },
-            'rootfs': {
-                'type': 'disk',
-                'path': '/',
-                'source': 'UUID=8f7fdf5e-dc60-4524-b9fe-634f82ac2fb6'
-            },
-        },
-        'status': {
-                    'status': "Running",
-                    'status_code': 103,
-                    'ips': [{'interface': "eth0",
-                             'protocol': "INET6",
-                             'address': "2001:470:b368:1020:1::2"},
-                            {'interface': "eth0",
-                             'protocol': "INET",
-                             'address': "172.16.15.30"}]}
-    }
-
diff --git a/specs/daemon-behavior.md b/specs/daemon-behavior.md
deleted file mode 100644
index 56f5bd2..0000000
--- a/specs/daemon-behavior.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Introduction
-
-This specification covers some of the daemon's behavior, such as
-reaction to given signals, crashes, ...
-
-# Startup
-On every start, LXD checks that its directory structure exists. If it
-doesn't, it'll create the required directories, generate a keypair and
-initialize the database.
-
-Once the daemon is ready for work, LXD will scan the containers table
-for any container for which the stored power state differs from the
-current one. If a container's power state was recorded as running and the
-container isn't running, LXD will start it.
-
-# Signal handling
-## SIGINT, SIGQUIT, SIGTERM
-For those signals, LXD assumes that it's being temporarily stopped and
-will be restarted at a later time to continue handling the containers.
-
-The containers will keep running and LXD will close all connections and
-exit cleanly.
-
-## SIGPWR
-Indicates to LXD that the host is going down.
-
-LXD will attempt a clean shutdown of all the containers. After 30s, it
-will kill any remaining container.
-
-The container power\_state in the containers table is kept as it was so
-that LXD after the host is done rebooting can restore the containers as
-they were.
-
-## SIGUSR1
-Write a memory profile dump to the file specified with \-\-memprofile.
diff --git a/specs/database.md b/specs/database.md
deleted file mode 100644
index fd7de4f..0000000
--- a/specs/database.md
+++ /dev/null
@@ -1,300 +0,0 @@
-# Introduction
-So first of all, why a database?
-
-Rather than keeping the configuration and state within each container's
-directory as is traditionally done by LXC, LXD has an internal database
-which stores all of that information. This allows very quick queries
-against all containers configuration.
-
-
-An example is the rather obvious question "what containers are using br0?".
-To answer that question without a database, LXD would have to iterate
-through every single container, load and parse its configuration and
-then look at what network devices are defined in there.
-
-While that may be quick with a few containers, imagine how many
-filesystem access would be required for 2000 containers. Instead with a
-database, it's only a matter of accessing the already cached database
-with a pretty simple query.
-
-
-# Database engine
-As this is a purely internal database with a single client and very
-little data, we'll be using sqlite3.
-
-We have no interest in replication or other HA features offered by the
-bigger database engines as LXD runs on each compute nodes and having the
-database accessible when the compute node itself isn't, wouldn't be
-terribly useful.
-
-
-# Design
-The design of the database is made to be as close as possible to the REST API.
-
-The main table and field names are exact match for the REST API.
-
-However this database isn't an exact match of the API, mostly because
-any runtime or external piece of information will not be stored in the
-database (as this would require constent polling and wouldn't gain us
-anything).
-
-We make no guarantee of stability for the database schema. This is a
-purely internal database which only LXD should ever use. Updating LXD
-may cause a schema update and data being shuffled. In those cases, LXD
-will make a copy of the old database as ".old" to allow for a revert.
-
-
-# Tables
-The list of tables is:
-
- * certificates
- * config
- * containers
- * containers\_config
- * containers\_devices
- * containers\_devices\_config
- * containers\_profiles
- * images
- * images\_properties
- * images\_aliases
- * images\_source
- * profiles
- * profiles\_config
- * profiles\_devices
- * profiles\_devices\_config
- * schema
-
-You'll notice that compared to the REST API, there are three main differences:
-
- 1. The extra "\*\_config" tables which are there for key/value config storage.
- 2. The extra "images\_properties" table which is there for key/value property storage.
- 3. The extra "schema" table whish is used for database schema version tracking.
- 4. There is no "snapshots" table. That's because snapshots are a copy
-    of a container at a given point in time, including its configuration and
-    on-disk state. So having snapshots in a separate table would only be needless duplication.
-
-# Notes on sqlite3
-sqlite3 only supports 5 storage classes: NULL, INTEGER, REAL, TEXT and BLOB
-There are then a set of aliases for each of those storage classes which is what we use below.
-
-# Schema
-## certificates
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-fingerprint     | VARCHAR(255)  | -             | NOT NULL          | HEX encoded certificate fingerprint
-type            | INTEGER       | -             | NOT NULL          | Certificate type (0 = client)
-name            | VARCHAR(255)  | -             | NOT NULL          | Certificate name (defaults to CN)
-certificate     | TEXT          | -             | NOT NULL          | PEM encoded certificate
-
-Index: UNIQUE ON id AND fingerprint
-
-
-## config (server configuration)
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
-value           | TEXT          | -             |                   | Configuration value (NULL for unset)
-
-Index: UNIQUE ON id AND key
-
-
-## containers
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-name            | VARCHAR(255)  | -             | NOT NULL          | Container name
-architecture    | INTEGER       | -             | NOT NULL          | Container architecture
-type            | INTEGER       | 0             | NOT NULL          | Container type (0 = container, 1 = container snapshot)
-ephemeral       | INTEGER       | 0             | NOT NULL          | Whether the container is ephemeral (0 = persistent, 1 = ephemeral)
-stateful        | INTEGER       | 0             | NOT NULL          | Whether the snapshot contains state (snapshot only)
-creation\_date  | DATETIME      | -             |                   | Image creation date (user supplied, 0 = unknown)
-
-Index: UNIQUE ON id AND name
-
-
-## containers\_config
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
-key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
-value           | TEXT          | -             |                   | Configuration value (NULL for unset)
-
-Index: UNIQUE ON id AND container\_id + key
-
-Foreign keys: container\_id REFERENCES containers(id)
-
-
-## containers\_devices
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
-name            | VARCHAR(255)  | -             | NOT NULL          | Container name
-type            | INTEGER       | 0             | NOT NULL          | Device type (see configuration.md)
-
-Index: UNIQUE ON id AND container\_id + name
-
-Foreign keys: container\_id REFERENCES containers(id)
-
-
-## containers\_devices\_config
-
-Column                  | Type          | Default       | Constraint        | Description
-:-----                  | :---          | :------       | :---------        | :----------
-id                      | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-container\_device\_id   | INTEGER       | -             | NOT NULL          | containers\_devices.id FK
-key                     | VARCHAR(255)  | -             | NOT NULL          | Configuration key
-value                   | TEXT          | -             |                   | Configuration value (NULL for unset)
-
-Index: UNIQUE ON id AND container\_device\_id + key
-
-Foreign keys: container\_device\_id REFERENCES containers\_devices(id)
-
-
-## containers\_profiles
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-container\_id   | INTEGER       | -             | NOT NULL          | containers.id FK
-profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
-apply\_order    | INTEGER       | 0             | NOT NULL          | Profile ordering
-
-Index: UNIQUE ON id AND container\_id + profile\_id
-
-Foreign keys: container\_id REFERENCES containers(id) and profile\_id REFERENCES profiles(id)
-
-
-## images
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-cached          | INTEGER       | 0             | NOT NULL          | Whether this is a cached image
-fingerprint     | VARCHAR(255)  | -             | NOT NULL          | Tarball fingerprint
-filename        | VARCHAR(255)  | -             | NOT NULL          | Tarball filename
-size            | INTEGER       | -             | NOT NULL          | Tarball size
-public          | INTEGER       | 0             | NOT NULL          | Whether the image is public or not
-auto\_update    | INTEGER       | 0             | NOT NULL          | Whether to update from the source of this image
-architecture    | INTEGER       | -             | NOT NULL          | Image architecture
-creation\_date  | DATETIME      | -             |                   | Image creation date (user supplied, 0 = unknown)
-expiry\_date    | DATETIME      | -             |                   | Image expiry (user supplied, 0 = never)
-upload\_date    | DATETIME      | -             | NOT NULL          | Image entry creation date
-last\_use\_date | DATETIME      | -             |                   | Last time the image was used to spawn a container
-
-Index: UNIQUE ON id AND fingerprint
-
-
-## images\_aliases
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-name            | VARCHAR(255)  | -             | NOT NULL          | Alias name
-image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
-description     | VARCHAR(255)  | -             |                   | Description of the alias
-
-Index: UNIQUE ON id AND name
-
-Foreign keys: image\_id REFERENCES images(id)
-
-
-## images\_properties
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
-type            | INTEGER       | 0             | NOT NULL          | Property type (0 = string, 1 = text)
-key             | VARCHAR(255)  | -             | NOT NULL          | Property name
-value           | TEXT          | -             |                   | Property value (NULL for unset)
-
-Index: UNIQUE ON id
-
-Foreign keys: image\_id REFERENCES images(id)
-
-## images\_source
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-image\_id       | INTEGER       | -             | NOT NULL          | images.id FK
-server          | TEXT          | -             | NOT NULL          | Server URL
-protocol        | INTEGER       | 0             | NOT NULL          | Protocol to access the remote (0 = lxd, 1 = direct, 2 = simplestreams)
-alias           | VARCHAR(255)  | -             | NOT NULL          | What remote alias to use as the source
-certificate     | TEXT          | -             |                   | PEM encoded certificate of the server
-
-Index: UNIQUE ON id
-
-Foreign keys: image\_id REFERENCES images(id)
-
-## profiles
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-name            | VARCHAR(255)  | -             | NOT NULL          | Profile name
-description     | TEXT          | -             |                   | Description of the profile
-
-Index: UNIQUE on id AND name
-
-
-## profiles\_config
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
-key             | VARCHAR(255)  | -             | NOT NULL          | Configuration key
-value           | VARCHAR(255)  | -             |                   | Configuration value (NULL for unset)
-
-Index: UNIQUE ON id AND profile\_id + key
-
-Foreign keys: profile\_id REFERENCES profiles(id)
-
-
-## profiles\_devices
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-profile\_id     | INTEGER       | -             | NOT NULL          | profiles.id FK
-name            | VARCHAR(255)  | -             | NOT NULL          | Container name
-type            | INTEGER       | 0             | NOT NULL          | Device type (see configuration.md)
-
-Index: UNIQUE ON id AND profile\_id + name
-
-Foreign keys: profile\_id REFERENCES profiles(id)
-
-
-## profiles\_devices\_config
-
-Column                  | Type          | Default       | Constraint        | Description
-:-----                  | :---          | :------       | :---------        | :----------
-id                      | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-profile\_device\_id     | INTEGER       | -             | NOT NULL          | profiles\_devices.id FK
-key                     | VARCHAR(255)  | -             | NOT NULL          | Configuration key
-value                   | TEXT          | -             |                   | Configuration value (NULL for unset)
-
-Index: UNIQUE ON id AND profile\_device\_id + key
-
-Foreign keys: profile\_device\_id REFERENCES profiles\_devices(id)
-
-
-## schema
-
-Column          | Type          | Default       | Constraint        | Description
-:-----          | :---          | :------       | :---------        | :----------
-id              | INTEGER       | SERIAL        | NOT NULL          | SERIAL
-version         | INTEGER       | -             | NOT NULL          | Schema version
-updated\_at     | DATETIME      | -             | NOT NULL          | When the schema update was done
-
-Index: UNIQUE ON id AND version
diff --git a/specs/dev-lxd.md b/specs/dev-lxd.md
deleted file mode 100644
index be5b398..0000000
--- a/specs/dev-lxd.md
+++ /dev/null
@@ -1,103 +0,0 @@
-# Introduction
-Communication between the hosted workload (container) and its host while
-not strictly needed is a pretty useful feature.
-
-In LXD, this feature is implemented through a /dev/lxd/sock node which is
-created and setup for all LXD containers.
-
-This file is a Unix socket which processes inside the container can
-connect to. It's multi-threaded so multiple clients can be connected at the
-same time.
-
-# Implementation details
-LXD on the host binds /var/lib/lxd/devlxd and starts listening for new
-connections on it.
-
-This socket is then bind-mounted into every single container started by
-LXD at /dev/lxd/sock.
-
-The bind-mount is required so we can exceed 4096 containers, otherwise,
-LXD would have to bind a different socket for every container, quickly
-reaching the FD limit.
-
-# Authentication
-Queries on /dev/lxd/sock will only return information related to the
-requesting container. To figure out where a request comes from, LXD will
-extract the initial socket ucred and compare that to the list of
-containers it manages.
-
-# Protocol
-The protocol on /dev/lxd/sock is plain-text HTTP with JSON messaging, so very
-similar to the local version of the LXD protocol.
-
-Unlike the main LXD API, there is no background operation and no
-authentication support in the /dev/lxd/sock API.
-
-# REST-API
-## API structure
- * /
-   * /1.0
-     * /1.0/config
-       * /1.0/config/{key}
-     * /1.0/meta-data
-
-## API details
-### /
-#### GET
- * Description: List of supported APIs
- * Return: list of supported API endpoint URLs (by default ['/1.0'])
-
-Return value:
-
-    [
-        "/1.0"
-    ]
-
-### /1.0
-#### GET
- * Description: Information about the 1.0 API
- * Return: dict
-
-Return value:
-
-    {
-        "api_version": "1.0"
-    }
-
-### /1.0/config
-#### GET
- * Description: List of configuration keys
- * Return: list of configuration keys URL
-
-Note that the configuration key names match those in the container
-config, however not all configuration namespaces will be exported to
-/dev/lxd/sock.
-Currently only the user.\* keys are accessible to the container.
-
-At this time, there also aren't any container-writable namespace.
-
-Return value:
-
-    [
-        "/1.0/config/user.a"
-    ]
-
-### /1.0/config/\<KEY\>
-#### GET
- * Description: Value of that key
- * Return: Plain-text value
-
-Return value:
-
-    blah
-
-### /1.0/meta-data
-#### GET
- * Description: Container meta-data compatible with cloud-init
- * Return: cloud-init meta-data
-
-Return value:
-
-    #cloud-config
-    instance-id: abc
-    local-hostname: abc
diff --git a/specs/environment.md b/specs/environment.md
deleted file mode 100644
index 02823ec..0000000
--- a/specs/environment.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Introduction
-The LXD client and daemon respect some environment variables to adapt to
-the user's environment and to turn some advanced features on and off.
-
-# Common
-LXD\_DIR                        | The LXD data directory
-PATH                            | List of paths to look into when resolving binaries
-http\_proxy                     | Proxy server URL for HTTP
-https\_proxy                    | Proxy server URL for HTTPs
-no\_proxy                       | List of domains that don't require the use of a proxy
-
-# Client environment variable
-Name                            | Description
-:---                            | :----
-EDITOR                          | What text editor to use
-VISUAL                          | What text editor to use (if EDITOR isn't set)
-
-# Server environment variable
-Name                            | Description
-:---                            | :----
-LXD\_SECURITY\_APPARMOR         | If set to "false", forces AppArmor off
-LXD\_LXC\_TEMPLATE\_CONFIG      | Path to the LXC template configuration directory
-LXD\_LVM\_LVSIZE                | Size of the default LVM LV (10Gib by default)
diff --git a/specs/image-handling.md b/specs/image-handling.md
deleted file mode 100644
index 5a81083..0000000
--- a/specs/image-handling.md
+++ /dev/null
@@ -1,130 +0,0 @@
-# Introduction
-LXD uses an image based workflow. It comes with a built-in image store
-where the user or external tools can import images.
-
-Containers are then started from those images.
-
-It's possible to spawn remote containers using local images or local
-containers using remote images. In such cases, the image may be cached
-on the target LXD.
-
-# Caching
-When spawning a container from a remote image, the remote image is
-downloaded into the local image store with the cached bit set. The image
-will be kept locally as a private image until either it's been unused
-(no new container spawned) for the number of days set in
-images.remote\_cache\_expiry or until the image's expiry is reached
-whichever comes first.
-
-LXD keeps track of image usage by updating the last\_used\_at image
-property every time a new container is spawned from the image.
-
-# Auto-update
-LXD can keep images up to date. By default, any image which comes from a
-remote server and was requested through an alias will be automatically
-updated by LXD. This can be changed with images.auto\_update\_cached.
-
-On startup and then every 3 hours (unless images.auto\_update\_interval
-is set), the LXD daemon will go look for more recent version of all the
-images in the store which are marked as auto-update and have a recorded
-source server.
-
-When a new image is found, it is downloaded into the image store, the
-aliases pointing to the old image are moved to the new one and the old
-image is removed from the store.
-
-The user can also request a particular image be kept up to date when
-manually copying an image from a remote server.
-
-# Image format
-LXD currently supports two LXD-specific image formats.
-
-The first is a unified tarball, where a single tarball
-contains both the container rootfs and the needed metadata.
-
-The second is a split model, using two tarballs instead, one containing
-the rootfs, the other containing the metadata.
-
-The former is what's produced by LXD itself and what people should be
-using for LXD-specific images.
-
-The latter is designed to allow for easy image building from existing
-non-LXD rootfs tarballs already available today.
-
-## Unified tarball
-Tarball, can be compressed and contains:
- - rootfs/
- - metadata.yaml
- - templates/ (optional)
-
-In this mode, the image identifier is the SHA-256 of the tarball.
-
-## Split tarballs
-Two (possibly compressed) tarballs. One for metadata, one for the rootfs.
-
-metadata.tar contains:
- - metadata.yaml
- - templates/ (optional)
-
-rootfs.tar contains a Linux root filesystem at its root.
-
-In this mode the image identifier is the SHA-256 of the concatenation of
-the metadata and rootfs tarball (in that order).
-
-## Content
-The rootfs directory (or tarball) contains a full file system tree of what will become the container's /.
-
-The templates directory contains pongo2-formatted templates of files inside the container.
-
-metadata.yaml contains information relevant to running the image under
-LXD, at the moment, this contains:
-
-    architecture: x86_64
-    creation_date: 1424284563
-    properties:
-      description: Ubuntu 14.04 LTS Intel 64bit
-      os: Ubuntu
-      release:
-        - trusty
-        - 14.04
-    templates:
-      /etc/hosts:
-        when:
-          - create
-          - rename
-        template: hosts.tpl
-        properties:
-          foo: bar
-      /etc/hostname:
-        when:
-          - start
-        template: hostname.tpl
-      /etc/network/interfaces:
-        when:
-          - create
-        template: interfaces.tpl
-        create_only: true
-
-The architecture and creation\_date fields are mandatory, the properties
-are just a set of default properties for the image. The os, release,
-name and description fields while not mandatory in any way, should be
-pretty common.
-
-For templates, the "when" key can be one or more of:
- - create (run at the time a new container is created from the image)
- - copy (run when a container is created from an existing one)
- - start (run every time the container is started)
-
-The templates will always receive the following context:
- - trigger: name of the event which triggered the template (string)
- - path: path of the file being templated (string)
- - container: key/value map of container properties (name, architecture, privileged and ephemeral) (map[string]string)
- - config: key/value map of the container's configuration (map[string]string)
- - devices: key/value map of the devices assigned to this container (map[string]map[string]string)
- - properties: key/value map of the template properties specified in metadata.yaml (map[string]string)
-
-The "create\_only" key can be set to have LXD only only create missing files but not overwrite an existing file.
-
-As a general rule, you should never template a file which is owned by a
-package or is otherwise expected to be overwritten by normal operation
-of the container.
diff --git a/specs/lxd-ssl-authentication.md b/specs/lxd-ssl-authentication.md
deleted file mode 100644
index f648b8e..0000000
--- a/specs/lxd-ssl-authentication.md
+++ /dev/null
@@ -1,106 +0,0 @@
-# Introduction
-Local communications over the UNIX socket happen over a cleartext HTTP
-socket and access is restricted by socket ownership and mode.
-
-Remote communications with the LXD daemon happen using JSON over HTTPS.
-The supported protocol must be TLS1.2 or better.
-All communications must use perfect forward secrecy and ciphers must be
-limited to strong elliptic curve ones (such as ECDHE-RSA or
-ECDHE-ECDSA).
-
-Any generated key should be at least 4096bit RSA and when using
-signatures, only SHA-2 signatures should be trusted.
-
-Since we control both client and server, there is no reason to support
-any backward compatibility to broken protocol or ciphers.
-
-Both the client and the server will generate a keypair the first time
-they're launched. The server will use that for all https connections to
-the LXD socket and the client will use its certificate as a client
-certificate for any client-server communication.
-
-# Adding a remote with a default setup
-In the default setup, when the user adds a new server with "lxc remote
-add", the server will be contacted over HTTPs, its certificate
-downloaded and the fingerprint will be shown to the user.
-
-The user will then be asked to confirm that this is indeed the server's
-fingerprint which they can manually check by connecting to or asking
-someone with access to the server to run the status command and compare
-the fingerprints.
-
-After that, the user must enter the trust password for that server, if
-it matches, the client certificate is added to the server's trust store
-and the client can now connect to the server without having to provide
-any additional credentials.
-
-This is a workflow that's very similar to that of ssh where an initial
-connection to an unknown server triggers a prompt.
-
-A possible extension to that is to support something similar to ssh's
-fingerprint in DNS feature where the certificate fingerprint is added as
-a TXT record, then if the domain is signed by DNSSEC, the client will
-automatically accept the fingerprint if it matches that in the DNS
-record.
-
-# Adding a remote with a PKI based setup
-In the PKI setup, a system administrator is managing a central PKI, that
-PKI then issues client certificates for all the lxc clients and server
-certificates for all the LXD daemons.
-
-Those certificates and keys are manually put in place on the various
-machines, replacing the automatically generated ones.
-
-The CA certificate is also added to all machines.
-A CRL may also accompany the CA certificate.
-
-In that mode, any connection to a LXD daemon will be done using the
-preseeded CA certificate. If the server certificate isn't signed by the
-CA, or if it has been revoked, the connection will simply go through the
-normal authentication mechanism.
-
-If the server certificate is valid and signed by the CA, then the
-connection continues without prompting the user for the certificate.
-
-After that, the user must enter the trust password for that server, if
-it matches, the client certificate is added to the server's trust store
-and the client can now connect to the server without having to provide
-any additional credentials.
-
-# Password prompt
-To establish a new trust relationship, a password must be set on the
-server and send by the client when adding itself.
-
-A remote add operation should therefore go like this:
- 1. Call GET /1.0
- 2. If we're not in a PKI setup ask the user to confirm the fingerprint.
- 3. Look at the dict we received back from the server. If "auth" is
-    "untrusted", ask the user for the server's password and do a POST to
-    /1.0/certificates, then call /1.0 again to check that we're indeed
-    trusted.
- 4. Remote is now ready
-
-# Failure scenarios
-## Server certificate changes
-This will typically happen in two cases:
-
- * The server was fully reinstalled and so changed certificate
- * The connection is being intercepted (MITM)
-
-In such cases the client will refuse to connect to the server since the
-certificate fringerprint will not match that in the config for this
-remote.
-
-It is then up to the user to contact the server administrator to check
-if the certificate did in fact change. If it did, then the certificate
-can be replaced by the new one or the remote be removed altogether and
-re-added.
-
-
-## Server trust relationship revoked
-In this case, the server still uses the same certificate but all API
-calls return a 403 with an error indicating that the client isn't
-trusted.
-
-This happens if another trusted client or the local server administrator
-removed the trust entry on the server.
diff --git a/specs/migration.md b/specs/migration.md
deleted file mode 100644
index 7dfe8d9..0000000
--- a/specs/migration.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Live Migration in LXD
-
-## Overview
-
-Migration has two pieces, a "source", that is, the host that already has the
-container, and a "sink", the host that's getting the container. Currently,
-in the 'pull' mode, the source sets up an operation, and the sink connects
-to the source and pulls the container.
-
-There are three websockets (channels) used in migration:
-  1. the control stream
-  2. the criu images stream
-  3. the filesystem stream
-
-When a migration is initiated, information about the container, its
-configuration, etc. are sent over the control channel (a full
-description of this process is below), the criu images and container
-filesystem are synced over their respective channels, and the result of
-the restore operation is sent from the sink to the source over the
-control channel.
-
-In particular, the protocol that is spoken over the criu channel and filesystem
-channel can vary, depending on what is negotiated over the control socket. For
-example, both the source and the sink's LXD directory is on btrfs, the
-filesystem socket can speak btrfs-send/receive. Additionally, although we do a
-"stop the world" type migration right now, support for criu's p.haul protocol
-will happen over the criu socket at some later time.
-
-## Control Socket
-
-Once all three websockets are connected between the two endpoints, the
-source sends a MigrationHeader (protobuf description found in
-`/lxd/migration/migrate.proto`). This header contains the container
-configuration which will be added to the new container.
-
-There are also two fields indicating the filesystem and criu protocol to speak.
-For example, if a server is hosted on a btrfs filesystem, it can indicate that it
-wants to do a `btrfs send` instead of a simple rsync (similarly, it could
-indicate that it wants to speak the p.haul protocol, instead of just rsyncing
-the images over slowly).
-
-The sink then examines this message and responds with whatever it
-supports. Continuing our example, if the sink is not on a btrfs
-filesystem, it responds with the lowest common denominator (rsync, in
-this case), and the source is to send the root filesystem using rsync.
-Similarly with the criu connection; if the sink doesn't have support for
-the p.haul protocol (or whatever), we fall back to rsync.
diff --git a/specs/requirements.md b/specs/requirements.md
deleted file mode 100644
index 7d840f7..0000000
--- a/specs/requirements.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Requirements
-## Go
-
-LXD requires Go 1.5 or higher.
-Both the golang and gccgo compilers are supported.
-
-## Kernel requirements
-The minimum supported kernel version is 3.13.
-
-LXD requires a kernel with support for:
- * Namespaces (pid, net, uts, ipc and mount)
- * Seccomp
-
-The following optional features also require extra kernel options:
- * Namespaces (user and cgroup)
- * AppArmor (including Ubuntu patch for mount mediation)
- * Control Groups (blkio, cpuset, devices, memory, pids and net\_prio)
- * CRIU (exact details to be found with CRIU upstream)
-
-As well as any other kernel feature required by the LXC version in use.
-
-## LXC
-LXD requires LXC 1.1.5 or higher with the following build options:
- * apparmor (if using LXD's apparmor support)
- * seccomp
-
-To run recent version of various distributions, including Ubuntu, LXCFS
-should also be installed.
diff --git a/specs/rest-api.md b/specs/rest-api.md
deleted file mode 100644
index 96a3429..0000000
--- a/specs/rest-api.md
+++ /dev/null
@@ -1,1546 +0,0 @@
-# Introduction
-All the communications between LXD and its clients happen using a
-RESTful API over http which is then encapsulated over either SSL for
-remote operations or a unix socket for local operations.
-
-Not all of the REST interface requires authentication:
-
- * GET to / is allowed for everyone (lists the API endpoints)
- * GET to /1.0 is allowed for everyone (but result varies)
- * POST to /1.0/certificates is allowed for everyone with a client certificate
- * GET to /1.0/images/\* is allowed for everyone but only returns public images for unauthenticated users
-
-Unauthenticated endpoints are clearly identified as such below.
-
-# API versioning
-The list of supported major API versions can be retrieved using GET /.
-
-The reason for a major API bump is if the API breaks backward compatibility.
-
-Feature additions done without breaking backward compatibility only
-result in addition to api\_extensions which can be used by the client
-to check if a given feature is supported by the server.
-
-# Return values
-There are three standard return types:
- * Standard return value
- * Background operation
- * Error
-
-### Standard return value
-For a standard synchronous operation, the following dict is returned:
-
-    {
-        "type": "sync",
-        "status": "Success",
-        "status_code": 200,
-        "metadata": {}                          # Extra resource/action specific metadata
-    }
-
-HTTP code must be 200.
-
-### Background operation
-When a request results in a background operation, the HTTP code is set to 202 (Accepted)
-and the Location HTTP header is set to the operation URL.
-
-The body is a dict with the following structure:
-
-    {
-        "type": "async",
-        "status": "OK",
-        "status_code": 100,
-        "operation": "/1.0/containers/<id>",                    # URL to the background operation
-        "metadata": {}                                          # Operation metadata (see below)
-    }
-
-The operation metadata structure looks like:
-
-    {
-        "id": "a40f5541-5e98-454f-b3b6-8a51ef5dbd3c",           # UUID of the operation
-        "class": "websocket",                                   # Class of the operation (task, websocket or token)
-        "created_at": "2015-11-17T22:32:02.226176091-05:00",    # When the operation was created
-        "updated_at": "2015-11-17T22:32:02.226176091-05:00",    # Last time the operation was updated
-        "status": "Running",                                    # String version of the operation's status
-        "status_code": 103,                                     # Integer version of the operation's status (use this rather than status)
-        "resources": {                                          # Dictionary of resource types (container, snapshots, images) and affected resources
-          "containers": [
-            "/1.0/containers/test"
-          ]
-        },
-        "metadata": {                                           # Metadata specific to the operation in question (in this case, exec)
-          "fds": {
-            "0": "2a4a97af81529f6608dca31f03a7b7e47acc0b8dc6514496eb25e325f9e4fa6a",
-            "control": "5b64c661ef313b423b5317ba9cb6410e40b705806c28255f601c0ef603f079a7"
-          }
-        },
-        "may_cancel": false,                                    # Whether the operation can be canceled (DELETE over REST)
-        "err": ""                                               # The error string should the operation have failed
-    }
-
-The body is mostly provided as a user friendly way of seeing what's
-going on without having to pull the target operation, all information in
-the body can also be retrieved from the background operation URL.
-
-### Error
-There are various situations in which something may immediately go
-wrong, in those cases, the following return value is used:
-
-    {
-        "type": "error",
-        "error": "Failure",
-        "error_code": 400,
-        "metadata": {}                      # More details about the error
-    }
-
-HTTP code must be one of of 400, 401, 403, 404, 409, 412 or 500.
-
-# Status codes
-The LXD REST API often has to return status information, be that the
-reason for an error, the current state of an operation or the state of
-the various resources it exports.
-
-To make it simple to debug, all of those are always doubled. There is a
-numeric representation of the state which is guaranteed never to change
-and can be relied on by API clients. Then there is a text version meant
-to make it easier for people manually using the API to figure out what's
-happening.
-
-In most cases, those will be called status and status\_code, the former
-being the user-friendly string representation and the latter the fixed
-numeric value.
-
-The codes are always 3 digits, with the following ranges:
- * 100 to 199: resource state (started, stopped, ready, ...)
- * 200 to 399: positive action result
- * 400 to 599: negative action result
- * 600 to 999: future use
-
-## List of current status codes
-
-Code  | Meaning
-:---  | :------
-100   | Operation created
-101   | Started
-102   | Stopped
-103   | Running
-104   | Cancelling
-105   | Pending
-106   | Starting
-107   | Stopping
-108   | Aborting
-109   | Freezing
-110   | Frozen
-111   | Thawed
-200   | Success
-400   | Failure
-401   | Cancelled
-
-
-# Recursion
-To optimize queries of large lists, recursion is implemented for collections.
-A "recursion" argument can be passed to a GET query against a collection.
-
-The default value is 0 which means that collection member URLs are
-returned. Setting it to 1 will have those URLs be replaced by the object
-they point to (typically a dict).
-
-Recursion is implemented by simply replacing any pointer to an job (URL)
-by the object itself.
-
-# Async operations
-Any operation which may take more than a second to be done must be done
-in the background, returning a background operation ID to the client.
-
-The client will then be able to either poll for a status update or wait
-for a notification using the long-poll API.
-
-# Notifications
-A websocket based API is available for notifications, different notification
-types exist to limit the traffic going to the client.
-
-It's recommended that the client always subscribes to the operations
-notification type before triggering remote operations so that it doesn't
-have to then poll for their status.
-
-# API structure
- * /
-   * /1.0
-     * /1.0/certificates
-       * /1.0/certificates/\<fingerprint\>
-     * /1.0/containers
-       * /1.0/containers/\<name\>
-         * /1.0/containers/\<name\>/exec
-         * /1.0/containers/\<name\>/files
-         * /1.0/containers/\<name\>/snapshots
-         * /1.0/containers/\<name\>/snapshots/\<name\>
-         * /1.0/containers/\<name\>/state
-         * /1.0/containers/\<name\>/logs
-         * /1.0/containers/\<name\>/logs/\<logfile\>
-     * /1.0/events
-     * /1.0/images
-       * /1.0/images/\<fingerprint\>
-         * /1.0/images/\<fingerprint\>/export
-       * /1.0/images/aliases
-         * /1.0/images/aliases/\<name\>
-     * /1.0/networks
-       * /1.0/networks/\<name\>
-     * /1.0/operations
-       * /1.0/operations/\<uuid\>
-         * /1.0/operations/\<uuid\>/wait
-         * /1.0/operations/\<uuid\>/websocket
-     * /1.0/profiles
-       * /1.0/profiles/\<name\>
-
-# API details
-## /
-### GET
- * Description: List of supported APIs
- * Authentication: guest
- * Operation: sync
- * Return: list of supported API endpoint URLs
-
-Return value:
-
-    [
-        "/1.0"
-    ]
-
-## /1.0/
-### GET
- * Description: Server configuration and environment information
- * Authentication: guest, untrusted or trusted
- * Operation: sync
- * Return: Dict representing server state
-
-Return value (if trusted):
-
-    {
-        "api_extensions": [],                           # List of API extensions added after the API was marked stable
-        "api_status": "development",                    # API implementation status (one of, development, stable or deprecated)
-        "api_version": "1.0",                           # The API version as a string
-        "auth": "trusted",                              # Authentication state, one of "guest", "untrusted" or "trusted"
-        "config": {                                     # Host configuration
-            "core.trust_password": true,
-            "core.https_address": "[::]:8443"
-        },
-        "environment": {                                # Various information about the host (OS, kernel, ...)
-            "addresses": [
-                "1.2.3.4:8443",
-                "[1234::1234]:8443"
-            ],
-            "architectures": [
-                "x86_64",
-                "i686"
-            ],
-            "certificate": "PEM certificate",
-            "driver": "lxc",
-            "driver_version": "1.0.6",
-            "kernel": "Linux",
-            "kernel_architecture": "x86_64",
-            "kernel_version": "3.16",
-            "server": "lxd",
-            "server_pid": 10224,
-            "server_version": "0.8.1"}
-            "storage": "btrfs",
-            "storage_version": "3.19",
-        },
-        "public": false,                                # Whether the server should be treated as a public (read-only) remote by the client
-    }
-
-Return value (if guest or untrusted):
-
-    {
-        "api_extensions": [],                   # List of API extensions added after the API was marked stable
-        "api_status": "development",            # API implementation status (one of, development, stable or deprecated)
-        "api_version": "1.0",                   # The API version as a string
-        "auth": "guest",                        # Authentication state, one of "guest", "untrusted" or "trusted"
-        "public": false,                        # Whether the server should be treated as a public (read-only) remote by the client
-    }
-
-### PUT
- * Description: Updates the server configuration or other properties
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (replaces any existing config with the provided one):
-
-    {
-        "config": {
-            "core.trust_password": "my-new-password",
-            "storage.zfs_pool_name": "lxd"
-        }
-    }
-
-## /1.0/certificates
-### GET
- * Description: list of trusted certificates
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs for trusted certificates
-
-Return:
-
-    [
-        "/1.0/certificates/3ee64be3c3c7d617a7470e14f2d847081ad467c8c26e1caad841c8f67f7c7b09"
-    ]
-
-### POST
- * Description: add a new trusted certificate
- * Authentication: trusted or untrusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "type": "client",                       # Certificate type (keyring), currently only client
-        "certificate": "PEM certificate",       # If provided, a valid x509 certificate. If not, the client certificate of the connection will be used
-        "name": "foo"                           # An optional name for the certificate. If nothing is provided, the host in the TLS header for the request is used.
-        "password": "server-trust-password"     # The trust password for that server (only required if untrusted)
-    }
-
-## /1.0/certificates/\<fingerprint\>
-### GET
- * Description: trusted certificate information
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing a trusted certificate
-
-Output:
-
-    {
-        "type": "client",
-        "certificate": "PEM certificate"
-        "fingerprint": "SHA256 Hash of the raw certificate"
-    }
-
-### DELETE
- * Description: Remove a trusted certificate
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
-
-## /1.0/containers
-### GET
- * Description: List of containers
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs for containers this server publishes
-
-Return value:
-
-    [
-        "/1.0/containers/blah",
-        "/1.0/containers/blah1"
-    ]
-
-### POST
- * Description: Create a new container
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (container based on a local image with the "ubuntu/devel" alias):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
-                   "alias": "ubuntu/devel"},                                # Name of the alias
-    }
-
-Input (container based on a local image identified by its fingerprint):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
-                   "fingerprint": "SHA-256"},                               # Fingerprint
-    }
-
-Input (container based on most recent match based on image properties):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
-                   "properties": {                                          # Properties
-                        "os": "ubuntu",
-                        "release": "14.04",
-                        "architecture": "x86_64"
-                    }},
-    }
-
-Input (container without a pre-populated rootfs, useful when attaching to an existing one):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "none"},                                         # Can be: "image", "migration", "copy" or "none"
-    }
-
-Input (using a public remote image):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
-                   "mode": "pull",                                          # One of "local" (default) or "pull"
-                   "server": "https://10.0.2.3:8443",                       # Remote server (pull mode only)
-                   "protocol": "lxd",                                       # Protocol (one of lxd or simplestreams, defaults to lxd)
-                   "certificate": "PEM certificate",                        # Optional PEM certificate. If not mentioned, system CA is used.
-                   "alias": "ubuntu/devel"},                                # Name of the alias
-    }
-
-
-Input (using a private remote image after having obtained a secret for that image):
-
-    {
-        "name": "my-new-container",                                         # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                            # List of profiles
-        "ephemeral": true,                                                  # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                      # Config override.
-        "source": {"type": "image",                                         # Can be: "image", "migration", "copy" or "none"
-                   "mode": "pull",                                          # One of "local" (default) or "pull"
-                   "server": "https://10.0.2.3:8443",                       # Remote server (pull mode only)
-                   "secret": "my-secret-string",                            # Secret to use to retrieve the image (pull mode only)
-                   "certificate": "PEM certificate",                        # Optional PEM certificate. If not mentioned, system CA is used.
-                   "alias": "ubuntu/devel"},                                # Name of the alias
-    }
-
-Input (using a remote container, sent over the migration websocket):
-
-    {
-        "name": "my-new-container",                                                     # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                                        # List of profiles
-        "ephemeral": true,                                                              # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                                  # Config override.
-        "source": {"type": "migration",                                                 # Can be: "image", "migration", "copy" or "none"
-                   "mode": "pull",                                                      # Only "pull" is supported for now
-                   "operation": "https://10.0.2.3:8443/1.0/operations/<UUID>",          # Full URL to the remote operation (pull mode only)
-                   "certificate": "PEM certificate",                                    # Optional PEM certificate. If not mentioned, system CA is used.
-                   "base-image": "<fingerprint>",                                       # Optional, the base image the container was created from
-                   "secrets": {"control": "my-secret-string",                           # Secrets to use when talking to the migration source
-                               "criu":    "my-other-secret",
-                               "fs":      "my third secret"},
-    }
-
-Input (using a local container):
-
-    {
-        "name": "my-new-container",                                                     # 64 chars max, ASCII, no slash, no colon and no comma
-        "architecture": "x86_64",
-        "profiles": ["default"],                                                        # List of profiles
-        "ephemeral": true,                                                              # Whether to destroy the container on shutdown
-        "config": {"limits.cpu": "2"},                                                  # Config override.
-        "source": {"type": "copy",                                                      # Can be: "image", "migration", "copy" or "none"
-                   "source": "my-old-container"}                                        # Name of the source container
-    }
-
-
-## /1.0/containers/\<name\>
-### GET
- * Description: Container information
- * Authentication: trusted
- * Operation: sync
- * Return: dict of the container configuration and current state.
-
-Output:
-
-    {
-        "architecture": "x86_64",
-        "config": {
-            "limits.cpu": "3",
-            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
-            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
-        },
-        "created_at": "2016-02-16T01:05:05Z",
-        "devices": {
-            "rootfs": {
-                "path": "/",
-                "type": "disk"
-            }
-        },
-        "ephemeral": false,
-        "expanded_config": {    # the result of expanding profiles and adding the container's local config
-            "limits.cpu": "3",
-            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
-            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
-        },
-        "expanded_devices": {   # the result of expanding profiles and adding the container's local devices
-            "eth0": {
-                "name": "eth0",
-                "nictype": "bridged",
-                "parent": "lxcbr0",
-                "type": "nic"
-            },
-            "root": {
-                "path": "/",
-                "type": "disk"
-            }
-        },
-        "name": "my-container",
-        "profiles": [
-            "default"
-        ],
-        "stateful": false,      # If true, indicates that the container has some stored state that can be restored on startup
-        "status": "Running",
-        "status_code": 103
-    }
-
-
-### PUT
- * Description: update container configuration or restore snapshot
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (update container configuration):
-
-    {
-        "architecture": "x86_64",
-        "config": {
-            "limits.cpu": "4",
-            "volatile.base_image": "97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
-            "volatile.eth0.hwaddr": "00:16:3e:1c:94:38"
-        },
-        "devices": {
-            "rootfs": {
-                "path": "/",
-                "type": "disk"
-            }
-        },
-        "ephemeral": true,
-        "profiles": [
-            "default"
-        ]
-    }
-
-
-Takes the same structure as that returned by GET but doesn't allow name
-changes (see POST below) or changes to the status sub-dict (since that's
-read-only).
-
-Input (restore snapshot):
-
-    {
-        "restore": "snapshot-name"
-    }
-
-### POST
- * Description: used to rename/migrate the container
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Renaming to an existing name must return the 409 (Conflict) HTTP code.
-
-Input (simple rename):
-
-    {
-        "name": "new-name"
-    }
-
-Input (migration across lxd instances):
-    {
-        "migration": true
-    }
-
-The migration does not actually start until someone (i.e. another lxd instance)
-connects to all the websockets and begins negotiation with the source.
-
-Output in metadata section (for migration):
-
-    {
-        "control": "secret1",       # Migration control socket
-        "criu": "secret2",          # State transfer socket (only if live migrating)
-        "fs": "secret3"             # Filesystem transfer socket
-    }
-
-These are the secrets that should be passed to the create call.
-
-### DELETE
- * Description: remove the container
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
-
-## /1.0/containers/\<name\>/state
-### GET
- * Description: current state
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing current state
-
-    {
-        "type": "sync",
-        "status": "Success",
-        "status_code": 200,
-        "metadata": {
-            "status": "Running",
-            "status_code": 103,
-            "disk": {
-                "root": {
-                    "usage": 422330368
-                }
-            },
-            "memory": {
-                "usage": 51126272,
-                "usage_peak": 70246400,
-                "swap_usage": 0,
-                "swap_usage_peak": 0
-            },
-            "network": {
-                "eth0": {
-                    "addresses": [
-                        {
-                            "family": "inet",
-                            "address": "10.0.3.27",
-                            "netmask": "24",
-                            "scope": "global"
-                        },
-                        {
-                            "family": "inet6",
-                            "address": "fe80::216:3eff:feec:65a8",
-                            "netmask": "64",
-                            "scope": "link"
-                        }
-                    ],
-                    "counters": {
-                        "bytes_received": 33942,
-                        "bytes_sent": 30810,
-                        "packets_received": 402,
-                        "packets_sent": 178
-                    },
-                    "hwaddr": "00:16:3e:ec:65:a8",
-                    "host_name": "vethBWTSU5",
-                    "mtu": 1500,
-                    "state": "up",
-                    "type": "broadcast"
-                },
-                "lo": {
-                    "addresses": [
-                        {
-                            "family": "inet",
-                            "address": "127.0.0.1",
-                            "netmask": "8",
-                            "scope": "local"
-                        },
-                        {
-                            "family": "inet6",
-                            "address": "::1",
-                            "netmask": "128",
-                            "scope": "local"
-                        }
-                    ],
-                    "counters": {
-                        "bytes_received": 86816,
-                        "bytes_sent": 86816,
-                        "packets_received": 1226,
-                        "packets_sent": 1226
-                    },
-                    "hwaddr": "",
-                    "host_name": "",
-                    "mtu": 65536,
-                    "state": "up",
-                    "type": "loopback"
-                },
-                "lxcbr0": {
-                    "addresses": [
-                        {
-                            "family": "inet",
-                            "address": "10.0.3.1",
-                            "netmask": "24",
-                            "scope": "global"
-                        },
-                        {
-                            "family": "inet6",
-                            "address": "fe80::68d4:87ff:fe40:7769",
-                            "netmask": "64",
-                            "scope": "link"
-                        }
-                    ],
-                    "counters": {
-                        "bytes_received": 0,
-                        "bytes_sent": 570,
-                        "packets_received": 0,
-                        "packets_sent": 7
-                    },
-                    "hwaddr": "6a:d4:87:40:77:69",
-                    "host_name": "",
-                    "mtu": 1500,
-                    "state": "up",
-                    "type": "broadcast"
-               },
-               "zt0": {
-                    "addresses": [
-                        {
-                            "family": "inet",
-                            "address": "29.17.181.59",
-                            "netmask": "7",
-                            "scope": "global"
-                        },
-                        {
-                            "family": "inet6",
-                            "address": "fd80:56c2:e21c:0:199:9379:e711:b3e1",
-                            "netmask": "88",
-                            "scope": "global"
-                        },
-                        {
-                            "family": "inet6",
-                            "address": "fe80::79:e7ff:fe0d:5123",
-                            "netmask": "64",
-                            "scope": "link"
-                        }
-                    ],
-                    "counters": {
-                        "bytes_received": 0,
-                        "bytes_sent": 806,
-                        "packets_received": 0,
-                        "packets_sent": 9
-                    },
-                    "hwaddr": "02:79:e7:0d:51:23",
-                    "host_name": "",
-                    "mtu": 2800,
-                    "state": "up",
-                    "type": "broadcast"
-                }
-            },
-            "pid": 13663,
-            "processes": 32
-        }
-    }
-
-
-### PUT
- * Description: change the container state
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input:
-
-    {
-        "action": "stop",       # State change action (stop, start, restart, freeze or unfreeze)
-        "timeout": 30,          # A timeout after which the state change is considered as failed
-        "force": true,          # Force the state change (currently only valid for stop and restart where it means killing the container)
-        "stateful": true        # Whether to store or restore runtime state before stopping or startiong (only valid for stop and start, defaults to false)
-    }
-
-## /1.0/containers/\<name\>/files
-### GET (?path=/path/inside/the/container)
- * Description: download a file from the container
- * Authentication: trusted
- * Operation: sync
- * Return: Raw file or standard error
-
-The following headers will be set (on top of standard size and mimetype headers):
- * X-LXD-uid: 0
- * X-LXD-gid: 0
- * X-LXD-mode: 0700
-
-This is designed to be easily usable from the command line or even a web
-browser.
-
-### POST (?path=/path/inside/the/container)
- * Description: upload a file to the container
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
- * Standard http file upload
-
-The following headers may be set by the client:
- * X-LXD-uid: 0
- * X-LXD-gid: 0
- * X-LXD-mode: 0700
-
-This is designed to be easily usable from the command line or even a web
-browser.
-
-## /1.0/containers/\<name\>/snapshots
-### GET
- * Description: List of snapshots
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs for snapshots for this container
-
-Return value:
-
-    [
-        "/1.0/containers/blah/snapshots/snap0"
-    ]
-
-### POST
- * Description: create a new snapshot
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input:
-
-    {
-        "name": "my-snapshot",          # Name of the snapshot
-        "stateful": true                # Whether to include state too
-    }
-
-## /1.0/containers/\<name\>/snapshots/\<name\>
-### GET
- * Description: Snapshot information
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing the snapshot
-
-Return:
-
-    {
-        "architecture": "x86_64",
-        "config": {
-            "security.nesting": "true",
-            "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
-            "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8",
-            "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]",
-        },
-        "created_at": "2016-03-08T23:55:08Z",
-        "devices": {
-            "eth0": {
-                "name": "eth0",
-                "nictype": "bridged",
-                "parent": "lxcbr0",
-                "type": "nic"
-            },
-            "root": {
-                "path": "/",
-                "type": "disk"
-            },
-        },
-        "ephemeral": false,
-        "expanded_config": {
-            "security.nesting": "true",
-            "volatile.base_image": "a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
-            "volatile.eth0.hwaddr": "00:16:3e:ec:65:a8",
-            "volatile.last_state.idmap": "[{\"Isuid\":true,\"Isgid\":false,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536},{\"Isuid\":false,\"Isgid\":true,\"Hostid\":100000,\"Nsid\":0,\"Maprange\":65536}]",
-        },
-        "expanded_devices": {
-            "eth0": {
-                "name": "eth0",
-                "nictype": "bridged",
-                "parent": "lxcbr0",
-                "type": "nic"
-            },
-            "root": {
-                "path": "/",
-                "type": "disk"
-            },
-        },
-        "name": "zerotier/blah",
-        "profiles": [
-            "default"
-        ],
-        "stateful": false
-    }
-
-### POST
- * Description: used to rename/migrate the snapshot
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (rename the snapshot):
-
-    {
-        "name": "new-name"
-    }
-
-Input (setup the migration source):
-
-    {
-        "migration": true,
-    }
-
-Return (with migration=true):
-
-    {
-        "control": "secret1",       # Migration control socket
-        "fs": "secret3"             # Filesystem transfer socket
-    }
-
-Renaming to an existing name must return the 409 (Conflict) HTTP code.
-
-### DELETE
- * Description: remove the snapshot
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
-
-## /1.0/containers/\<name\>/exec
-### POST
- * Description: run a remote command
- * Authentication: trusted
- * Operation: async
- * Return: background operation + optional websocket information or standard error
-
-Input (run bash):
-
-    {
-        "command": ["/bin/bash"],       # Command and arguments
-        "environment": {},              # Optional extra environment variables to set
-        "wait-for-websocket": false,    # Whether to wait for a connection before starting the process
-        "interactive": true             # Whether to allocate a pts device instead of PIPEs
-    }
-
-`wait-for-websocket` indicates whether the operation should block and wait for
-a websocket connection to start (so that users can pass stdin and read
-stdout), or simply run to completion with /dev/null as stdin and stdout.
-
-If interactive is set to true, a single websocket is returned and is mapped to a
-pts device for stdin, stdout and stderr of the execed process.
-
-If interactive is set to false (default), three pipes will be setup, one
-for each of stdin, stdout and stderr.
-
-Depending on the state of the interactive flag, one or three different
-websocket/secret pairs will be returned, which are valid for connecting to this
-operations /websocket endpoint.
-
-Return (with wait-for-websocket=true and interactive=false):
-
-    {
-        "fds": {
-            "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21",
-            "1": "464dcf9f8fdce29d0d6478284523a9f26f4a31ae365d94cd38bac41558b797cf",
-            "2": "25b70415b686360e3b03131e33d6d94ee85a7f19b0f8d141d6dca5a1fc7b00eb",
-            "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5"
-        }
-    }
-
-Return (with wait-for-websocket=true and interactive=true):
-
-    {
-        "fds": {
-            "0": "f5b6c760c0aa37a6430dd2a00c456430282d89f6e1661a077a926ed1bf3d1c21",
-            "control": "20c479d9532ab6d6c3060f6cdca07c1f177647c9d96f0c143ab61874160bd8a5"
-        }
-    }
-
-
-When the exec command finishes, its exit status is available from the
-operation's metadata:
-
-    {
-        "return": 0
-    }
-
-## /1.0/containers/\<name\>/logs
-### GET
-* Description: Returns a list of the log files available for this container.
-  Note that this works on containers that have been deleted (or were never
-  created) to enable people to get logs for failed creations.
-* Authentication: trusted
-* Operation: Sync
-* Return: a list of the available log files
-
-Return:
-
-    [
-        "/1.0/containers/blah/logs/forkstart.log",
-        "/1.0/containers/blah/logs/lxc.conf",
-        "/1.0/containers/blah/logs/lxc.log"
-    ]
-
-## /1.0/containers/\<name\>/logs/\<logfile\>
-### GET
-* Description: returns the contents of a particular log file.
-* Authentication: trusted
-* Operation: N/A
-* Return: the contents of the log file
-
-### DELETE
-* Description: delete a particular log file.
-* Authentication: trusted
-* Operation: Sync
-* Return: empty response or standard error
-
-## /1.0/events
-This URL isn't a real REST API endpoint, instead doing a GET query on it
-will upgrade the connection to a websocket on which notifications will
-be sent.
-
-### GET (?type=operation,logging)
- * Description: websocket upgrade
- * Authentication: trusted
- * Operation: sync
- * Return: none (never ending flow of events)
-
-Supported arguments are:
- * type: comma separated list of notifications to subscribe to (defaults to all)
-
-The notification types are:
- * operation (notification about creation, updates and termination of all background operations)
- * logging (every log entry from the server)
-
-This never returns. Each notification is sent as a separate JSON dict:
-
-    {
-        "timestamp": "2015-06-09T19:07:24.379615253-06:00",                # Current timestamp
-        "type": "operation",                                               # Notification type
-        "metadata": {}                                                     # Extra resource or type specific metadata
-    }
-
-    {
-        "timestamp": "2016-02-17T11:44:28.572721913-05:00",
-        "type": "logging",
-        "metadata": {
-            "context": {
-                "ip": "@",
-                "method": "GET"
-                "url": "/1.0/containers/xen/snapshots",
-            },
-            "level": "info",
-            "message": "handling"
-        }
-    }
-
-
-## /1.0/images
-### GET
- * Description: list of images (public or private)
- * Authentication: guest or trusted
- * Operation: sync
- * Return: list of URLs for images this server publishes
-
-Return:
-
-    [
-        "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473",
-        "/1.0/images/97d97a3d1d053840ca19c86cdd0596cf1be060c5157d31407f2a4f9f350c78cc",
-        "/1.0/images/a49d26ce5808075f5175bf31f5cb90561f5023dcd408da8ac5e834096d46b2d8",
-        "/1.0/images/c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f"
-    ]
-
-### POST
- * Description: create and publish a new image
- * Authentication: trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input (one of):
- * Standard http file upload
- * Source image dictionary (transfers a remote image)
- * Source container dictionary (makes an image out of a local container)
- * Remote image URL dictionary (downloads a remote image)
-
-In the http file upload case, The following headers may be set by the client:
- * X-LXD-fingerprint: SHA-256 (if set, uploaded file must match)
- * X-LXD-filename: FILENAME (used for export)
- * X-LXD-public: true/false (defaults to false)
- * X-LXD-properties: URL-encoded key value pairs without duplicate keys (optional properties)
-
-In the source image case, the following dict must be used:
-
-    {
-        "filename": filename,                   # Used for export (optional)
-        "public": true,                         # Whether the image can be downloaded by untrusted users (defaults to false
-        "properties": {                         # Image properties (optional, applied on top of source properties)
-            "os": "Ubuntu"
-        },
-        "source": {
-            "type": "image",
-            "mode": "pull",                     # Only pull is supported for now
-            "server": "https://10.0.2.3:8443",  # Remote server (pull mode only)
-            "protocol": "lxd",                  # Protocol (one of lxd or simplestreams, defaults to lxd)
-            "secret": "my-secret-string",       # Secret (pull mode only, private images only)
-            "certificate": "PEM certificate",   # Optional PEM certificate. If not mentioned, system CA is used.
-            "fingerprint": "SHA256",            # Fingerprint of the image (must be set if alias isn't)
-            "alias": "ubuntu/devel",            # Name of the alias (must be set if fingerprint isn't)
-        }
-    }
-
-In the source container case, the following dict must be used:
-
-    {
-        "filename": filename,     # Used for export (optional)
-        "public":   true,         # Whether the image can be downloaded by untrusted users  (defaults to false)
-        "properties": {           # Image properties (optional)
-            "os": "Ubuntu"
-        },
-        "source": {
-            "type": "container",  # One of "container" or "snapshot"
-            "name": "abc"
-        }
-    }
-
-In the remote image URL case, the following dict must be used:
-
-    {
-        "filename": filename,                           # Used for export (optional)
-        "public":   true,                               # Whether the image can be downloaded by untrusted users  (defaults to false)
-        "properties": {                                 # Image properties (optional)
-            "os": "Ubuntu"
-        },
-        "source": {
-            "type": "url",
-            "url": "https://www.some-server.com/image"  # URL for the image
-        }
-    }
-
-
-After the input is received by LXD, a background operation is started
-which will add the image to the store and possibly do some backend
-filesystem-specific optimizations.
-
-## /1.0/images/\<fingerprint\>
-### GET (optional ?secret=SECRET)
- * Description: Image description and metadata
- * Authentication: guest or trusted
- * Operation: sync
- * Return: dict representing an image properties
-
-Output:
-
-    {
-        "aliases": [
-            {
-                "name": "trusty",
-                "description": "",
-            }
-        ],
-        "architecture": "x86_64",
-        "auto_update": true,
-        "cached": false,
-        "fingerprint": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473",
-        "filename": "ubuntu-trusty-14.04-amd64-server-20160201.tar.xz",
-        "properties": {
-            "architecture": "x86_64",
-            "description": "Ubuntu 14.04 LTS server (20160201)",
-            "os": "ubuntu",
-            "release": "trusty"
-        },
-        "update_source": {
-            "server": "https://10.1.2.4:8443",
-            "protocol": "lxd",
-            "certificate": "PEM certificate",
-            "alias": "ubuntu/trusty/amd64"
-        },
-        "public": false,
-        "size": 123792592,
-        "created_at": "2016-02-01T21:07:41Z",
-        "expires_at": "1970-01-01T00:00:00Z",
-        "last_used_at": "1970-01-01T00:00:00Z",
-        "uploaded_at": "2016-02-16T00:44:47Z"
-    }
-
-### DELETE
- * Description: Remove an image
- * Authentication: trusted
- * Operation: async
- * Return: background operaton or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
-
-### PUT
- * Description: Updates the image properties
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "auto_update": true,
-        "properties": {
-            "architecture": "x86_64",
-            "description": "Ubuntu 14.04 LTS server (20160201)",
-            "os": "ubuntu",
-            "release": "trusty"
-        },
-        "public": true,
-    }
-
-## /1.0/images/\<fingerprint\>/export
-### GET (optional ?secret=SECRET)
- * Description: Download the image tarball
- * Authentication: guest or trusted
- * Operation: sync
- * Return: Raw file or standard error
-
-The secret string is required when an untrusted LXD is spawning a new
-container from a private image stored on a different LXD.
-
-Rather than require a trust relationship between the two LXDs, the
-client will POST to /1.0/images/\<fingerprint\>/export to get a secret
-token which it'll then pass to the target LXD. That target LXD will then
-GET the image as a guest, passing the secret token.
-
-
-## /1.0/images/\<fingerprint\>/secret
-### POST
- * Description: Generate a random token and tell LXD to expect it be used by a guest
- * Authentication: guest or trusted
- * Operation: async
- * Return: background operation or standard error
-
-Input:
-
-    {
-    }
-
-Return:
-
-    {
-        "secret": "52e9ec5885562aa24d05d7b4846ebb8b5f1f7bf5cd6e285639b569d9eaf54c9b"
-    }
-
-Standard backround operation with "secret" set to the generated secret
-string in metadata.
-
-The secret is automatically invalidated 5s after an image URL using it
-has been accessed. This allows to both retried the image information and
-then hit /export with the same secret.
-
-## /1.0/images/aliases
-### GET
- * Description: list of aliases (public or private based on image visibility)
- * Authentication: guest or trusted
- * Operation: sync
- * Return: list of URLs for aliases this server knows about
-
-Return:
-
-    [
-        "/1.0/images/aliases/sl6",
-        "/1.0/images/aliases/trusty",
-        "/1.0/images/aliases/xenial"
-    ]
-
-### POST
- * Description: create a new alias
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "description": "The alias description",
-        "target": "SHA-256",
-        "name": "alias-name"
-    }
-
-## /1.0/images/aliases/\<name\>
-### GET
- * Description: Alias description and target
- * Authentication: guest or trusted
- * Operation: sync
- * Return: dict representing an alias description and target
-
-Output:
-    {
-        "name": "test",
-        "description": "my description",
-        "target": "c9b6e738fae75286d52f497415463a8ecc61bbcb046536f220d797b0e500a41f"
-    }
-
-### PUT
- * Description: Updates the alias target or description
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "description": "New description",
-        "target": "54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473"
-    }
-
-### POST
- * Description: rename an alias
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "name": "new-name"
-    }
-
-Renaming to an existing name must return the 409 (Conflict) HTTP code.
-
-### DELETE
- * Description: Remove an alias
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (none at present):
-
-    {
-    }
-
-## /1.0/networks
-### GET
- * Description: list of networks
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs for networks that are current defined on the host
-
-    [
-        "/1.0/networks/eth0",,
-        "/1.0/networks/lxcbr0"
-    ]
-
-## /1.0/networks/\<name\>
-### GET
- * Description: information about a network
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing a network
-
-    {
-        "name": "lxcbr0",
-        "type": "bridge",
-        "used_by": [
-            "/1.0/containers/blah"
-        ]
-    }
-
-## /1.0/operations
-### GET
- * Description: list of operations
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs for operations that are currently going on/queued
-
-    [
-        "/1.0/operations/c0fc0d0d-a997-462b-842b-f8bd0df82507",
-        "/1.0/operations/092a8755-fd90-4ce4-bf91-9f87d03fd5bc"
-    ]
-
-## /1.0/operations/\<uuid\>
-### GET
- * Description: background operation
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing a background operation
-
-Return:
-
-    {
-        "id": "b8d84888-1dc2-44fd-b386-7f679e171ba5",
-        "class": "token",                                                                       # One of "task" (background task), "websocket" (set of websockets and crendentials) or "token" (temporary credentials)
-        "created_at": "2016-02-17T16:59:27.237628195-05:00",                                    # Creation timestamp
-        "updated_at": "2016-02-17T16:59:27.237628195-05:00",                                    # Last update timestamp
-        "status": "Running",
-        "status_code": 103,
-        "resources": {                                                                          # List of affected resources
-            "images": [
-                "/1.0/images/54c8caac1f61901ed86c68f24af5f5d3672bdc62c71d04f06df3a59e95684473"
-            ]
-        },
-        "metadata": {                                                                           # Extra information about the operation (action, target, ...)
-            "secret": "c9209bee6df99315be1660dd215acde4aec89b8e5336039712fc11008d918b0d"
-        },
-        "may_cancel": true,                                                                     # Whether it's possible to cancel the operation (DELETE)
-        "err": ""
-    }
-
-### DELETE
- * Description: cancel an operation. Calling this will change the state to "cancelling" rather than actually removing the entry.
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
-
-## /1.0/operations/\<uuid\>/wait
-### GET (optional ?timeout=30)
- * Description: Wait for an operation to finish
- * Authentication: trusted
- * Operation: sync
- * Return: dict of the operation after it's reached its final state
-
-Input (wait indefinitely for a final state): no argument
-
-Input (similar but times out after 30s): ?timeout=30
-
-## /1.0/operations/\<uuid\>/websocket
-### GET (?secret=SECRET)
- * Description: This connection is upgraded into a websocket connection
-   speaking the protocol defined by the operation type. For example, in the
-   case of an exec operation, the websocket is the bidirectional pipe for
-   stdin/stdout/stderr to flow to and from the process inside the container.
-   In the case of migration, it will be the primary interface over which the
-   migration information is communicated. The secret here is the one that was
-   provided when the operation was created. Guests are allowed to connect
-   provided they have the right secret.
- * Authentication: guest or trusted
- * Operation: sync
- * Return: websocket stream or standard error
-
-## /1.0/profiles
-### GET
- * Description: List of configuration profiles
- * Authentication: trusted
- * Operation: sync
- * Return: list of URLs to defined profiles
-
-Return:
-
-    [
-        "/1.0/profiles/default"
-    ]
-
-
-### POST
- * Description: define a new profile
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "name": "my-profilename",
-        "description": "Some description string",
-        "config": {
-            "limits.memory": "2GB"
-        },
-        "devices": {
-            "kvm": {
-                "type": "unix-char",
-                "path": "/dev/kvm"
-            }
-        }
-    }
-
-## /1.0/profiles/\<name\>
-### GET
- * Description: profile configuration
- * Authentication: trusted
- * Operation: sync
- * Return: dict representing the profile content
-
-Output:
-
-    {
-        "name": "test",
-        "description": "Some description string",
-        "config": {
-            "limits.memory": "2GB"
-        },
-        "devices": {
-            "kvm": {
-                "path": "/dev/kvm",
-                "type": "unix-char"
-            }
-        }
-    }
-
-### PUT
- * Description: update the profile
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input:
-
-    {
-        "config": {
-            "limits.memory": "4GB"
-        },
-        "description": "Some description string",
-        "devices": {
-            "kvm": {
-                "path": "/dev/kvm",
-                "type": "unix-char"
-            }
-        }
-    }
-
-Same dict as used for initial creation and coming from GET. The name
-property can't be changed (see POST for that).
-
-
-### POST
- * Description: rename a profile
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (rename a profile):
-
-    {
-        "name": "new-name"
-    }
-
-
-HTTP return value must be 204 (No content) and Location must point to
-the renamed resource.
-
-Renaming to an existing name must return the 409 (Conflict) HTTP code.
-
-
-### DELETE
- * Description: remove a profile
- * Authentication: trusted
- * Operation: sync
- * Return: standard return value or standard error
-
-Input (none at present):
-
-    {
-    }
-
-HTTP code for this should be 202 (Accepted).
diff --git a/specs/storage-backends.md b/specs/storage-backends.md
deleted file mode 100644
index 4b4ce0e..0000000
--- a/specs/storage-backends.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Storage Backends and supported functions
-## Feature comparison
-
-LXD supports using plain dirs, Btrfs, LVM, and ZFS for storage of images and containers.  
-Where possible, LXD tries to use the advanced features of each system to optimize operations.
-
-Feature                                     | Directory | Btrfs | LVM   | ZFS
-:---                                        | :---      | :---  | :---  | :---
-Optimized image storage                     | no        | yes   | yes   | yes
-Optimized container creation                | no        | yes   | yes   | yes
-Optimized snapshot creation                 | no        | yes   | yes   | yes
-Optimized image transfer                    | no        | yes   | no    | yes
-Optimized container transfer                | no        | yes   | no    | yes
-Copy on write                               | no        | yes   | yes   | yes
-Block based                                 | no        | no    | yes   | no
-Instant cloning                             | no        | yes   | yes   | yes
-Nesting support                             | yes       | yes   | no    | no
-Restore from older snapshots (not latest)   | yes       | yes   | yes   | no
-Storage quotas                              | no        | yes   | no    | yes
-
-## Mixed storage
-When switching storage backend after some containers or images already exist, LXD will create any new container  
-using the new backend and converting older images to the new backend as needed.
-
-## Non-optimized container transfer
-When the filesystem on the source and target hosts differs or when there is no faster way,  
-rsync is used to transfer the container content across.
-
-## Notes
-### Directory
-
- - The directory backend is the fallback backend when nothing else is configured or detected.
- - While this backend is fully functional, it's also much slower than
-   all the others due to it having to unpack images or do instant copies of
-   containers, snapshots and images.
-
-### Btrfs
-
- - The btrfs backend is automatically used if /var/lib/lxd is on a btrfs filesystem.
- - Uses a subvolume per container, image and snapshot, creating btrfs snapshots when creating a new object.
-
-### LVM
-
- - A LVM VG must be created and then storage.lvm\_vg\_name set to point to it.
- - If a thinpool doesn't already exist, one will be created, the name of the thinpool can be set with storage.lvm\_thinpool\_name .
- - Uses LVs for images, then LV snapshots for containers and container snapshots.
- - The filesystem used for the LVs is ext4 (can be configured to use xfs instead).
- - LVs are created with a default size of 10GiB (can be configured through).
-
-### ZFS
-
- - LXD can use any zpool or part of a zpool. storage.zfs\_pool\_name must be set to the path to be used.
- - ZFS doesn't have to (and shouldn't be) mounted on /var/lib/lxd
- - Uses ZFS filesystems for images, then snapshots and clones to create containers and snapshots.
- - Due to the way copy-on-write works in ZFS, parent filesystems can't
-   be removed until all children are gone. As a result, LXD will
-   automatically rename any removed but still referenced object to a random
-   deleted/ path and keep it until such time the references are gone and it
-   can safely be removed.
- - ZFS as it is today doesn't support delegating part of a pool to a
-   container user. Upstream is actively working on this.
- - ZFS doesn't support restoring from snapshots other than the latest
-   one. You can however create new containers from older snapshots which
-   makes it possible to confirm the snapshots is indeed what you want to
-   restore before you remove the newer snapshots.
diff --git a/specs/userns-idmap.md b/specs/userns-idmap.md
deleted file mode 100644
index a244f65..0000000
--- a/specs/userns-idmap.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Introduction
-LXD runs safe containers. This is achieved mostly through the use of
-user namespaces which make it possible to run containers unprivileged,
-greatly limiting the attack surface.
-
-User namespaces work by mapping a set of uids and gids on the host to a
-set of uids and gids in the container.
-
-
-For example, we can define that the host uids and gids from 100000 to
-165535 may be used by LXD and should be mapped to uid/gid 0 through
-65535 in the container.
-
-As a result a process running as uid 0 in the container will actually be
-running as uid 100000.
-
-Allocations should always be of at least 65536 uids and gids to cover
-the POSIX range including root (0) and nobody (65534).
-
-
-To simplify things, at this point, we will only deal with identical
-allocations for uids and gids and only support a single contiguous range
-per container.
-
-# Kernel support
-User namespaces require a kernel >= 3.12, LXD will start even on older
-kernels but will refuse to start containers.
-
-# Allowed ranges
-On most hosts, LXD will check /etc/subuid and /etc/subgid for
-allocations for the "lxd" user and on first start, set the default
-profile to use the first 65536 uids and gids from that range.
-
-If the range is shorter than 65536 (which includes no range at all),
-then LXD will fail to create or start any container until this is corrected.
-
-If some but not all of /etc/subuid, /etc/subgid, newuidmap (path lookup)
-and newgidmap (path lookup) can't be found on the system, LXD will fail
-the startup of any container until this is corrected as this shows a
-broken shadow setup.
-
-If none of those 4 files can be found, then LXD will assume it's running
-on a host using an old version of shadow. In this mode, LXD will assume
-it can use any uids and gids above 65535 and will take the first 65536
-as its default map.
-
-# Varying ranges between hosts
-The source map is sent when moving containers between hosts so that they
-can be remapped on the receiving host.


More information about the lxc-devel mailing list