View: HTML | Text | PS | PDF | RTF | Wiki | DocBook | DocBook Inline | changelog | about this header Circle Jeff Boweron  
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML v4.5//EN" "/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
<article lang="en">
  <articleinfo>
    <keywordset>
      <keyword>ubuntu</keyword>
      <keyword>ppa</keyword>
      <keyword>launchpad</keyword>
      <keyword>configure</keyword>
      <keyword>setup</keyword>
    </keywordset>
    <title>Configuring a Simple Launchpad PPA</title>
    <abstract>
      <para>
This document describes how to setup a simple Launchpad PPA for your projects.
</para>
    </abstract>
  </articleinfo>
  <section id="what-is-ppa">
    <title>What is a PPA? (and why do I want one?)</title>
    <para>
A PPA is a Personal Package Archive.  Essentially when you do <command>apt-get install cool-stuff</command> you're pulling information from a public repository of code and compiled binaries.  If you've written your own code you may want to share it with the world and a PPA is a great way to do this, using the familiar <command>apt-get</command> mechanisms Debian-based users have come to know and love.
</para>
    <para>
A PPA is a great way to share files with people, but only certain types of files.  It's designed to distribute code and binaries to a broad audience, if you want to share a video of your kid's birthday party you'd still be better off with email or a file sharing service (or, even better, just run <command>cp birthday /dev/null</command> since most parents vastly overestimate how much other people like those videos...).  On the other hand, if you've written a nifty script that transmorgifies your framus widgets automatically and you think other people may be interested a PPA is a good way to go.
</para>
    <section id="ppa-vs-deb">
      <title>How is a PPA different from a .DEB file?</title>
      <para>
Many of you have probably downloaded and installed <filename>.deb</filename> files.  These files are nice in that they can install an application and take care of dependencies just like a PPA can, but there is a big difference between them and a PPA.
</para>
      <para>
The biggest difference is that a PPA will not only install an application, but it will also keep that application up-to-date for you.  When you own a PPA and push out a new release, anyone who subscribes to your PPA will be notified and offered the download.  With a <filename>.deb</filename> it's a one-time operation.  People who install your application will need to check your website for updates (or you can build that into the application itself).
</para>
      <para>
PPAs are also a bit more secure.  Anyone can make a <filename>.deb</filename> file and it can do anything - especially since typically you'll install it with <command>sudo dpkg -i coolstuff.deb</command> giving it superuser privileges.  A PPA is signed and controlled, anything in my PPA has been uploaded by someone with access to my GPG key and the password I use to lock it.  Anyone could create <filename>google-chrome.deb</filename> that downloads and installs Google Chrome but also installs malware to do whatever they want.  Now, I can also do the same thing with my PPA but at least then the PPA is traceable to me and Launchpad can terminate my account and/or turn my IP information over to the authorities so they can investigate.
</para>
      <para>
Finally, PPAs tend to be for open source stuff.  My scripts are all based on the Apache license which I find to be a bit more free than GPL - this means that anyone can look at my scripts, modify them, and use them as they see fit.  It also means that anyone who spots me doing anything bad can report it - whether "bad" is a mistake like running a command a root when I can get away with running it as another user or "bad" is malicious like sending all of your <filename>~/Documents</filename> to my personal webserver in the background.  There's nothing about a PPA that says I can't include pre-compiled binaries, but you can bet that popular PPAs that include them get a lot more scrutiny than the ones that are open source.
</para>
    </section>
  </section>
  <section id="launchpad">
    <title>Configure Launchpad</title>
    <para>
The first thing you'll need to do is setup your Launchpad account.  Some of you may already have one of these so some steps may be redundant.  For example, when I decided to setup my PPA I already had an account, had signed the Code of Conduct, and had secured my OpenPGP key with one-way encryption by forgetting the passphrase.
</para>
    <section id="launchpad-signup">
      <title>Sign up for a Launchpad Account</title>
      <para>
First, get a <ulink url="http://launchpad.net">Launchpad</ulink> account.  This is quick, easy to do, costs zero dollars and only requires an annual fee of nothing.  I think they have financing available for those who qualify...  Getting a Launchpad account should be pretty simple, there's a link in the upper right to sign-in or register and you should be able to figure out what to do from there.
</para>
    </section>
    <section id="get-keys">
      <title>Create and Publish GPG/PGP Keys</title>
      <para>
After you sign up, you'll need to create a GPG/PGP key.  Launchpad has a <ulink url="https://help.launchpad.net/YourAccount/ImportingYourPGPKey">nice tutorial</ulink> that explains this pretty well.  When you create it, I recommend you use a strong passphrase.  I use <ulink url="http://www.keepassx.org/">KeePassX</ulink> to generate the passphrase (<command>sudo apt-get install keepassx</command>), and they've got an <ulink url="http://www.appbrain.com/app/keepassdroid/com.android.keepass">Android version</ulink> for when you're on-the-go (note that you'll need to move your database to your phone for this to work, I use <command>scp</command> and <ulink url="http://www.appbrain.com/app/quicksshd/com.teslacoilsw.quicksshd">QuickSSHd</ulink> to keep mine in sync).  Anyone who gets a hold of your key and can unlock the passphrase can send authenticated mail as you - not a pleasant thought.
</para>
      <para>
After you've followed the instructions in the Launchpad link above you should have a key working its way through the Ubuntu keyservers.  In a few minutes (probably 5-10, maybe longer) you should be able to log into your Launchpad account and click the "Edit" icon next to your OpenPGP Keys entry.  Here you'll want to paste your key <ulink url="https://launchpad.net/+help/import-pgp-key.html">Fingerprint</ulink> and Launchpad will send you an email to the associated address.
</para>
      <para>
On the down side, reading email with your new key may be a little less straightforward than creating it.  If you use Thunderbird, you can look into <ulink url="http://enigmail.mozdev.org/">Enigmail</ulink>.  If you use Evolution you can look into Thunderbird (or check out <ulink url="http://fedoraproject.org/wiki/Using_GPG_with_Evolution">this link</ulink>).  But I use webmail exclusively, so what's a guy to do until Gmail supports native encryption?  Well, you can download the message and decrypt it offline, but that's no fun when you can do it on your phone!
</para>
      <para>
First download <ulink url="http://www.appbrain.com/app/apg/org.thialfihar.android.apg">APG</ulink> to your phone.  Now you'll need to export your key to your phone.  To do so, first run <command>gpg --list-keys</command> to list your keys.  Your output will look like this:
</para>
      <programlisting>
$ gpg --list-keys
/home/username/.gnupg/pubring.gpg
--------------------------------
pub   2048R/A1D934AC 2011-01-13
uid                  Your Name &lt;email@here.com&gt;
sub   2048R/9CA7D53D 2011-01-13
</programlisting>
      <para>
You may have multiples, in which case check for the email address and the name you used to create the key.  If you've already uploaded your key to Launchpad you can see the identifier on your Launchpad page.  What we're interested in is the hex code after the 2048R, in this case <emphasis>A1D934AC</emphasis>.  To export those keys run the following commands:
</para>
      <programlisting>
gpg --output your_name_email_here_com_pub.gpg --armor --export A1D934AC
gpg --output your_name_email_here_com_sec.gpg --armor --export-secret-key A1D934AC
</programlisting>
      <para>
Now get them to your phone's SD card somehow.  Using <command>scp</command> is a good choice, as is plugging the phone in or removing the SD card and putting it in a reader.  Once they're there, open APG on your phone and hit Menu --> Manage Secret Keys.  Click Menu --> Import Keys and find the key on your SD card.  Use the back button to get to the main APG screen and click Menu --> Add Gmail Account.  If you're having trouble, see if the <ulink url="http://www.thialfihar.org/projects/apg/">APG site</ulink> can help.
</para>
      <para>
These are once-and-done steps.  You should now have your keys installed and your Gmail account setup.  If you click on your Gmail account from APG you should see a lock symbol next to any encrypted emails, which you can now open once you type in your passphrase.  If you're not frustrated at this step you either didn't listen to me and didn't use a strong passphrase or you listened to me fully and figured out that KeepassDroid can allow you to copy and paste the password.  Either way, hopefully you've opened the email from Launchpad, decrypted it, and can follow the link to activate your new key.  This is the hard part, I promise!
</para>
    </section>
    <section id="sign-coc">
      <title>Sign the Code of Conduct</title>
      <para>
The next step should be a piece of cake.  Assuming the cake isn't a lie, of course.  Go back to your Launchpad profile and click the link by the Code of Conduct entry and follow the instructions.  You'll need an OpenPGP key for this step, hence the hassle from the previous step.
</para>
    </section>
    <section id="create-ppa">
      <title>Create Your PPA</title>
      <para>
Finally, we're off to create your PPA.  Just click the <emphasis>Create a new PPA</emphasis> link and we'll get started.  Your PPA's URL will be of the format <emphasis>ppa:launchpad-id/ppaname</emphasis>, so the PPA name field should be a short, one-word description related to the use.  The Displayname field is a short description, but is plaintext.  And the PPA contents description is just a long description field and can be ignored if you like.
</para>
    </section>
    <section id="celebrate">
      <title>Celebrate!</title>
      <para>
If you've managed to get this far you're pretty much done.  You've got your first PPA, but no projects for it.  Initially you shouldn't try to add the PPA since the appropriate files haven't been generated yet.  It's possible that this is simply a timing issue, but I believe you actually need to have an actual package available before the system will build the list of packages.
</para>
    </section>
  </section>
  <section id="local-config">
    <title>Configure Your PPA Locally</title>
    <para>
First we'll need to get some of the scripts and utilities needed to post your work to a PPA by running <command>sudo apt-get install dh_make devscripts dput gpg-agent</command>.  This should take care of all of the dependencies and let us get to work.
</para>
    <para>
You'll want to give some thought into your directory structure before we get too far.  I've created a <filename>ppasrc</filename> directory what holds all of my files that I want to publish via PPA.  From there I have a directory for each project, for example I have a <ulink url="../uping">Universal Ping</ulink> utility that I have in <filename>ppasrc/uping</filename>.  From there I have a directory for each version of <command>uping</command>, giving a bunch of directories like <filename>ppasrc/uping/uping-0.2.5</filename>.  The reason for this is that some of the scripts we'll be running will put files into the <filename>ppasrc/uping</filename> directory and I find this structure is fairly clean.
</para>
    <para>
It's also a good time to think about versioning.  It's traditional in a lot of Linux projects to start with version 0.x instead of 1.x.  This both indicates that 1.x is a stable, feature-rich utility as well as satisfies the C programmer in you who loves to start counting from 0.  I like to try to have version a.b.c refer to a change that actually affects functionality.  However I've had to use a.b.c.d to refer to a change that is just a mistake in configuring the PPA (for example, a change in dependencies, a goofed installation file, etc.).  It took me six tries to get my first PPA working, and I wish I had started with the a.b.c.d nomenclature so I'd be at 0.2.0.5 instead of going from 0.2.0 to 0.2.5 with no real code changes.
</para>
    <para>
Once you've created a directory for your utility and figured our what version you want it to be, simply copy all of the necessary files to the directory in whatever format makes sense.  I frequently only have scripts so I don't use any special directory structure internally.  If you have a lot of files you may wish to separate your executables from your images or any other directory structure that makes sense to you.  From this directory you can get started by running <command>dh_make --single --native --copyright apache --email you@email.com</command>.  Note that it's important to use the same email you created your GPG key for in <xref linkend="get-keys"/>.  This will create a <filename>debian</filename> directory for you with a few relevant files.
</para>
    <section id="remove-ex">
      <title>Remove Some Extraneous Files</title>
      <para>
First, let's remove the irrelevant files with <command>rm debian/*.ex debian/*.EX</command>.
</para>
    </section>
    <section id="changelog">
      <title>The changelog File</title>
      <para>
Now we want to look at <filename>debian/changelog</filename>.  We want to check the version number, change <emphasis>unstable</emphasis> to an Ubuntu release such as <emphasis>maverick</emphasis> and add notes about what's changed (typically I start with a simple "Initial Release" and build up the changelog as needed).  Note that if you want to build for multiple releases you'll probably want to pick your favorite release and then read <xref linkend="multiple-distros"/>.
</para>
      <example>
        <title>An Example changelog File</title>
        <programlisting><inlinemediaobject><imageobject><imagedata fileref="sample/changelog" format="linespecific"/></imageobject></inlinemediaobject></programlisting>
      </example>
    </section>
    <section id="control">
      <title>The control File</title>
      <para>
Next is <filename>debian/control</filename>. You'll need to change the line defining the <emphasis>Section</emphasis> to something more meaningful, typically I put mine in <emphasis>utils</emphasis>.  Then add some extra information like a URL where you've documented the package, a quick description, as well as a more detailed description.
</para>
      <para>
The most important thing is to make sure you've set up your dependencies properly.  There should be a line in the <filename>control</filename> file starting with <emphasis>Depends</emphasis> (note that this is distinct from the <emphasis>Build-Depends</emphasis> line which is about compiling and not installing).  After the two pre-populated entries just put a comma-delimited list of the required packages and version number.
</para>
      <para>
If you use a program and you're not sure where it came from, you can use <command>dpkg -S /path/to/file</command> to figure out what the dependency should be.  This can be useful if you use something that is installed by default under Ubuntu but perhaps Debian or an older/newer version of Ubuntu needs it installed manually.  I also run into this a lot when developing on my Ubuntu Desktop and then trying to get it to run on my Ubuntu Server.
</para>
      <programlisting>
$ dpkg -S /usr/bin/xml_pp
xml-twig-tools: /usr/bin/xml_pp
</programlisting>
      <para>
If you need to find the version you should support you can visit <ulink url="http://packages.ubuntu.com/distro/package/">http://packages.ubuntu.com/distro/package/</ulink>.  For example, <ulink url="http://packages.ubuntu.com/hardy/xml-twig-tools">http://packages.ubuntu.com/hardy/xml-twig-tools</ulink> will tell us that Hardy uses xml-twig-tools version 3.32.
</para>
      <example>
        <title>An Example control File</title>
        <programlisting><inlinemediaobject><imageobject><imagedata fileref="sample/control" format="linespecific"/></imageobject></inlinemediaobject></programlisting>
      </example>
    </section>
    <section id="install">
      <title>The install File</title>
      <para>
The <filename>debian/install</filename> file simply states where each file should go and is of the format <emphasis>filename /path/to/install/</emphasis>.
</para>
      <example>
        <title>An Example install File</title>
        <programlisting><inlinemediaobject><imageobject><imagedata fileref="sample/install" format="linespecific"/></imageobject></inlinemediaobject></programlisting>
      </example>
    </section>
    <section id="upload">
      <title>Upload to PPA</title>
      <para>
To get things going you'll need to install two packages, run <command>sudo apt-get install devscripts debhelper</command> to get these out of the way.  You may have done this up above as well.
</para>
      <para>
Next you'll need to build the package using <command>debuild -S</command> in the version directory (one step below the <filename>debian</filename> directory you were just editing, so something like <filename>~/ppcsrc/projectname/projectname-0.2.4</filename>).  This will prompt you for your GPG key passphrase twice assuming things work.
</para>
      <para>
If you get a message about not being able to find a GPG key (an error like <computeroutput>clearsign failed: secret key not available</computeroutput>), try running <command>gpg --list-secret-keys</command> and make sure that the name and email that show up next to your key matches exactly with what you've specified in your <filename>debian/changelog</filename>.
</para>
      <para>
Once you've finished that, you're ready to upload to your PPA using the command <command>dput ppa:launchpad-id/ppaname ../package_version_source.changes</command>.  For example, to put <command>uping</command> version 0.2.4 up I'd run <command>dput ppa:ubuntu-ebower/ebower ../uping_0.2.4_source.changes</command>.
</para>
    </section>
    <section id="multiple-distros">
      <title>Configuring for Multiple Distros</title>
      <para>
I try to make sure that my scripts run on as many systems as possible, but I at least need the latest LTS Ubuntu (which I run on my servers) and the latest stable Ubuntu (which I run on my desktops).  The easiest way to have the same script run on multiple distros as of now is to simply copy the files once they've been accepted in the PPA.  I tend to develop on Maverick these days which means that I typically set my changelog to <emphasis>maverick</emphasis> as I'm pushing the update.  From there I copy the files to <emphasis>lucid</emphasis> and (just because I'm feeling brave) <emphasis>natty</emphasis>.  Since I mostly upload scripts with a no-op compiling command I copy them over without rebuilding.
</para>
    </section>
  </section>
  <section id="adding-ppa">
    <title>Adding Your PPA to your Machine</title>
    <para>
Under most modern Ubuntu systems you can run the command <command>sudo add-apt-repository ppa:launchpad-id/ppaname</command> to add the PPA.  This will also download the security keys for you and set things up properly.  If you make a mistake or want to remove the repository, run <command>sudo add-apt-repository --remove ppa:launchpad-id/ppaname</command>.
</para>
    <para>
If you're running a streamlined server, you may not want to bother installing the <command>add-apt-repository</command> scripts.  In which case you can edit <filename>/etc/apt/sources.lst</filename> and add the following lines to the bottom of the file:
</para>
    <programlisting>
deb http://ppa.launchpad.net/launchpad-id/ppa/ppaname lucid main
deb-src http://ppa.launchpad.net/launchpad-id/ppa/ppaname lucid main
</programlisting>
    <para>
If you open up a web browser to <ulink url="https://launchpad.net/~launchpad-id/+archive/ppaname">https://launchpad.net/~launchpad-id/+archive/ppaname</ulink> and then click on the link "Technical details about this PPA" you can find the exact lines for your specific PPA.
</para>
    <para>
With this method you'll need to install the key manually.  The key can be found under the Technical Details link mentioned above, it's the eight numbers and letters after the 1024R/ under "Signing Key."  Once you've gotten this, run <command>sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1234ABCD</command> and it will download the keys for you.
</para>
    <para>
Once the repository has been added, you'll need to update your local databases with <command>sudo apt-get update</command> and check for errors.  From there it's just a <command>sudo apt-get install packagename</command> to install any package from the PPA and it will be kept up-to-date automatically.
</para>
    <para>
Additional information may be found on the <ulink url="https://launchpad.net/+help/soyuz/ppa-sources-list.html">PPA Help Site</ulink>.
</para>
    <para>
I've included a section in <xref linkend="ebower-ppa-install"/> on how to install my PPA for a more concrete example.
</para>
  </section>
  <section id="updating-ppa">
    <title>Updating Your Code</title>
    <para>
Now that you've got your PPA up and running, you'll probably find that you need to update your code (or, in my case, scripts).  Doing so isn't all that tough.  Let's say you're working on a package called <command>cool-stuff</command> and you're going from version 0.2 to 0.3.  First go into the <filename>cool-stuff</filename> directory you created and run <command>cp -r cool-stuff-0.2 cool-stuff-0.3</command>.  I like using a dash between the package name and the version just to make tab completion a little easier than if I used an underscore.
</para>
    <para>
Now make the changes you need or copy all of your new files into this directory, remembering to delete the old ones as needed.
</para>
    <para>
Now you'll want to <command>cd cool-stuff-0.3</command> and <command>vi debian/changelog</command>.  Edit the version number, add your change list, edit the date and save the file.  If you need to, change the other files like <filename>debian/control</filename> to update dependencies or <filename>debian/install</filename> if you've added new files or changed the installation.
</para>
    <para>
Once you're done and you've tested things, follow the instructions in <xref linkend="upload"/> to upload the code to your PPA and kick off the build process.
</para>
  </section>
  <section id="ppa-utilities">
    <title>PPA Utilities</title>
    <para>
If you intend on using your PPA frequently you may wish to explore some utilities to help you manage it.  If you speak Python, you can create your own using the <ulink url="https://help.launchpad.net/API">Launchpad API</ulink>.  I've also written a wrapper for this called <ulink url="../ppa-tools">ppa-tools</ulink>.  However, for most simple things you may be interested in my <ulink url="../multi-build">multi-build</ulink> project which will automatically submit your package, copy to all available series, and then download the <filename>.deb</filename> files and convert them to <filename>.rpm</filename> files for RedHat-based users.
</para>
  </section>
  <!-- INCLUDE ../ebower-ppa.docbook -->
  <appendix id="ebower-ppa-install">
    <title>Installing the eBower PPA</title>
    <para>
I've created a Personal Packages Archive (PPA) on Launchpad.net.  You can add this using the command <command>sudo add-apt-repository ppa:ubuntu-ebower/ebower</command> and then <command>sudo apt-get update</command> to load the list of packages.  Alternatively you can add the following lines to your <filename>/etc/apt/sources.lst</filename> (this is useful if you're running server and don't want to add the <command>add-apt-repository</command> command):
</para>
    <programlisting>
deb http://ppa.launchpad.net/ubuntu-ebower/ebower/ubuntu precise main 
deb-src http://ppa.launchpad.net/ubuntu-ebower/ebower/ubuntu precise main 
</programlisting>
    <para>
Make sure you replace <emphasis>precise</emphasis> above with your distro (lucid, oneiric, etc.).  If your distro is not available please contact me with the version and package name and I'll try to update things posthaste.  After this is done, run the command <command>sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C27A63B3</command> to import the keys.
</para>
    <para>
By installing my scripts from the PPA you'll be sure to have the most up-to-date versions in case I need to make changes.  However, note that I'm not a developer and I only play one on the Internet.  If you use my scripts as a baseline and make changes yourself please let me know how you're changing things and I'll try to accommodate your efforts to ensure that I don't stomp on your customizations.
</para>
  </appendix>

<!-- INCLUDE_END ../ebower-ppa.docbook -->
<!--INCLUDE ../about-me.docbook -->
</article>