APT Repository Setup #
This guide walks you through creating and maintaining a signed Debian/APT repository under the deb/ prefix in your S3-compatible bucket, suitable for Debian, Ubuntu, Linux Mint, and other Debian-based client systems.
Understanding APT Repository Concepts #
If you are new to the Debian ecosystem, the repository structure might look complex. Let's break down the three main variables:
- Distribution (e.g.,
stable,testing,bookworm,focal): Represents the target release or release state. You can name these whatever you like (e.g.,production,staging). - Component (e.g.,
main,contrib,non-free): A sub-section of the distribution. Typically,mainis used for the primary software packages. - Architecture (e.g.,
amd64,arm64,all): The hardware architecture the packages are compiled for.allis used for architecture-independent packages (like Python scripts, configuration files, or themes).
1. Configure Storage #
Hakobin needs credentials and settings to communicate with your S3 bucket. Export these environment variables:
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
export S3_BUCKET_NAME=your-bucket-name
export AWS_REGION=us-east-1
For custom endpoints (like MinIO, Cloudflare R2, or DigitalOcean Spaces):
export S3_ENDPOINT=http://localhost:9000
export S3_USE_PATH_STYLE=true
Set the public base URL that clients will use to download packages:
export HAKOBIN_PUBLIC_URL=https://packages.example.com
2. Initialize the Repository #
Initialize your APT metadata and let Hakobin generate the initial repository signing key:
hakobin deb init \
--origin "Example Inc" \
--label "Example Packages" \
--description "APT repository for Example packages" \
--distributions stable \
--components main \
--architectures amd64,all \
--key-name "Example Repository Signing Key" \
--key-email "packages@example.com"
What does this command do? #
- Generates a private GPG key named
signing-key.gpgin your current local directory. - Creates
deb/apt-repo.jsonin your bucket to store these configurations. - Creates empty package indexes.
- Signs the repository metadata.
- Writes
deb/pubkey.asc,deb/pubkey.gpg(the public keys), anddeb/setup.sh(a client bootstrapping script) to S3.
Important
Save signing-key.gpg in a secure location (e.g., a credential manager or CI secrets). Do not commit it to source control. It is used to sign all future package uploads.
3. Upload Packages #
To upload a .deb package file:
hakobin --signing-key ./signing-key.gpg \
deb upload ./package.deb \
--distribution stable \
--component main
If you are running this in a CI pipeline (such as GitHub Actions or GitLab CI), passing file paths can be cumbersome. Instead, pass the key content directly via an environment variable:
export GPG_PRIVATE_KEY="$(cat signing-key.gpg)"
hakobin deb upload ./package.deb --distribution stable --component main
Forcing Overwrites #
By default, Hakobin will fail if you try to upload a package version that already exists. To overwrite it, use the --force flag:
hakobin --signing-key ./signing-key.gpg deb upload --force ./*.deb
4. Query and Manage Packages #
List Published Packages #
To see what packages are currently published in your repository:
hakobin deb list
You can filter the list by package name, distribution, or component:
hakobin deb list nginx --distribution stable --component main
Remove a Package #
To delete a specific package version and architecture from the repository:
hakobin deb remove nginx --version 1.2.3 --architecture amd64 --force
5. Configure APT Clients #
There are two ways to configure your client machines to download packages from your repository.
Option A: The One-Liner Script (Recommended) #
Hakobin automatically generates a helper shell script called setup.sh and publishes it to your bucket. Clients can run it directly:
curl -fsSL https://packages.example.com/deb/setup.sh | sudo bash
Note
The setup.sh script detects the client's OS, installs the public GPG key into /etc/apt/keyrings/hakobin.gpg, adds the repository sources list, and runs apt update.
Option B: Manual Client Setup #
If you want to configure clients manually or write Ansible/Chef playbooks, run:
# 1. Create the keyrings folder if it doesn't exist
sudo install -d -m 0755 /etc/apt/keyrings
# 2. Download the binary public GPG key
curl -fsSL https://packages.example.com/deb/pubkey.gpg \
| sudo tee /etc/apt/keyrings/hakobin.gpg >/dev/null
sudo chmod 0644 /etc/apt/keyrings/hakobin.gpg
# 3. Add the repository sources list pointing to the downloaded keyring
echo "deb [signed-by=/etc/apt/keyrings/hakobin.gpg] https://packages.example.com/deb stable main" \
| sudo tee /etc/apt/sources.list.d/hakobin.list
# 4. Refresh package indexes
sudo apt update
Once completed, users can install your packages using standard apt commands:
sudo apt install package-name