1. 创建简单的程序
首先创建一个简单的 C 程序作为示例:
# 创建程序目录
mkdir -p ~/example/hello-world-program
# 编写 C 程序
echo '#include <stdio.h>
int main() {
printf("hello packaged world\n");
return 0;
}' > ~/example/hello-world-program/hello.c
# 编译程序
cd ~/example/hello-world-program
gcc -o hello-world hello.c
2. 创建 Debian 包结构
2.1 创建包目录结构
# 创建符合命名规范的目录
# 格式: <package-name>_<version>-<release-number>_<architecture>
mkdir -p ~/example/hello-world_0.0.1-1_amd64
2.2 组织文件结构
cd ~/example/hello-world_0.0.1-1_amd64
# 创建二进制文件目录
mkdir -p usr/bin
# 复制编译好的程序
cp ~/example/hello-world-program/hello-world usr/bin/
2.3 创建控制文件
# 创建 DEBIAN 目录
mkdir -p DEBIAN
# 创建 control 文件
cat > DEBIAN/control << EOF
Package: hello-world
Version: 0.0.1
Maintainer: example <example@example.com>
Depends: libc6
Architecture: amd64
Homepage: http://example.com
Description: A program that prints hello
EOF
3. 构建 Debian 包
# 返回包目录的上级目录
cd ~/example
# 构建 .deb 包
dpkg --build hello-world_0.0.1-1_amd64
构建完成后会生成 hello-world_0.0.1-1_amd64.deb文件。
4. 检查包内容
4.1 查看包信息
dpkg-deb --info hello-world_0.0.1-1_amd64.deb
输出示例:
new Debian package, version 2.0.
size 2832 bytes: control archive=336 bytes.
182 bytes, 7 lines control
Package: hello-world
Version: 0.0.1
Maintainer: example <example@example.com>
Depends: libc6
Architecture: amd64
Homepage: http://example.com
Description: A program that prints hello
4.2 查看包内容
dpkg-deb --contents hello-world_0.0.1-1_amd64.deb
5. 安装和测试
5.1 安装包
sudo apt-get install -f ./hello-world_0.0.1-1_amd64.deb
5.2 验证安装
# 检查程序位置
which hello-world
# 运行程序
hello-world
应该输出:hello packaged world
5.3 卸载包
sudo apt-get remove hello-world
6. 创建 APT 仓库(可选)
6.1 创建仓库目录结构
mkdir -p ~/example/apt-repo/pool/main/
cp ~/example/hello-world_0.0.1-1_amd64.deb ~/example/apt-repo/pool/main/
6.2 生成 Packages 文件
cd ~/example/apt-repo
mkdir -p dists/stable/main/binary-amd64
# 生成 Packages 文件
dpkg-scanpackages --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages
# 压缩 Packages 文件
gzip -9 < dists/stable/main/binary-amd64/Packages > dists/stable/main/binary-amd64/Packages.gz
6.3 生成 Release 文件
# 创建生成脚本
cat > ~/example/generate-release.sh << 'EOF'
#!/bin/sh
set -e
do_hash() {
HASH_NAME=$1
HASH_CMD=$2
echo "${HASH_NAME}:"
for f in $(find -type f); do
f=$(echo $f | cut -c3-) # remove ./ prefix
if [ "$f" = "Release" ]; then
continue
fi
echo " $(${HASH_CMD} ${f} | cut -d" " -f1) $(wc -c $f)"
done
}
cat << EOF
Origin: Example Repository
Label: Example
Suite: stable
Codename: stable
Version: 1.0
Architectures: amd64
Components: main
Description: An example software repository
Date: $(date -Ru)
EOF
do_hash "MD5Sum" "md5sum"
do_hash "SHA1" "sha1sum"
do_hash "SHA256" "sha256sum"
EOF
chmod +x ~/example/generate-release.sh
# 生成 Release 文件
cd ~/example/apt-repo/dists/stable
~/example/generate-release.sh > Release
7. 测试本地仓库
7.1 启动 HTTP 服务器
cd ~/example
python3 -m http.server
7.2 配置 APT 源
echo "deb [arch=amd64] http://127.0.0.1:8000/apt-repo stable main" | sudo tee /etc/apt/sources.list.d/example.list
7.3 更新并安装
sudo apt-get update --allow-insecure-repositories
sudo apt-get install hello-world
8. 包签名(安全部署)
8.1 生成 GPG 密钥
# 创建密钥生成配置
cat > /tmp/example-pgp-key.batch << EOF
%echo Generating an example PGP key
Key-Type: RSA
Key-Length: 4096
Name-Real: example
Name-Email: example@example.com
Expire-Date: 0
%no-ask-passphrase
%no-protection
%commit
EOF
# 生成密钥
export GNUPGHOME="$(mktemp -d ~/example/pgpkeys-XXXXXX)"
gpg --no-tty --batch --gen-key /tmp/example-pgp-key.batch
8.2 导出公钥
gpg --armor --export example > ~/example/pgp-key.public
8.3 签名仓库
# 签名 Release 文件
cd ~/example/apt-repo/dists/stable
cat Release | gpg --default-key example -abs > Release.gpg
# 创建 InRelease 文件(包含签名的 Release)
cat Release | gpg --default-key example -abs --clearsign > InRelease
8.4 安全配置 APT 源
echo "deb [arch=amd64 signed-by=$HOME/example/pgp-key.public] http://127.0.0.1:8000/apt-repo stable main" | sudo tee /etc/apt/sources.list.d/example.list
# 安全更新和安装
sudo apt-get update
sudo apt-get install hello-world
重要注意事项
-
包命名规范 :遵循
<package>_<version>-<release>_<arch>格式 -
文件权限:确保二进制文件有可执行权限
-
依赖管理:在 control 文件中正确声明依赖
-
架构支持:根据程序类型选择正确的架构(amd64, all 等)
-
安全签名:生产环境必须使用 GPG 签名
-
私钥保护:妥善保管 GPG 私钥,不要泄露
这个指南涵盖了从简单程序打包到完整 APT 仓库创建的全过程,适合个人使用和小规模部署。
参考:Creating and hosting your own deb packages and apt repo - Earthly Blog