Server

Revision 3 as of 2013-05-02 21:35:37

Clear message

Server side

Introduction

The update server is where all the clients connect to to get the list of available updates. Updates are split into channels and devices. The client can query the list of channels and then grab an index file for their specific model.

The server has been designed to be dumm, all the files are generated statically and so the server can be easily mirrored if needed.

Files

/channels.json

The channels file lists the list of channels and for each a dict mapping the various devices to per-device json indexes.

Structure: Dict keyed by channel name containing a dict keyed by device model each containing a dict containg the path to the index AND OPTIONALY a link to the device GPG keyring.

Example:

{
    "daily": {
        "nexus7": {
            "index": "/daily/nexus7/index.json",
            "keyring": "/daily/nexus7/keyring.gpg"
        },
        "nexus4":{
            "index": "/daily/nexus4/index.json"
        }
    },
    "stable": {
        "nexus7":{
            "index": "/stable/nexus7/index.json"
        }
    }
}

/<channel>/<model>/index.json

The index contains the list of all available updates for a given device. It's that file that's used to figure out an upgrade path.

Structure (dict containing the following keys):

  • global - dict of global variables
    • generated_at - Date at which the index was generated, output of "date -u" (string, mandatory)
  • images - List of dicts representing available images
    • base - Base version for a delta image (mandatory, for delta images only)
    • bootme - Flag to tell the downloader that a reboot is required in order to apply the update (boolean, optional, default to false)
    • description - Description string for the image (string, mandatory)
    • description-ll (eg. description-en) - Translated description string for the image (string, optional)
    • description-ll_CC (eg. description-en_US) - Translated description string for the image (string, optional)
    • files - List of dicts representing files that are part of the updates (list, mandatory)
      • checksum - SHA1 sum of the file (string, mandatory)
      • order - Used to sort the different files passed to the upgrader (integer, mandatory)
      • path - Relative path or URL to the actual file (string, mandatory)
      • signature - Relative path or URL to the GPG signature for the file (string, mandatory)
      • size - Size of the file in bytes (integer, mandatory)
    • minversion - Minimum version of the previous installed system to update from (integer, optional, for full images only, default to 0)
    • type - Image type (string, mandatory, one of "full" or "delta")
    • version - Version number for the image (integer, mandatory)

/<channel>/<some-path>/<some-file>.tar.xz

WARNING: The actual layout depends on the upgrader and the target platform. The tarball layout for the initial implementation hasn't been fixed yet so this section is subject to change. An update file, the format for update files is the same for full and delta images.

The following files/directories may be found inside:

  • <partition>/files/* - fs structure containing all the files that need to be copied to the partition

  • <partition>/removed - list of files to remove on the partition

  • META-DATA - Update data, containing the list of actions the upgrader needs to perform

Number of files included in an update

An update can contain any number of files, all will be applied sequentially, sorted by the order field.

For Ubuntu-generated images, we expect to use 3 files:

  • hardware-dependent - contains the hardware specific bits (android system, boot partition, recovery partition, ...)
  • hardware-independent - contains the common bits between devices (ubuntu rootfs)
  • version - contains a single file, ubuntu:/etc/ubuntu-build (containing the build number)

Those images will always include at least two files, one hardware-dependent or hardware-independent and one containing the updated version file.

This is done so that the hardware-independent may be shared acroos a large number of supported devices and so that the hardware-dependent bit may be shared across update channels. The benefit from this is massive space saving on the server side (compared to having a single file containing everything).

Carrier/OEM may choose to build a single file containing the equivalent of our 3 files. There's no restriction in the number of files that can be applied by the upgrader and there's no special-casing based on the file content.

Security

To ensure nobody may intercept the traffic to our update server and send fake or old updates back to the client, the design includes various measures to ensure the security of our updates:

  • channels.json and index.json MUST be retrieved over HTTPs. This is to avoid someone intercepting HTTP trafic and pushing an older copy of the update server.
  • channels.json and index.json are GPG signed (detacted armored signature as <filename>.asc), those MUST be checked by the client

  • The SHA1 of the update files is included in the index and MUST be checked by the client to validate the authenticity and integrity of the files (unless the client does GPG validation on the file).
  • The update files are also GPG signed (detached armored signature as <filename>.asc), those CAN be checked by the client and MUST be checked by the upgrader.

Details on the GPG trust path and key update/revocation process may be found in the separate GPG wiki page.

Requirements

  • Static web server
  • SSL certificate (to retrieve the JSON indexes)

Code

Versioning

The update version needs to be an integer so that it's easily sortable, the recommended format is YYYYMMXX (20130500 for the first image of May, 20130501 for the second).