搭建一个 apt 仓库服务
curl -fsSL https://apt.skiy.net/get.sh | sudo sh
一、APT 服务器配置
- 生成 GPG 密钥
# 生成 gpg key (默认参数值。3072 长度,4年有效期)
gpg --gen-key
# 生成 gpg key (全量自定义配置)
gpg --full-generate-key
以方式一为例:
输入对应的 Real name
和 Email address
后,按 O 确定,显示下图
按 TAB 键
选择 OK
,回车确认
回车确认
...
后续的操作同上
...
最终显示
导出 gpg 公钥
# gpg --armor --export <EMAIL> > idev.gpg
gpg --armor --export report@mail.idev.top > idev.gpg
脚本(点击查看最新):debfetch.sh
https://framagit.org/-/snippets/7181
源码:
#!/usr/bin/env bash
# ORIGIN: https://framagit.org/-/snippets/7181/raw/main/debfetch.sh
set -euo pipefail
judgment_parameters() {
while [[ "$#" -gt '0' ]]; do
case "$1" in
'-h' | '--help')
HELP='1'
break
;;
-n | --name)
if [[ -z "${2:?error: Please specify the correct name.}" ]]; then
exit 1
fi
NAME="$2"
shift
;;
-u | --url)
if [[ -z "${2:?error: Please specify the correct url.}" ]]; then
exit 1
fi
URL="$2"
shift
;;
*)
echo "$0: unknown option -- -"
exit 1
;;
esac
shift
done
}
show_help() {
echo "usage: $0 [ options ]"
echo ' -h, --help Show help'
echo ' -n, --name App name'
echo ' -u, --url App url'
exit 0
}
fetch_deb() {
if [[ ! "$1" =~ .deb$ ]]; then
echo -e "The url is not a deb package:\n$1\n"
exit 1
fi
GITHUB="${GITHUB:-https://github.com}"
url=${1/https:\/\/github.com/"$GITHUB"/}
name="${2:-$(mktemp)}"
if file "$name" | grep -v 'Debian binary package'; then
rm -rf "$name"
fi
if [[ ! -f "$name" ]]; then
echo "Save to '$name' from $url"
curl -fSL -o "$name" "$url"
echo
fi
if file "$name" | grep -v 'Debian binary package'; then
echo -e "The file is not a deb package:\n$name\n"
exit 1
fi
move_deb "$name"
}
move_deb() {
DEB_FULL_PATH="${1:-}"
PACKAGE_INFO=$(dpkg-deb --info "$DEB_FULL_PATH" | awk '/Package:|Architecture:|Version:|Maintainer:/ {print}')
# 从提取的信息中获取软件包名称、版本和维护者
PACKAGE_NAME=$(echo "$PACKAGE_INFO" | awk -F ': ' '/Package:/ {print $2}')
PACKAGE_ARCH=$(echo "$PACKAGE_INFO" | awk -F ': ' '/Architecture:/ {print $2}')
PACKAGE_VERSION=$(echo "$PACKAGE_INFO" | awk -F ': ' '/Version:/ {print $2}')
MAINTAINER=$(echo "$PACKAGE_INFO" | awk -F ': ' '/Maintainer:/ {print $2}')
# 输出提取的信息
echo
echo "Package Name: $PACKAGE_NAME"
echo "Architecture: $PACKAGE_ARCH"
echo "Version: $PACKAGE_VERSION"
echo "Maintainer: $MAINTAINER"
DEB_TARGET_PATH="${DEB_POOL_PATH}/${PACKAGE_NAME}_${PACKAGE_VERSION}_${PACKAGE_ARCH}.deb"
echo
echo "Target deb path: ${DEB_TARGET_PATH}"
if [[ "$DEB_FULL_PATH" = "$DEB_TARGET_PATH" ]]; then
echo -e "The same as the target file:\n$DEB_FULL_PATH\n"
exit 1
fi
mv "$DEB_FULL_PATH" "$DEB_TARGET_PATH" || {
echo "Failed to move $DEB_FULL_PATH to $DEB_TARGET_PATH"
exit 1
}
}
set_archconf() {
if [[ -f "$APT_CONF_PATH" ]]; then
return
fi
Origin="$HEADER_ORIGIN"
Label="$HEADER_LABEL"
Codename=stable
Version=$(date +%Y)
Architectures=amd64
Components=main
Description="$Origin packages"
tee "$APT_CONF_PATH" <<EOF
Origin: $Origin
Label: $Label
Codename: $Codename
Version: $Version
Architectures: $Architectures
Components: $Components
Description: $Description
EOF
}
update_pool() {
pushd "$APT_ROOT_PATH" >/dev/null 2>&1 || {
echo "Failed to enter $APT_ROOT_PATH"
exit 1
}
[[ -d "pool/main" ]] || mkdir -p "pool/main"
[[ -d "dists/stable/main/binary-amd64/" ]] || mkdir -p "dists/stable/main/binary-amd64/"
dpkg-scanpackages --multiversion --arch amd64 pool/ >"dists/stable/main/binary-amd64/Packages"
gzip -9 >"dists/stable/main/binary-amd64/Packages.gz" <"dists/stable/main/binary-amd64/Packages"
DIST_STABLE="dists/stable"
apt-ftparchive release "$DIST_STABLE" >"$DIST_STABLE/Release"
sed -i "1r $APT_CONF_PATH" "$DIST_STABLE/Release"
gpg --default-key "$GPG_KEY" -abs >"$DIST_STABLE/Release.gpg" <"$DIST_STABLE/Release"
gpg --default-key "$GPG_KEY" -abs --clearsign >"$DIST_STABLE/InRelease" <"$DIST_STABLE/Release"
popd >/dev/null 2>&1 || {
echo "Failed to exit $APT_ROOT_PATH"
exit 1
}
}
main() {
judgment_parameters "$@"
[[ "${HELP:-}" -eq '1' ]] && show_help
if ! which dpkg-buildpackage >/dev/null 2>&1; then
echo "dpkg-dev is not installed."
exit 1
fi
APT_ROOT_PATH="${APTPATH:-/root/downloads}"
DEB_POOL_PATH="${DEBPATH:-$APT_ROOT_PATH/pool/main}"
APT_CONF_PATH="${APTCONF:-/etc/apt-ftparchive.conf}"
ORGNAME="${ORGNAME:-idev}"
GPG_KEY="${GPGKEY:-example@example.com}"
echo "APT_ROOT_PATH: $APT_ROOT_PATH"
echo "DEB_POOL_PATH: $DEB_POOL_PATH"
echo "APT_CONF_PATH: $APT_CONF_PATH"
echo "GPG_KEY: $GPG_KEY"
echo "ORG NAME: $ORGNAME"
echo
[[ -d "$DEB_POOL_PATH" ]] || mkdir -p "$DEB_POOL_PATH"
if [[ -n "${URL:-}" ]]; then
fetch_deb "$URL" "${NAME:-}"
fi
HEADER_ORIGIN="$ORGNAME"
HEADER_LABEL="$ORGNAME"
set_archconf
update_pool
}
main "$@"
环境变量
APT_ROOT_PATH="${APTPATH:-/root/downloads}"
DEB_POOL_PATH="${DEBPATH:-$APT_ROOT_PATH/pool/main}"
APT_CONF_PATH="${APTCONF:-/etc/apt-ftparchive.conf}"
ORGNAME="${ORGNAME:-idev}"
GPG_KEY="${GPGKEY:-example@example.com}"
可以修改上述代码中的环境变量,或者直接修改全局环境变量
执行脚本
# 首次需执行
curl -O https://framagit.org/-/snippets/7181/raw/main/debfetch.sh && chmod +x debfetch.sh
# 此后更新软件需要使用,具体参数信息可通过 ./debfetch.sh -h 查看
./debfetch.sh -u https://example.com/latest/app.deb
# 自定义环境变量(每次都需要)
GPGKEY=report@mail.idev.top ./debfetch.sh -u https://example.com/latest/app.deb
# 自定义环境变量
export GPGKEY=report@mail.idev.top
./debfetch.sh -u https://example.com/latest/app.deb
- 最终文件目录内容
~/downloads# tree
.
├── dists
│ └── stable
│ ├── InRelease
│ ├── main
│ │ └── binary-amd64
│ │ ├── Packages
│ │ └── Packages.gz
│ ├── Release
│ └── Release.gpg
├── idev.gpg
└── pool
└── main
└── app.deb
或者,将 deb 文件保存到 pool/main
下,再执行脚本更新
bash debfetch.sh
# 或将之移动到 /usr/local/bin/debfetch ,方便更新
mv debfetch.sh /usr/local/bin/debfetch
# 执行 debfetch
- nginx 配置文件中,配置文件中添加的
autoindex on
,如
# root 目录需修改
root /root/downloads;
location / {
autoindex on;
}
部分参考:https://earthly.dev/blog/creating-and-hosting-your-own-deb-packages-and-apt-repo/