<center>
# Python Packaging Guide for APT/Debian
*A quick guide on how to package your Python/`pip` project into an `apt`-installable Debian package using `stdeb`.*
<div style="display: inline-block; width: 50%;vertical-align: top; min-width: 400px; margin-right: 4px; text-align: left">
```bash
# how to go from this
cd yourpackage/
python setup.py install
# to this:
add-apt-repository ppa:yourppa/yourpackage
apt install yourpackage
```
</div>
<img src="https://docs.monadical.com/uploads/upload_64a8d49f0a0b0690f3d3a43072e36d09.png" style="width:300px; display: inline-block">
</center>
</center>
---
*ArchiveBox is used as an example package throughout this guide, but you can replace anywhere you see `archivebox` with the name of your own package*
## Goals
Assuming you have a Python project with a `setup.py` file and `python setup.py install` already working, we aim to achieve:
- a Debian package published, installable with `apt install yourpackage`
- a static Debian bundle built, installable with `dpkg -i ./yourpackage.deb`
- a source Debian changeset built, inspectable in `yourpackage.changes`
You can host your repository anywhere, but Ubuntu/Launchpad (aka Canonical) provide a public PPA you can sign up for. This tutorial assumes you're using their PPA server, but you can use any. You must tell your users to add the PPA/repository sources to their machine in order to install your package.
```bash
# on ubuntu focal:
sudo add-apt-repository -u ppa:archivebox/archivebox
# on other deb systems should add these to /etc/apt/sources.list instead:
deb http://ppa.launchpad.net/archivebox/archivebox/ubuntu focal main
deb-src http://ppa.launchpad.net/archivebox/archivebox/ubuntu focal main
```
## Steps to Get Started
1. Sign up for an [Ubuntu + Launchpad](https://launchpad.net/) account
2. Verify your email address, and add a [PGP key](https://www.gnupg.org/gph/en/manual/c14.html ) to your account <code style="color:blue">https://launchpad.net/~YOURUSERNAME/+editpgpkeys</code>
3. Sign the code of conduct with your PGP key
<code style="color:blue">https://launchpad.net/~YOURUSERNAME</code>
4. Create a new PPA for your packages (pick a good, short name)
<code style="color:blue">https://launchpad.net/~YOURUSERNAME/+activate-ppa</code>
5. Set up your branding and PPA info:
<code style="color:blue">https://launchpad.net/~YOURUSERNAME/+branding</code><code style="color:blue">https://launchpad.net/~YOURUSERNAME/+edit</code>
6. Set up your build machine (see below)
7. Build, sign, and upload changes on each release (see below)
### Build Machine Setup
**Install the tools for python and debian packaging:**
```bash
apt install python3 python3-dev python3-pip python3-venv python3-all dh-python devscripts dput software-properties-common debhelper
python3 -m pip install setuptools stdeb
```
**Set up your package definition and dependencies in `stdeb.cfg`:**
```ini
[DEFAULT]
Package: archivebox
Suite: focal
Build-Depends: dh-python
Depend: python3, nodejs, chromium, wget, curl, ffmpeg, git, python3-atomicwrites, python3-croniter, python3-crontab
XS-Python-Version: >= 3.7
```
**Set up your launchpad ppa upload location in `~/.dput.cf`:**
```ini
[archivebox-ppa]
fqdn: ppa.launchpad.net
method: ftp
incoming: ~archivebox/ubuntu/archivebox/
login: anonymous
allow_unsigned_uploads: 0
```
No username/password is needed for launchpad FTP uploads because your PGP signature on the changeset is used to verify authenticity.
## Common Tasks
#### Build the package
```bash
python3 setup.py --command-packages=stdeb.command sdist_dsc --debian-version=2 bdist_deb
```
<small>The final version number will be `{version from setup.py}-{debian-version}` e.g. `0.4.21-2`.</small>
#### Manage your PGP keys
```bash
gpg --refresh-keys
gpg --list-keys
gpg --export YOURKEYID > public.key
gpg --export-secret-key YOURKEYID > private.key
gpg --import public.key
gpg --import --allow-secret-key-import private.key
gpg --verify deb_dist/archivebox_0.4.21-2_source.changes
```
#### Sign a build
```bash
debsign -k YOURGPGKEYID deb_dist/archivebox_0.4.21-2_source.changes
gpg --verify deb_dist/archivebox_0.4.21-2_source.changes
gpg --verify deb_dist/archivebox_0.4.21-2.dsc
```
#### Push a build to the launchpad ppa
```bash
dput archivebox deb_dist/archivebox_0.4.21-2_source.changes
```
<small>(check your email for build status updates)</small>
#### Install a source build from the launchpad ppa
```bash
add-apt-repository ppa:archivebox/archivebox
apt update
apt install archivebox
```
#### Install a binary build from `.deb`
```bash
dpkg -i $PWD/deb_dist/archivebox_0.4.21-2_all.deb
apt install $PWD/deb_dist/archivebox_0.4.21-2_all.deb
```
#### Troubleshooting
If you run into problems, you can always try fixing broken dependencies with apt, or purging and reinstalling the package.
```bash
apt --fix-broken install
apt purge archivebox
rm -Rf build deb_dist dist archivebox-*.tar.gz
```
https://help.launchpad.net/Packaging/UploadErrors
https://www.youtube.com/watch?v=O83rIRRJysA
## The Rules of Debian Packaging
1. Debian packages can only install other Debian packages, if you need a Python package e.g. `django`, you have to install the Debian equivalent `python3-django` instead. If a Debian equivalent is not available, then you'll have to vendor the package yourself by downloading it and putting it in your source code folder.
2. You can never upload different content with the same version number to launchpad (if anything is changed, you must bump `--debian-version n`).
3. Every change must be signed with PGP before being uploaded (using key from launchpad).
4. You cannot distribute compiled binaries via launchpad, only source code and build instructions (you can still offer compiled `.deb`s on your own website).
## Summary
You should now have a finished `apt`/`deb` package, available via Launchpad PPA that your users can easily install on Ubuntu and other Debian-based systems.
If you have any trouble or want to try an alternative to `stdeb`, check out FPM: https://fpm.readthedocs.io/en/latest/intro.html
Recent posts:
- So you want to build a social network?
- Mastering Project Estimation
- Typescript Validators Jamboree
- Mindfulness in Typescript code branching. Exhaustiveness, pattern matching, and side effects
- View more posts...
Back to top