[Share Experiences] 打造一个属于自己的 APT 仓库
Tofloor
poster avatar
爱开发
deepin
2023-09-02 21:34
Author

一、APT 服务器配置

  1. 生成 GPG 密钥
# 生成 gpg key (默认参数值。3072 长度,4年有效期)
gpg --gen-key

# 生成 gpg key  (全量自定义配置。支持自定义长度,不设置过期时间)
gpg --full-generate-key

方式一为例:
image.png
输入对应的 Real nameEmail address 后,按 O 确定,显示下图

image.png
TAB 键 选择 OK,回车确认

image.png
回车确认

...
后续的操作同上
...

最终显示

image.png

  1. 导出 gpg 公钥
# gpg --armor --export  > idev.gpg
gpg --armor --export [email protected] > idev.gpg
  1. 脚本(点击查看最新):debfetch.sh
    https://framagit.org/-/snippets/7181

用于下载 deb 软件到软件仓

源码:

#!/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" </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:[email protected]}"
  
  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:[email protected]}"

可以修改上述代码中的环境变量,或者直接修改全局环境变量

执行脚本

# 首次需执行
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
# 自定义环境变量(每次都需要)
[email protected] ./debfetch.sh -u https://example.com/latest/app.deb
# 自定义环境变量
export [email protected]
./debfetch.sh -u https://example.com/latest/app.deb
  1. 最终文件目录内容
~/downloads# tree
.
├── dists
│   └── stable
│       ├── InRelease
│       ├── main
│       │   └── binary-amd64
│       │       ├── Packages
│       │       └── Packages.gz
│       ├── Release
│       └── Release.gpg
├── idev.gpg
└── pool
    └── main
        └── app.deb

比如

image.png

或者,将 deb 文件保存到 pool/main 下,再执行脚本更新

bash debfetch.sh

# 或将之移动到 /usr/local/bin/debfetch ,方便更新
mv debfetch.sh /usr/local/bin/debfetch
# 执行 debfetch
  1. nginx 配置文件中,配置文件中添加的 autoindex on,如
# root 目录需修改
root  /root/downloads;
location / {
  autoindex on;
}

桌面客户端

https://framagit.org/-/snippets/7181

  • 首次安装和设置 apt 软件仓:get.sh
curl -fsSL https://apt.skiy.net/get.sh | sudo sh

源码:

#!/bin/sh

APT_URL="https://apt.skiy.net"
GPG_PATH="/etc/apt/trusted.gpg.d/idev.gpg"
APT_PATH="/etc/apt/sources.list.d/idev.list"

if [ "$(id -u)" -eq 0 ]; then
  curl -fsSL "$APT_URL/idev.gpg" | gpg --dearmor | tee "$GPG_PATH" > /dev/null
  echo "deb [arch=$(dpkg --print-architecture)] $APT_URL stable main" | tee "$APT_PATH" > /dev/null
  apt update -y
else
  curl -fsSL "$APT_URL/idev.gpg" | gpg --dearmor | sudo tee "$GPG_PATH" > /dev/null
  echo "deb [arch=$(dpkg --print-architecture)] $APT_URL stable main" | sudo tee "$APT_PATH" > /dev/null
  sudo apt update -y
fi

更新源

sudo apt update

image.png

Reply Favorite View the author
All Replies
Zeta.
deepin
2024-02-17 09:44
#1

运行您的脚本后报了一个错误

Zero@Zero-PC:~/Desktop/apt$ sudo bash aptupdate.sh
请输入密码:
验证成功
+ DEB_FOLDERS=./deb
+ [email protected]
+ APT_CONF=/etc/apt-ftparchive.conf
+ pushd ./deb
+ [[ -d dists/stable/main/binary-amd64/ ]]
+ [[ -d pool/main ]]
+ dpkg-scanpackages --arch amd64 pool/
dpkg-scanpackages: info: Wrote 0 entries to output Packages file.
+ cat dists/stable/main/binary-amd64/Packages
+ gzip -9
+ apt-ftparchive release dists/stable
+ Origin=ppwq
+ Label=ppwq
+ Codename=stable
+ Version=2024
+ Architectures=amd64
+ Components=main
+ Description='ppwq packages'
+ tee /etc/apt-ftparchive.conf
Origin: ppwq
Label: ppwq
Codename: stable
Version: 2024
Architectures: amd64
Components: main
Description: ppwq packages
+ sed -i '1r /etc/apt-ftparchive.conf' dists/stable/Release
+ gpg --default-key [email protected] -abs
+ cat dists/stable/Release
gpg: 传递给‘--default-key’的所有值被忽略
gpg: 签名时失败: 对设备不适当的 ioctl 操作
gpg: signing failed: 对设备不适当的 ioctl 操作

下面是我添加我的信息的脚本和gpg命令

gpg --gen-key
gpg --armor --export [email protected] > zhsoft.gpg

脚本:

#!/usr/bin/env bash

set -eux

DEB_FOLDERS="./"
GPG_KEY="[email protected]"
APT_CONF="/etc/apt-ftparchive.conf"

pushd "$DEB_FOLDERS" >/dev/null 2>&1 
[[ -d "dists/stable/main/binary-amd64/" ]] || mkdir -p dists/stable/main/binary-amd64/
[[ -d "pool/main" ]] || mkdir -p pool/main

dpkg-scanpackages --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages
cat dists/stable/main/binary-amd64/Packages | gzip -9 > dists/stable/main/binary-amd64/Packages.gz


apt-ftparchive release dists/stable > dists/stable/Release

# Add deb info to head
Origin=ppwq
Label=ppwq
Codename=stable
Version=2024
Architectures=amd64
Components=main
Description="$Origin packages"

tee $APT_CONF << EOF
Origin: $Origin
Label: $Label
Codename: $Codename
Version: $Version
Architectures: $Architectures
Components: $Components
Description: $Description
EOF

sed -i "1r $APT_CONF" dists/stable/Release

cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs > dists/stable/Release.gpg
cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs --clearsign > dists/stable/InRelease

popd > /dev/null 2>&1
Reply View the author
Zeta.
deepin
2024-02-17 09:46
#2
Zeta.

运行您的脚本后报了一个错误

Zero@Zero-PC:~/Desktop/apt$ sudo bash aptupdate.sh
请输入密码:
验证成功
+ DEB_FOLDERS=./deb
+ [email protected]
+ APT_CONF=/etc/apt-ftparchive.conf
+ pushd ./deb
+ [[ -d dists/stable/main/binary-amd64/ ]]
+ [[ -d pool/main ]]
+ dpkg-scanpackages --arch amd64 pool/
dpkg-scanpackages: info: Wrote 0 entries to output Packages file.
+ cat dists/stable/main/binary-amd64/Packages
+ gzip -9
+ apt-ftparchive release dists/stable
+ Origin=ppwq
+ Label=ppwq
+ Codename=stable
+ Version=2024
+ Architectures=amd64
+ Components=main
+ Description='ppwq packages'
+ tee /etc/apt-ftparchive.conf
Origin: ppwq
Label: ppwq
Codename: stable
Version: 2024
Architectures: amd64
Components: main
Description: ppwq packages
+ sed -i '1r /etc/apt-ftparchive.conf' dists/stable/Release
+ gpg --default-key [email protected] -abs
+ cat dists/stable/Release
gpg: 传递给‘--default-key’的所有值被忽略
gpg: 签名时失败: 对设备不适当的 ioctl 操作
gpg: signing failed: 对设备不适当的 ioctl 操作

下面是我添加我的信息的脚本和gpg命令

gpg --gen-key
gpg --armor --export [email protected] > zhsoft.gpg

脚本:

#!/usr/bin/env bash

set -eux

DEB_FOLDERS="./"
GPG_KEY="[email protected]"
APT_CONF="/etc/apt-ftparchive.conf"

pushd "$DEB_FOLDERS" >/dev/null 2>&1 
[[ -d "dists/stable/main/binary-amd64/" ]] || mkdir -p dists/stable/main/binary-amd64/
[[ -d "pool/main" ]] || mkdir -p pool/main

dpkg-scanpackages --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages
cat dists/stable/main/binary-amd64/Packages | gzip -9 > dists/stable/main/binary-amd64/Packages.gz


apt-ftparchive release dists/stable > dists/stable/Release

# Add deb info to head
Origin=ppwq
Label=ppwq
Codename=stable
Version=2024
Architectures=amd64
Components=main
Description="$Origin packages"

tee $APT_CONF << EOF
Origin: $Origin
Label: $Label
Codename: $Codename
Version: $Version
Architectures: $Architectures
Components: $Components
Description: $Description
EOF

sed -i "1r $APT_CONF" dists/stable/Release

cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs > dists/stable/Release.gpg
cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs --clearsign > dists/stable/InRelease

popd > /dev/null 2>&1

这是文件目录结构

Zero@Zero-PC:~/Desktop/apt$ tree
.
├── aptupdate.sh
├── dists
│   └── stable
│       ├── main
│       │   └── binary-amd64
│       │       ├── Packages
│       │       └── Packages.gz
│       ├── Release
│       └── Release.gpg
├── gpgkey.sh
├── pool
│   └── main
└── zhsoft.gpg

6 directories, 7 files

Reply View the author
爱开发
deepin
2024-02-17 12:34
#3
Zeta.

运行您的脚本后报了一个错误

Zero@Zero-PC:~/Desktop/apt$ sudo bash aptupdate.sh
请输入密码:
验证成功
+ DEB_FOLDERS=./deb
+ [email protected]
+ APT_CONF=/etc/apt-ftparchive.conf
+ pushd ./deb
+ [[ -d dists/stable/main/binary-amd64/ ]]
+ [[ -d pool/main ]]
+ dpkg-scanpackages --arch amd64 pool/
dpkg-scanpackages: info: Wrote 0 entries to output Packages file.
+ cat dists/stable/main/binary-amd64/Packages
+ gzip -9
+ apt-ftparchive release dists/stable
+ Origin=ppwq
+ Label=ppwq
+ Codename=stable
+ Version=2024
+ Architectures=amd64
+ Components=main
+ Description='ppwq packages'
+ tee /etc/apt-ftparchive.conf
Origin: ppwq
Label: ppwq
Codename: stable
Version: 2024
Architectures: amd64
Components: main
Description: ppwq packages
+ sed -i '1r /etc/apt-ftparchive.conf' dists/stable/Release
+ gpg --default-key [email protected] -abs
+ cat dists/stable/Release
gpg: 传递给‘--default-key’的所有值被忽略
gpg: 签名时失败: 对设备不适当的 ioctl 操作
gpg: signing failed: 对设备不适当的 ioctl 操作

下面是我添加我的信息的脚本和gpg命令

gpg --gen-key
gpg --armor --export [email protected] > zhsoft.gpg

脚本:

#!/usr/bin/env bash

set -eux

DEB_FOLDERS="./"
GPG_KEY="[email protected]"
APT_CONF="/etc/apt-ftparchive.conf"

pushd "$DEB_FOLDERS" >/dev/null 2>&1 
[[ -d "dists/stable/main/binary-amd64/" ]] || mkdir -p dists/stable/main/binary-amd64/
[[ -d "pool/main" ]] || mkdir -p pool/main

dpkg-scanpackages --arch amd64 pool/ > dists/stable/main/binary-amd64/Packages
cat dists/stable/main/binary-amd64/Packages | gzip -9 > dists/stable/main/binary-amd64/Packages.gz


apt-ftparchive release dists/stable > dists/stable/Release

# Add deb info to head
Origin=ppwq
Label=ppwq
Codename=stable
Version=2024
Architectures=amd64
Components=main
Description="$Origin packages"

tee $APT_CONF << EOF
Origin: $Origin
Label: $Label
Codename: $Codename
Version: $Version
Architectures: $Architectures
Components: $Components
Description: $Description
EOF

sed -i "1r $APT_CONF" dists/stable/Release

cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs > dists/stable/Release.gpg
cat dists/stable/Release | gpg --default-key "$GPG_KEY" -abs --clearsign > dists/stable/InRelease

popd > /dev/null 2>&1

gpg 密钥生成成功了没?

gpg --version

看看 gpg 的版本号是多少?

Reply View the author
Zeta.
deepin
2024-02-18 15:46
#4
爱开发

gpg 密钥生成成功了没?

gpg --version

看看 gpg 的版本号是多少?

生成了这是版本

Zero@Zero-PC:~$ gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/Zero/.gnupg
支持的算法:
公钥: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
密文: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
    CAMELLIA128, CAMELLIA192, CAMELLIA256
散列: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
压缩:  不压缩, ZIP, ZLIB, BZIP2

Reply View the author
爱开发
deepin
2024-02-19 11:04
#5
Zeta.

生成了这是版本

Zero@Zero-PC:~$ gpg --version
gpg (GnuPG) 2.2.12
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Home: /home/Zero/.gnupg
支持的算法:
公钥: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
密文: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
    CAMELLIA128, CAMELLIA192, CAMELLIA256
散列: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
压缩:  不压缩, ZIP, ZLIB, BZIP2

应该没问题。你用最新的脚本试试。自己修改下环境变量。再操作看看。

给了可执行权限后,空参数执行。

Reply View the author
Zeta.
deepin
2024-02-24 13:27
#6
爱开发

应该没问题。你用最新的脚本试试。自己修改下环境变量。再操作看看。

给了可执行权限后,空参数执行。

ok

Reply View the author