Results 1 to 10 of 39

Thread: Creating a Trusted Local Repository from which Software Updates can be installed.

Threaded View

  1. #1
    Join Date
    Jan 2006
    Boom, Belgium
    Ubuntu 10.04 Lucid Lynx

    Creating a Trusted Local Repository from which Software Updates can be installed.


    If you manage multiple PCs running Ubuntu, you will likely want to keep them all updated. Thus, you will want to install the Ubuntu updates to each of them as they become available, and you will have each PC individually download all of the updates from the Ubuntu repositories on the internet. This may, however, be impractical to you—particularly if, e.g., you are on a rather slow internet connection, or if your monthly data transfer volume is severely limited, or if you simply prefer to save the bandwidth.

    If you would like to download the updates just once, and further distribute the downloaded files locally, you can set up a Local Repository. Basically, a "repository" is a directory that contains a set of software packages (i.e., ".deb" files, in the case of Debian-based distributions—such as Ubuntu), plus an index file that lists the packages that are available in the directory. Such a repository, however, is considered "untrusted": the software installer (i.e., the "APT" system—which includes the "apt-get" command, the "Synaptic Package Manager," the "Update Manager," etc.) will ignore any package that is present in the repository whenever another copy of the package is available in another, trusted, repository—i.e., most likely, on the internet. To create a trusted repository, you need to take a few extra steps, in addition to creating the index file:
    • Create a "release" file, which is a small text file that contains, among other details, a checksum for the index file;
    • Generate a digital signature for the release file, to prevent tampering by unauthorised individuals.

    Whenever the software installer attempts to use the trusted repository, it will verify if the digital signature for the release file is correct—i.e., if it corresponds to the current contents of the file. If the digital signature is correct, then the installer will trust the contents of the release file—which includes the checksum for the index file. If, subsequently, that checksum corresponds to the current contents of the index file, then the contents of that file can be trusted as well. Finally, the index file includes a checksum for each of the packages made available by the repository, so the packages themselves can be verified too.

    Thus, before you can set up a trusted local repository, you will have to make sure that you can generate a digital signature for its release file. To that end, you will have to create a "GPG Key Pair" for yourself, and register it (or, more precisely, its public key part) as a trusted key for APT to use—so that APT can verify any digital signatures that are generated with this key pair (or, more precisely, with its private key part).

    Step 1: Generating your GPG Key Pair.

    To generate a GPG key pair, start the following command:
    gpg --gen-key
    After some introductory text, the program will ask you which type of key you want to create:
    Please select what kind of key you want:
       (1) DSA and Elgamal (default)
       (2) DSA (sign only)
       (5) RSA (sign only)
    Since you will be using your key only for generating digital signatures, you don't need option 1, "DSA and Elgamal," (although it will work fine), but you can get by with a "sign only" key—i.e., option 2, "DSA," or option 5, "RSA." Of these two, RSA is the more powerful, so I suggest you select that:
    Your selection? 5
    If you opt for an RSA key, the program will next ask you what size you want for the key; for maximum security, you will most likely want the longest possible key—i.e., 4096 bits (however, longer keys will require more computing resources, so you may prefer a shorter key if your computer is not all too powerful):
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 4096
    Next, the program will ask you if you want to attach an expiration date to the key; if you don't, then the key will remain valid indefinitely:
    Please specify how long the key should be valid.
             0 = key does not expire
          <n>  = key expires in n days
          <n>w = key expires in n weeks
          <n>m = key expires in n months
          <n>y = key expires in n years
    For a high-risk key (e.g., a key that you will use to digitally prove your identity), it may be critical to set an appropriate expiration date, but the type of key that you are currently generating doesn't really need an expiration date. The default option—i.e., a key that won't expire—is, therefore, perfectly acceptable. Alternatively, you may prefer the key to expire in, say, 5 years or so:
    Key is valid for? (0) 5y
    The program will show you the expiration date and time for the key, and ask you to confirm if that is what you want:
    Key expires at Thu 06 Mar 2014 21:12:03 CET
    Is this correct? (y/N) Y
    Now it's time to specify the "user id" for your new key:
    You need a user ID to identify your key; the software constructs the user ID
    from the Real Name, Comment and E-mail Address in this form:
        "Heinrich Heine (Der Dichter) <>"
    The program will ask you for the following three items:
    • Real name
      For a key that you will use to prove your identity, you should specify your own real name here.
      In this case, however, you should really avoid using your own name. Technically, you can give the key any name that you like—even something totally unrelated to the function of the key, like "Bart Bogus" or "Teri Hatcher is the Greatest!" or even "Who the Hell is Teri Hatcher, anyway?" will do.
      Since you will be using the key to sign your local Ubuntu repository, you should probably name it "Local Ubuntu Repository" or (if you want to mention the specific Ubuntu release for which you will be using the key) "Local Ubuntu Intrepid Ibex Repository" or some such.
    • E-mail address
      You needn't specify an e-mail address for this key.
    • Comment
      You needn't specify a comment either.

    So, for example:
    Real name: Local Ubuntu Intrepid Ibex Repository
    E-mail address:
    You selected this USER-ID:
        "Local Ubuntu Intrepid Ibex Repository"
    You will get a chance to modify the user id; if you're satisfied with what you entered, then select Okay to continue:
    Change (N)ame, (C)omment, (E)-mail or (O)kay/(Q)uit? O
    At this point, the program has all the data that it needs to generate your new key. The key will actually consist of two parts:
    • A private (or secret) key—which (as the name suggests) you should keep secret, to prevent "digital identity theft."
      In this case, you don't really reveal your identity, but anyone who gains access to your secret key will be able to create falsely "trusted" software repositories that could be installed on any computer that knows about your key.
    • A public key—which you are supposed to distribute to anyone who should be able to verify your identity.
      In this particular case, you will add this public key to the list of trusted keys on any computer on which you want to install the packages from your local repository.

    It should be obvious that the secret key should really be kept secret. Therefore, the program will ask you for a "passphrase" (or "password"), which will protect your secret key:
    You need a Passphrase to protect your secret key.
    Enter passphrase:
    Select a sufficiently complex passphrase, but one that you can remember—if you ever forget it, then you will lose access to your secret key, and you will no longer be able to generate any digital signatures with it.

    You will have to repeat your passphrase:
    Repeat passphrase:
    Finally, the program will begin to compute your new key pair:
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, use the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    You should really follow the advice that the program gives you, and keep your system busy. If you don't, then the program will complain that it cannot generate enough random bytes for your key—and it will make you wait until it can:
    Not enough random bytes available.  Please do some other work to give
    the OS a chance to collect more entropy!  (Need 182 more bytes)
    Once your new key pair is ready, the program will produce the following output:
    gpg: /home/luvr/.gnupg/trustdb.gpg: trustdb created
    gpg: key xxxxxxxx marked as ultimately trusted
    public and secret key created and signed.
    gpg: checking the trustdb
    gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
    gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
    gpg: next trustdb check due at 2014-03-06
    pub   4096R/xxxxxxxx 2009-03-07 [expires: 2014-03-06]
          Key fingerprint = xxxx xxxx xxxx xxxx xxxx  xxxx xxxx xxxx xxxx xxxx
    uid                  Local Ubuntu Intrepid Ibex Repository
    Note that this key cannot be used for encryption.  You may want to use
    the command "--edit-key" to generate a subkey for this purpose.
    The bold, underlined and coloured text, xxxxxxxx, represents the "key id"—which you will have to specify when you export the (public) key, next.


    You can list your keys at any time, with the following command:
    gpg --list-keys
    The output will include the key id, as shown below:
    pub   4096R/xxxxxxxx 2009-03-07 [expires: 2014-03-06]
    uid                  Local Ubuntu Intrepid Ibex Repository

    Step 2: Exporting your newly generated Public Key.

    Now that your GPG key pair is ready, you will have to export the public key to a text file, using the following command:
    gpg --output pubkey-export-file --armor --export xxxxxxxx
    You should, obviously, replace the pubkey-export-file parameter string with an appropriate name for the output file. Furthermore, the xxxxxxxx parameter represents the key id, as discussed above.

    Step 3: Importing your Public Key into the APT List of Trusted Keys.


    You will have to perform this step on every computer on which you want to install software packages from your (yet to be created) local software repository.
    You can perform this step at any time, and on as many computers as you deem appropriate.

    Make sure that you have the pubkey-export-file (which you created in Step 2, above) available, and execute the following command to import it into the list of keys that will be trusted by APT:
    sudo apt-key add  pubkey-export-file

    To verify if the key was successfully imported into APT, you can run the following command:
    sudo apt-key list
    Alternatively, you could start the "Software Sources" utility (from the "System""Administration" menu) and display its "Authentication" tab page.
    Moreover, you can also start the "Software Sources" utility from within the "Synaptic Package Manager," through its "Settings""Repositories" menu.

    Step 4: Installing the Debian Package Development Tools.

    Return to the computer on which you generated your key pair (i.e., where you ran steps 1 and 2 above).

    Execute the following command to install the Debian Package Development Tools:
    sudo apt-get install dpkg-dev
    Once this package is installed, you will be able to create software package repositories on this system.

    Step 5: Creating the Directory Structure for your Local Repository.

    You will be setting up a simple repository—i.e., one that consists of just one directory. Complex repositories, consisting of a deeper directory hierarchy, are out of the scope of this document.

    As an example, the following commands will create a "LocalRepository" subdirectory under your personal home directory,
    mkdir LocalRepository
    cd LocalRepository
    (The first "cd" command will set your current directory to your home location, after which the second command will create the "LocalRepository" subdirectory, and the third command will enter the newly created directory.)

    To kickstart your new local repository, you can load it with the software packages that you have recently installed. Whenever you install new software or updates through APT, the required packages will be loaded into the APT cache—i.e., the "/var/cache/apt/archives" directory on your system. You can now copy these packages to your local repository:
    cp /var/cache/apt/archives/*.deb .
    (Notice the lone dot (".") at the end of this command—it is required, and is a placeholder for the "current directory." The command effectively copies all Debian packages from the APT cache into your current directory—i.e., into your local repository.)


    If your APT cache does not contain any packages, then be sure to verify the "Temporary Files" setting in the "Synaptic Package Manager," as follows:
    • Open "Synaptic Package Manager" ("System""Administration""Synaptic Package Manager");
    • Display its "Preferences" dialogue ("Settings""Preferences");
    • Display the "Files" tab page;
    • Under the "Temporary Files" header, ensure that either "Leave all downloaded packages in the cache" or "Only delete packages which are no longer available" is selected.

    Step 6: Creating the Index File for your Local Repository.

    Once your local repository contains all the packages that you want to make available through it, you are ready to create the index file for the repository. To that end, run the following command:
    dpkg-scanpackages . /dev/null > Packages
    This will create a text file, "Packages," which is the plain-text, uncompressed version of the index file. You should also create a compressed version of the index file, using the following command:
    gzip -9c Packages > Packages.gz
    This will create the compressed version, "Packages.gz," of the index file, without deleting the original, uncompressed file.

    Step 7: Creating the Release File for your Local Repository.

    The release file is a small text file that should contain:
    • A header.
      A detailed description of the format of this section is out of the scope of this document, but the following is a simple example of a perfectly valid header:
      Archive: intrepid
      Origin: Ubuntu
      Label: Local Ubuntu Intrepid Repository
      Architecture: i386
    • Two detail lines—one for the uncompressed "Packages" file, and one for the compressed "Packages.gz" file. The detail lines should be formatted as follows:
      • One blank space;
      • The MD5 checksum for the file, as calculated by the "md5sum" command;
      • One blank space;
      • The size, in bytes, of the file, right-aligned and padded to the left with blanks, in a 16-character field;
      • One blank space;
      • The name of the file.

      The following example shows two valid detail lines:
       d8cd948e0371a338025d3d99f5f9f304           454617 Packages
       7e43f7e45a7f49dbb01e659c25997446           109619 Packages.gz

    Obviously, it would be an awfully error-prone process if you were to try and manually type in these lines. Hence, an automated process is highly desirable—and, fortunately, not too hard to develop. For example, you can construct the command to generate the detail line for the "Packages" file as follows:
    • To calculate the MD5 checksum, run the "md5sum" command:
      $ md5sum Packages
      d8cd948e0371a338025d3d99f5f9f304  Packages
    • You should keep only the checksum value, and drop the file name from the output of the "md5sum" command. To that end, pipe the output through the "cut" command, keeping only the first blank-delimited field:
      $ md5sum Packages | cut --delimiter=' ' --fields=1
    • To obtain the size of the file, you can use the "wc" command with the "--bytes" option:
      $ wc --bytes Packages
      454617 Packages
    • Again, you need keep only the first blank-delimited field of the output:
      $ wc --bytes Packages | cut --delimiter=' ' --fields=1
    • To generate the properly formatted output line, you can use the "printf" command.
      The checksum can be inserted directly into the format string thanks to the "$(...command...)" construct supported by the shell; for the file size, the format string can specify a 16-character decimal number field, and the value can be given as an argument to be substituted into the format string:
      $ printf ' '$(md5sum Packages | cut --delimiter=' ' --fields=1)' %16d Packages\n' \
      > $(wc --bytes Packages | cut --delimiter=' ' --fields=1)
       d8cd948e0371a338025d3d99f5f9f304           454617 Packages

    Based on the above description, the following is a command sequence to fully automate the creation of the release file. To generate the header, a so-called "here" document is used--i.e., the input text is copied directly into the command sequence, with a specified marker string (in this case, "EOF") used to mark the end of the document.
    cat > Release <<EOF
    Archive: intrepid
    Origin: Ubuntu
    Label: Local Ubuntu Intrepid Repository
    Architecture: i386
    printf ' '$(md5sum Packages | cut --delimiter=' ' --fields=1)' %16d Packages\n' \
       $(wc --bytes Packages | cut --delimiter=' ' --fields=1) >> Release
    printf ' '$(md5sum Packages.gz | cut --delimiter=' ' --fields=1)' %16d Packages.gz' \
       $(wc --bytes Packages.gz | cut --delimiter=' ' --fields=1) >> Release
    Step 8: Generating the Digital Signature for the Release File.

    The digital signature for the release file should be written to a file named "Release.gpg," using the following command:
    gpg --armor --detach-sign --output Release.gpg Release
    With this step, your local repository is ready for use.

    Step 9: Adding your Local Repository as an APT Source.

    Now that your local repository is fully set up, you can copy it to any computer on which you want to use it, and add it to its APT source configuration file, "/etc/apt/sources.list."

    You will need root privileges to edit the "/etc/apt/sources.list." file—therefore, if you want to start up your text editor (e.g., "gedit") from a terminal, you should run the command as follows:
    sudo gedit /etc/apt/sources.list
    Alternatively, you can start the text editor from the GNOME desktop environment by pressing <Alt>-<F2> to display the "Run Application" dialog, and typing the following command:
    gksudo gedit /etc/apt/sources.list
    At the top of the file, add a definition for the local repository, as follows:
    deb   file:///home/luvr/LocalRepository   /
    (Note that you should, of course, specify the correct path to your repository on the "file://" protocol.)

    Finally, you should let APT update its internal package index:
    sudo apt-get update
    (Alternatively, you can execute the "Reload" function in "Synaptic Package Manager.")

    Epilogue: Keeping your Local Repository Up-To-Date.

    From now on, whenever you perform any further software installations through APT, you should perform the following steps to keep your local repository updated:
    • Copy the downloaded packages from the APT cache to your local repository;
    • Recreate the repository index and release files, and generate a new digital signature.

    To fully automate this process, you can execute the "update-repository" script file, which you can find attached as a zip archive file to this post.


    Attached Files Attached Files
    Last edited by luvr; September 23rd, 2010 at 06:30 PM. Reason: Added a link to my post about creating a trusted Ubuntu mirror from a set of Ubuntu Repository DVDs


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts