If you are building Debian packages for your own libraries and applications (that are not open source), you are probably familiar with the pain of managing and hosting your own private Apt repository. This post shows how to easily manage your own Apt repo and host it on S3 so that only your servers can access it. You will not have to maintain any Apt index files, nor will you have to expose your Apt repo using a web server. While this approach works especially well when you are running everything on EC2, that is not required.
To accomplish this, we will use:
- reprepro to manage the Apt repo
- s3cmd to store the Apt repo in a private S3 bucket
- apt-s3 to use that S3 bucket as a private Apt repo
Note that if you want to provide public access to your Apt repo, you can just set all of the files in S3 to have an anyone-readable ACL. Then anyone can just access the files in the S3 bucket using HTTP. If this is all you need to do, then here is a great blog post showing how to set that up.
However, when you need a private Apt repo to host your company’s important libs & apps, there is no way to have Apt provide the proper request signing for S3 security over HTTP. In this case, we need a custom Apt protocol, which is provided by apt-s3. This protocol lets you specify your AWS access & security keys to access your private Apt repo files.
Warning: apt-s3 is pretty new and you’ll have to choose a fork from github to compile yourself, but it has worked well so far in my tests. The castlabs fork seems to be the most mature at the time of this writing.
Here is a great blog post describing how to set up reprepro. We’ll just abbreviate some of the commands.
Install reprepro, it should already be in standard Ubuntu repos. Create a new empty directory, create a conf subdir in it, then create a conf/distributions file something like this:
Codename: production Components: main Architectures: i386 amd64
The reprepro docs provide full detail on what should go in this file.
Install s3cmd, it should already be in standard Ubuntu repos. Set it up by running:
s3cmd --configure s3cmd mb s3://my-repo/
The first command will ask you for your AWS keys. The second command creates the S3 bucket. If you already have the S3 bucket then just omit this step.
Next you’ll need a .deb to put in your new repo. Creating these is outside the scope of this post. Presumably your .deb will either be built by hand, or some Continuous Integration server such as Jenkins will build it for you.
Let’s assume you end up with mysuperapp_1.0_i386.deb. This is all you need to do to add it to the repo:
reprepro -b /path/to/repo includedeb production mysuperapp_1.0_i386.deb
That’s it! Look in your Apt repo dir, you’ll find that reprepro has created tons of stuff for you.
Now let’s get that repo on S3:
s3cmd --verbose --delete-removed --follow-symlinks sync /path/to/repo/ s3://my-repo/
This command ensures that your S3 bucket contains all of the same files as your local Apt repo, in the proper directory structure. The –delete-removed should be obvious. –follow-symlinks is useful if you are using suites with reprepro. Note that all of the files on S3 are private and only readable/writable by you.
Next you’ll need to compile apt-s3 from source to create your own binary. Make sure you compile it for the architecture on which you’ll eventually use it (i386 for 32-bit, amd64 for 64-bit, etc). I used these commands on a fresh Ubuntu EC2 instance:
sudo apt-get install -y git libapt-pkg-dev libcurl4-openssl-dev make build-essential git clone https://github.com/castlabs/apt-s3 cd apt-s3 make
You’ll end up with an s3 executable in the src dir. Move this to the /usr/lib/apt/methods dir on the server on which you want to use your S3-based Apt repo.
Next, tell Apt where to find your repo. Add a line to /etc/apt/sources.list (or a file in sources.list.d) like this one, substituting your AWS keys and your S3 bucket name:
deb s3://ACCESS_KEY:[SECRET_KEY]@s3.amazonaws.com/BUCKET production main
Finally, you should be able to tell Apt to find your new repo and install packages from it:
sudo apt-get update sudo apt-get install mysuperapp
Note that we’ve skipped over signing your .debs and Apt repo, so that last line may give warnings. In a full production setting you’ll probably want to sign these things, but that is left as an exercise to the reader. You’ll also probably want to just build apt-s3 once and make it easily accessible to put on a new server.
And that’s it! The next time you have a new .deb package, just run the reprepro command above to add it to the local repo, then run s3cmd sync as above to update the files in the S3 bucket. If Jenkins is building your .deb files, just have him also perform these commands. Then on your servers, you can just apt-get update and apt-get install mysuperapp to upgrade to the new version.