Research

如何建立一个个人软件包仓库(PPA)

This is an article written by my student Xincheng Ren. He helps me setup the Ubuntu software repository for PicoScenes.


本文将介绍如何在linux服务器上构建一个属于你自己的第三方软件仓库(Personal Package Archives,简称PPA),构建完成之后,其他人将可以像安装linux官方源中的软件那样在命令行中安装你定制的软件。而和官方官方软件仓库稍微不同的是,需要首先添加你的软件源,之后便可以使用sudo apt update && sudo apt install xxx来进行安装你的软件。

1.操作平台

安装了Ubuntu20.04的服务器

2.软件仓库简介

很多人可能都在自己的电脑上更改过自己的软件源,以获得更快的软件下载速度,更改不同的源就对应着不同的软件仓库。比如Linux mint可以打开软件源(Software Resources),通过测速和更改镜像源来比较获得一个更快的软件下载源,如图所示:

更改源之后,可以执行sudo apt update && sudo apt upgrade,可以发现下载软件速度明显提高。在更改官方源,update和upgrade时,在系统内部都进行了什么操作呢?

三步操作都各自完成了一个具体的操作:

1.更改官方源。每一个linux系统都有一个或者多个存放源的文件,比如在Linux mint20.04中,文件的完整路径为(对于不同的linux发行版存放软件源的文件可能有所区别,需要根据自己的系统具体查询):/etc/apt/sources.list.d/official-package-repositories.list,在official-package-repositories.list中的内容如下(假设主要(ulyana)源和基础(focal)源均改为清华源):

deb https://mirrors.tuna.tsinghua.edu.cn/linuxmint ulyana main upstream import backport 

deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu focal main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu focal-updates main restricted universe multiverse
deb http://mirrors.tuna.tsinghua.edu.cn/ubuntu focal-backports main restricted universe multiverse

deb http://security.ubuntu.com/ubuntu/ focal-security main restricted universe multiverse
deb http://archive.canonical.com/ubuntu/ focal partner

由图中可知,更改源是更改了第一行,第三四五行的内容。更改之后update和upgrade时查询软件仓库的地址即为清华源所对应的目录。而对于一些不在清华源的软件,则会从ubuntu官方的源仓库来进行安装。

2.update。在更改源之后进行,具体操作为查询软件仓库中的Release文件,InRelease文件以及文件的一些配置信息,数字签名等等。最重要的一点,对比软件仓库中的软件信息文件,是否有版本更新,然后在update查询之后显示有多少软件可以进行更新。

3.upgrade。在update更新之后,如果有软件可以更新,则从所更改的软件源来进行下载安装所有可以更新的软件。

假设你要构建一个包含三个deb包的软件仓库,分别first.deb,second.deb和single.deb,架构全部为amd64,其中的依赖关系为second.deb依赖first.deb,而first.deb和single.deb不依赖任何包。对于常见的linux软件仓库来说,其完成构建时,软件仓库的目录大致如下:

├── dists
│   └── stable
│       ├── Contents-amd64.gz
│       ├── Release
│       ├── Release.gpg
│       ├── apt.conf
│       └── main
│           └── binary-amd64
│               ├── Packages
│               └── Packages.gz
├── pool
│   └── main
│       ├── first.deb
│       ├── second.deb
│       ├── single.deb
└── project
     └── ppa-public-key.gpg

典型的ubuntu仓库有dists目录和pool目录,dists中存放关于软件包的一些信息,如依赖关系,文件大小,所需要的系统架构等等;pool中存放实际要安装的deb包,实际的软件仓库一般main一个目录,可以按照自己的需要进行添加。对于大多数非官方仓库,会多一个project目录,其中存放服务器上导出的公钥文件,当公钥文件导入到系统中时,系统才会认为来自这个服务器的文件是安全的。

更改源可以简单理解为更改安装软件的地址,从不同的网络地址下载软件的速度是不一样的;update则可以简单理解为查询软件包的一系列参数。upgrade和install则可以理解为从安装软件的地址下载软件并安装在本机。从软件安装的角度来说,上述三步是简化了安装软件的步骤,这和你从软件源地址下载deb包点击安装得到的效果是一样的。

3.配置信息生成

假设你在服务器端已经有了first.deb,second.deb和single.deb这三个deb包。则对应于上一节的三个目录dists,pool和project我们已经完成了pool目录中文件的生成。接下来我们需要在服务器端进行一些修改,从而来生成dists和project中的内容。

1.准备操作

1.安装apache2服务器,具体操作参考上一文。

2.创建软件仓库所需要的文件夹,并将前面准备的三个deb包复制到/var/www/html/pool/main目录,预期的效果为:

上层目录为/var/www/html
├── dists
│   └── stable
│       └── main
│           └── binary-amd64
├── pool
│   └── main
│       ├── first.deb
│       ├── second.deb
│       ├── single.deb
└── project

3.安装配置信息生成文件必备软件:

# 安装gpg
$ sudo apt install gpg
# 安装rng-tools
$ sudo apt install rng-tools

gpg可以生成服务器公钥,并导出公钥文件,从而供其他用户导入。rng-tools可以加快gpg生成公钥时产生随机值的过程,否则可能会很久甚至服务器未响应都不会产生所需要的随机值。

4.确保你的服务器上有压缩软件,例如gzip。

5.假设下文中在服务器上的操作均为管理员用户。

2.dists目录中信息文件的生成

以下的操作中,不做特殊说明,均在/var/www/html目录下进行,即在当前目录下列出文件或者查询工作目录的话,结果如下:

$ ls
dists  pool  project
$ pwd
/var/www/html
1.packages文件生成

调用格式为:apt-ftparchive packages deb包所在目录 > Packages文件路径和文件名。

例如如下命令格式:

# 生成packages文件
$ apt-ftparchive packages pool/main > dists/stable/main/binary-amd64/Packages

运行之后会在/var/www/html/dists/stable/main/binary-amd64目录下生成一个Packages文件。Packages中的内容类似如下:

Package: picoscenes-driver
Architecture: amd64
Version: 20191229
Priority: optional
Section: network
Source: picoscenes-driver
Maintainer: Zhiping Jiang <zpj@xidian.edu.cn>
Installed-Size: 2763
Depends: linux-image-5.4.0-45-generic
Filename: pool/main/picoscenes-driver-20191229.deb
Size: 619152
MD5sum: 58b9342be5bcea08c5b66cb2288c2fc7
SHA1: bba0cf6070383b0b5c1e455dfc04b1f2e5af493f
SHA256: 2faeb2d3dadaa6507ba1dc380ce5e23889263ed03d21a654b2fc83954a3530d8
SHA512: 5ddd2710086f5c441c97e5e011fec6317e412ba46e9845f1f758b5f5346675126dc1bff5bc98c815c6384bd1e6f2e8f6dc4f1b486beacf04f8c20ee67a8db259
Homepage: https://zpj.io/PicoScenes
Description: PicoScenes Driver
 This package contains the customized Qualcomm Atheros ar9300 (QCA9300) and Intel Wireless Link 5300 (IWL5300) Wi-Fi drivers for PicoScenes system. To reduce the maintainance work, this driver is ONLY compatible with kernel verion: 5.4.0-45-generic.

Package: picoscenes-platform
Architecture: amd64
Version: 2020.0816.1248
Priority: optional
Section: devel
Maintainer: Zhiping Jiang<zpj@xidian.edu.cn>
Installed-Size: 10340
Depends: picoscenes-driver, build-essential, libboost-all-dev, openjdk-8-jre, libcpprest-dev, libssl-dev, net-tools, p7zip-full, hostapd, cpufrequtils, libsodium23, libfmt-dev, uhd-host, libopenblas-base
Filename: pool/main/picoscenes-platform-2020.0816.1248-Linux.deb
Size: 3395486
MD5sum: 4888b72822ee635507b75c9cb3c7aa8e
SHA1: 16ba5232fbc734e3da77af0685a9e092a0a6c0bd
SHA256: 6ddee9f2936eb25c341f717aeaff67d69eb39d43f7e1e9227f382018697e0238
SHA512: 1dcaa0b05fbc8e2cf0893b18279d3446e693762e14b8b9981079b3da3edf7b6992fb71bfb350e39e22b179144f1118ce370bd3f70ed2f1eb1ce9361c1055a026
Homepage: https://zpj.io/PicoScenes
Description: PicoScenes Platform 
 PicoScenes Platform, depending on PicoScenes Driver, wraps all the low-level Wi-Fi NIC controls into a bunch of powerful APIs for the atop PicoScenes plug-in subsystem.

Package: picoscenes-plugins-demo-rxsbroadcaster-echoprobe
Architecture: amd64
Version: 20.0718.0252
Priority: optional
Section: devel
Maintainer: Zhiping Jiang<zpj@xidian.edu.cn>
Installed-Size: 1153
Depends: picoscenes-platform
Filename: pool/main/picoscenes-plugins-demo-rxsbroadcaster-echoprobe-20.0718.0252-Linux.deb
Size: 349528
MD5sum: 2b61bf7bfced4632148b79d87908d13c
SHA1: 418452d5f64342e960aa35cee5bb59ea8c401794
SHA256: 063f67584a2fcdcfb46c5b9a21eb99d4af19c9ec104d0b40c8f0a2078ba44a53
SHA512: cbb301e0bc46783966b7b719f8c99f8e668efdf64b3a26b3ae89016762135f0cae52a3a20b20e193dcd77145074896f51acc8f83a1e41d4a87cc7b412479d725
Homepage: https://zpj.io/PicoScenes
Description: Three Sample Plug-Ins of PicoScenes System. 
 The plug-ins are: EchoProbe, us-level round-trip CSI measurement in UWB spectrum; RXS-Broadcaster, RxS data forwarding to the remote via UDP protocol; and Demo, the sample code of PicoScenes Plug-In Development Kit (PSPDK).

对于你自己的deb仓库,生成的文件会有所不同,但是所拥有的参数都是类似的,例如Package,Source, Version,Architecture,和Maintainer等等,这些参数都是在deb文件中的control文件中的信息。还有一些是在control文件中所没有的,例如Filename,Size,MD5sum等等,这些都是apt-ftarchive packages所新生成的,主要起了对比文件信息的作用,例如如果软件仓库中的文件大小和packages文件中登记的文件大小不一样的时候,会报错,如下所示:

Get:1  https://服务器地址/ stable main amd64 picoscenes-driver amd64 20191229 [619 kB]
Err:1  https://服务器地址/ stable main amd64 picoscenes-driver amd64 20191229
  Hash Sum mismatch
  Hashes of expected file:
   - SHA512:5ddd2710086f5c441c97e5e011fec6317e412ba46e9845f1f758b5f5346675126dc1bff5bc98c815c6384bd1e6f2e8f6dc4f1b486beacf04f8c20ee67a8db259
   - SHA256:2faeb2d3dadaa6507ba1dc380ce5e23889263ed03d21a654b2fc83954a3530d8
   - SHA1:bba0cf6070383b0b5c1e455dfc04b1f2e5af493f [weak]
   - MD5Sum:58b9342be5bcea08c5b66cb2288c2fc7 [weak]
   - Filesize:619152 [weak]
  Hashes of received file:
   - SHA512:f3bf69496b2f86f9a2a6d69baa3a19cacba20e7125251c922894725603a4e11cec764200ec8207d000033880086530a47e632dcadef0979cf716d7d05e377cf7
   - SHA256:aa768f83bca305c3979399589bbdc0521804401017dda001ea9171517291cedb
   - SHA1:1b03162a6336a58d253b8f919be041b360b04ae7 [weak]
   - MD5Sum:83d4771518c082731bd40e253af4e7f8 [weak]
   - Filesize:618820 [weak]
  Last modification reported: Sat, 15 Aug 2020 02:11:56 +0000
E: Failed to fetch  https://服务器地址/pool/main/picoscenes-driver-20191229.deb  Hash Sum mismatch
   Hashes of expected file:
    - SHA512:5ddd2710086f5c441c97e5e011fec6317e412ba46e9845f1f758b5f5346675126dc1bff5bc98c815c6384bd1e6f2e8f6dc4f1b486beacf04f8c20ee67a8db259
    - SHA256:2faeb2d3dadaa6507ba1dc380ce5e23889263ed03d21a654b2fc83954a3530d8
    - SHA1:bba0cf6070383b0b5c1e455dfc04b1f2e5af493f [weak]
    - MD5Sum:58b9342be5bcea08c5b66cb2288c2fc7 [weak]
    - Filesize:619152 [weak]
   Hashes of received file:
    - SHA512:f3bf69496b2f86f9a2a6d69baa3a19cacba20e7125251c922894725603a4e11cec764200ec8207d000033880086530a47e632dcadef0979cf716d7d05e377cf7
    - SHA256:aa768f83bca305c3979399589bbdc0521804401017dda001ea9171517291cedb
    - SHA1:1b03162a6336a58d253b8f919be041b360b04ae7 [weak]
    - MD5Sum:83d4771518c082731bd40e253af4e7f8 [weak]
    - Filesize:618820 [weak]
   Last modification reported: Sat, 15 Aug 2020 02:11:56 +0000
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?

在Packages文件生成之后,还要做一件事,将Packages文件压缩,存放在和Packages文件相同的目录中,如下:

# 生成压缩包
$ gzip -9c dists/stable/main/binary-amd64/Packages > dists/stable/main/binary-amd64/Packages.gz

在本小节完成后,dists目录中的内容如下:

├── dists
│   └── stable
│       └── main
│           └── binary-amd64
│               ├── Packages
│               └── Packages.gz
2.contents文件生成

调用格式为:apt-ftparchive contents deb包所在目录 > contents文件路径和文件名。由于最终需要的是一个压缩文件,在上述命令进行调整,添加一个压缩文件的一步。

调整后的命令格式参考如下:

# 生成contents文件
$ apt-ftparchive contents pool/main | gzip -9c > dists/stable/Contents-amd64.gz

由于在本文中的deb包架构为amd64,故需要生成一个名为Contents-amd64.gz,可根据自己的软件架构生成Contents-i386.gz或者Contents-armhf.gz。

contents文件中的内容为目录中的deb包中所有安装文件的绝对路径和文件名以及属于哪个deb包。如下所示为contents文件片段:

...
usr/include/gmock/gmock-actions.h picoscenes-platform
usr/include/gmock/gmock-cardinalities.h picoscenes-platform
usr/include/gmock/gmock-function-mocker.h picoscenes-platform
usr/include/gmock/gmock-generated-actions.h picoscenes-platform
...
usr/local/PicoScenes/plugins/libPDK-EchoProbe.so picoscenes-plugins-demo-rxsbroadcaster-echoprobe
usr/local/PicoScenes/plugins/libPDK-demo.so picoscenes-plugins-demo-rxsbroadcaster-echoprobe
usr/local/PicoScenes/plugins/libPlugIn-RXSBroadcaster.so picoscenes-plugins-demo-rxsbroadcaster-echoprobe
...

在本小节完成后,dists目录中的内容如下:

├── dists
│   └── stable
│       ├── Contents-amd64.gz
│       └── main
│           └── binary-amd64
│               ├── Packages
│               └── Packages.gz
3.apt.conf文件制作

atp.conf文件中主要包含了一些软件包的信息,可以参考如下形式,根据自己的需求创建apt.conf文件。若需要详细配置,则可以参考apt官方说明文档进行创建apt.conf文件,最终将apt.conf文件复制到和Contents-amd64.gz同样的目录,apt.conf参考内容如下:

APT::FTPArchive::Release {
Origin "ubuntu";
Label "Ubuntu";
Suite "stable";
Codename "ulyana";
Versin "1.0";
Architecture "amd64";
Components "main";
Description "PicoScenes driver, platform, plugins and all.";
};

在本小节完成后,dists目录中的内容如下:

├── dists
│   └── stable
│       ├── apt.conf
│       ├── Contents-amd64.gz
│       └── main
│           └── binary-amd64
│               ├── Packages
│               └── Packages.gz
4.release文件生成

调用格式为:apt-ftparchive -c apt.conf路径 release dists下对应软件目录 > dists下对应软件目录/Release。命令参考格式如下:

# 生成release文件
$ apt-ftparchive -c dists/stable/apt.conf release dists/stable > dists/stable/Release

生成的Release文件内容形式如下所示:

Codename: ulyana
Components: main
Date: Tue, 08 Sep 2020 03:36:43 +0000
Description: PicoScenes driver, platform, plugins and all.
Label: Ubuntu
Origin: ubuntu
Suite: stable
MD5Sum:
 4de5291165f3ddfdabd6b177f71a9d65             1749 Contents-amd64.gz
 1468f7b3232a231f6a0680036e21fd17              174 Release
 ac956e2363b5d057c9fd507ba17b6f79             2860 main/binary-amd64/Packages
 26f29795d563b5cab3bdd0b84c4b238e             1466 main/binary-amd64/Packages.gz
SHA1:
 38e46946208c73452b9208de8617e8904fb6b5bc             1749 Contents-amd64.gz
 31400d36f372bdae9de45e550a8cc657c6d659dc              174 Release
 b9ee4d61fdba4a8fa6894dddd608485cf2ddcd21             2860 main/binary-amd64/Packages
 3497f0c023366edbba492473e8307c4c26e76a3b             1466 main/binary-amd64/Packages.gz
SHA256:
 addbcd1a4ef90fa4de802db680e0abb79552bf45697ef20533ab7f38b8988215             1749 Contents-amd64.gz
 7ddf81179c6d143f714e443c970e8b1390e1ac17462b070bf03eba68056d083a              174 Release
 3729fad154cf8748e03dd7356985139cabf98eac347c3c9cf686bc67e1795fce             2860 main/binary-amd64/Packages
 74c1888a9f6b82295dcea66b78f9f123ba87ab766d49652859c0c4e66aab5d9b             1466 main/binary-amd64/Packages.gz
SHA512:
 a86ff11bade4672403bd932eb092376fefb4bbc39774e234ec7c2ea48c5c62e3d4becd98c8c7f3abc1fb418df5b6c5981af69989a4df72b6bab3cc756e1a50a1             1749 Contents-amd64.gz
 4ec161deb1ad5107974ef7939e0a84f9650dd085633f8265796efc101c1b00058f5138a494d08594d11f9f18f45597cc73c78ebce7cd784090d7ff78052ee97d              174 Release
 3034171a9c06a3792915823019b9193ec62e5a3b50962330807aed677484b712ee79cd70a75e266fa41f246954180e315636e5a73456875abd1be407e64d1af2             2860 main/binary-amd64/Packages
 9175417730f4988ae29bda88af33fafae2dcbd428f194a34d150cd55a7cd5fcbaa360e54d9cbd874af9c9e923fa2ce529ebce2ae868e8e68ecc3287927421c5b             1466 main/binary-amd64/Packages.gz

在本小节完成后,dists目录中的内容如下:

├── dists
│   └── stable
│       ├── apt.conf
│       ├── Contents-amd64.gz
│       ├── main
│       │   └── binary-amd64
│       │       ├── Packages
│       │       └── Packages.gz
│       └── Release
5.Release.gpg文件

最终Release.gpg文件是要生成在和Release的同一目录下,同样也是dists目录下的一个文件。但是由于是需要用到gpg软件进行操作,目前还没使用到gpg软件,所以将生成Release.gpg文件的操作放在下一章。

3. project目录中信息文件的生成

以下的操作中,若不做特殊说明,均在/var/www/html目录下进行。

1.ppa-public-key.gpg公钥导出

注意:在project目录下的ppa-public-key.gpg文件和之前提到的Release.gpg是不同的两个文件。

目前,你已经安装了gpg和rng-tools,使用gpg –list-keys可以查看当前所生成过的密钥,当未生成过密钥时,显示如下:

# 显示密钥
$ gpg --list-keys

显示为空,则我们需要在服务器端生成一个密钥,使用gpg –full-generate-key来生成密钥,如下所示为生成过程:

# 生成密钥
$ gpg --full-generate-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
  (14) Existing key from card
Your selection? 1(用户输入确认)
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096(用户输入确认)
Requested keysize is 4096 bits
Please specify how long the key should be valid.
         0 = key does not expire
      <n>  = key expires in n days
      <n>w = key expires in n weeks
      <n>m = key expires in n months
      <n>y = key expires in n years
Key is valid for? (0) 0(用户输入确认)
Key does not expire at all
Is this correct? (y/N) Y(用户输入确认)

GnuPG needs to construct a user ID to identify your key.

Real name: PPA-Demo(用户输入确认)
Email address: XX@XXX.com(用户输入确认)
Comment: NO(用户输入确认)
You selected this USER-ID:
    "PPA-Demo (NO) <XX@XXX.com>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
(会弹出一个窗口让你提示输入公钥密码以及重复一遍密码,如下)     
             
 │ Please enter the passphrase to                       │                      
 │ protect your new key                                 │                      
 │                                                      │                      
 │ Passphrase: ________________________________________ │                      
 │                                                      │                      
 │       <OK>                              <Cancel>     │     
                 
(假设输入的密码为PPAPwd并确认)
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key 7B2677D04250EA0E marked as ultimately trusted
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/DF431E9AFB953A977D83071A7B2677D04250EA0E.rev'
public and secret key created and signed.

pub   rsa4096 2020-09-08 [SC]
      DF431E9AFB953A977D83071A7B2677D04250EA0E
uid                      PPA-Demo (NO) <XX@XXX.com>
sub   rsa4096 2020-09-08 [E]

此时再次显示密钥:

# 显示公钥
$ gpg --list-keys
/root/.gnupg/pubring.kbx
------------------------
pub   rsa4096 2020-09-08 [SC]
      DF431E9AFB953A977D83071A7B2677D04250EA0E
uid           [ultimate] PPA-Demo (NO) <XX@XXX.com>
sub   rsa4096 2020-09-08 [E]

至此,我们完成了在服务器端生成密钥的操作,接下来就要导出密钥文件到project,操作命令如下:

# 导出公钥文件
$ gpg --export  > project/ppa-public-key.gpg

在本小节完成后,project目录中的内容如下:

└── project
    └── ppa-public-key.gpg
2.Release.gpg文件生成(最终生成后存放在dists/stable目录中)

注意:本节的操作必须在Release文件生成后和密钥生成之后才可以进行,否则会出错。

调用格式为:gpg –passphrase ‘PPAPwd’ –pinentry-mode loopback –output dists/stable/Release.gpg -abs dists/stable/Release。如下:

# 生成Release.gpg文件
$ gpg --passphrase "PPAPwd" --pinentry-mode loopback --output dists/stable/Release.gpg -abs dists/stable/Release

本条命令有点复杂,可以根据参数和值的顺序来进行分析:

命令开始于gpg,表示使用gpg软件中的gpg命令;

第一个参数为–passphrase,表示密钥的密码,即在–full-generate-key一步中输入的密码,在这里密码为:PPAPwd;

第二个参数为–pinentry-mode,表示设置pinentry的模式,在这里设置为loopback,表示可以使用–passphrase所提供的密码,从而可以实现不弹出界面而输入密钥密码,使之可以用脚本在服务器端导出公钥文件;

第三个参数为–output,表示写入到文件,值为dists/stable/Release.gpg。

第四个参数为-abs,包含–armor,–detach-sign和–sign(–clear-sign)三个参数,–armor表示输出一个以ascii编码的文件,其余两个参数表示签名。值为dists/stable/Release,表示使用之前生成的Release文件。

以上参数的详细含义可以通过:man gpg > gpg帮助手册。来进行查看。

最终生成的文件内容形式如下:

-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEEk5EedDfs91PXpQSCKfS6vV0k7tIFAl9XJBcACgkQKfS6vV0k
7tIDJA/+JA/aE5TuSwZ3TY9jXlLZ7jN1vzmZ3kYrYf9u8YRfcuApiS8zt1gc8R8g
o3qvy8Cnc2ifVJai1fnmfCNDOR3LQru6VWfNJqRiO/GHqc3IYsU2prNDJV+jXp57
d0g3nLqKeCNlWgqxzvvcDC1wsZwiwMrjXxdNQXPWYolo79udmhPlW2lfQLnQfGDE
OqP5qlDPTMvO3Agd+hDvel4T9wCha1QYc97vC369lb/wUUkzVSp6arOEN8iTu3fM
fGEl9O6dPCocDLaQGiSiepQiShoxDCE4d9McE2XQ2c4n1rwaYqlx6NckaM/PH8PL
1/oJNx0ocVZd4SDttYh9Ir6yRKJppOZ7hbv64+xTEKcvKNTaTvXC85NVr/6Q7d+W
Peyn0wVuMfmzHcbgZ6ckwjv9GMUlKtp/TL18xuUFMxI72tzSItmpH7/2aqI5q3NR
vVIy7NlDnDKjalrGsiQWOZb9jJAVacYzqN1SkDjK0Dt6WAQtRMSVq9y9fbjIBR7g
MNwCAQs8wMSLPcehMrpi6Ny6om3FMeoZ4G2p4IVhPSeVUIRjowF+h7eLjASCGQpH
kjzUaEgUqXvpXuZxmXT2qLJcxhiDQR9qqCDTpuo1Ps8XdcR4gjtYemSTc/3QkXlK
GDGpCRdyndN/WRvqq2dhT/zkUTAZtao7ijqZFbnthNftTn5j06w=
=Wk3o
-----END PGP SIGNATURE-----

到此为止,一个完整的PPA仓库创建完成。此时,目录结构如下:

├── dists
│   └── stable
│       ├── apt.conf
│       ├── Contents-amd64.gz
│       ├── main
│       │   └── binary-amd64
│       │       ├── Packages
│       │       └── Packages.gz
│       ├── Release
│       └── Release.gpg
├── pool
│   └── main
│       ├── picoscenes-driver-20191229.deb
│       ├── picoscenes-platform-2020.0816.1248-Linux.deb
│       └── picoscenes-plugins-demo-rxsbroadcaster-echoprobe-20.0718.0252-Linux.deb
└── project
    └── ppa-public-key.gpg

4.使用定制软件仓库安装软件

当搭建软件仓库成功后,在浏览器访问服务器IP或者访问对应域名,可以看见类似如下所示图:

这时其他用户就可以使用你定制的PPA,具体操作如下:

1.添加密钥

# 添加密钥(q后为大写英文字母O)
$ wget -qO- https://服务器地址/project/ppa-public-key.gpg | sudo apt-key add -
OK

显示OK即可,这时可以通过apt-key list可以查看已经信任的密钥:

# 显示信任密钥
$ apt-key list
/etc/apt/trusted.gpg
--------------------
...
pub   rsa4096 2020-09-08 [SC]
      DF43 1E9A FB95 3A97 7D83  071A 7B26 77D0 4250 EA0E
uid           [ unknown] PPA-Demo (NO) <XX@XXX.com>
sub   rsa4096 2020-09-08 [E]
...
/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-archive.gpg
------------------------------------------------------
pub   rsa4096 2012-05-11 [SC]
      790B C727 7767 219C 42C8  6F93 3B4F E6AC C0B2 1F32
uid           [ unknown] Ubuntu Archive Automatic Signing Key (2012) <ftpmaster@ubuntu.com>

/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg
------------------------------------------------------
pub   rsa4096 2012-05-11 [SC]
      8439 38DF 228D 22F7 B374  2BC0 D94A A3F0 EFE2 1092
uid           [ unknown] Ubuntu CD Image Automatic Signing Key (2012) <cdimage@ubuntu.com>
...

可以看到其中有我们在服务器端生成的密钥,这表示此时PC机信任来自这个服务器密钥生成的配置信息。在添加密钥之后便可以添加软件仓库。

2.添加软件仓库

添加软件仓库的命令add-apt-repository在软件包software-properties-common中,确保你的服务器已经安装software-properties-common,若没有安装,执行sudo apt install software-properties-common进行安装。

安装完成之后,执行如下命令添加软件仓库:

# 添加软件仓库
$ sudo add-apt-repository 'deb [arch=amd64] https://服务器地址/ stable main'

添加之后如果执行sudo apt update将会看见你的服务器地址出现在列表中,类似如下:

# 更新源
$ sudo apt update
...
Ign:16 https://服务器地址 stable InRelease                                                                                                    
Get:17 https://服务器地址 stable Release [1,896 B]                                                                                             
Get:19 https://服务器地址 stable Release.gpg [659 B]                                        
Get:20 https://服务器地址 stable/main amd64 Packages [1,690 B]  
...
Reading package lists... Done                                    
Building dependency tree       
Reading state information... Done
All packages are up to date.

这表明添加密钥及软件仓库成功,此后,就可以在终端直接sudo apt install xxx来安装你定制的软件。

3.移除密钥以及软件仓库

当出于某种原因需要移除密钥和软件仓库时,可以执行如下代码:

# 移除密钥(引号中的值即为apt-key list中显示的一长串字母数字的组合)
$ sudo apt-key del 'DF43 1E9A FB95 3A97 7D83  071A 7B26 77D0 4250 EA0E'
OK
# 移除软件仓库
sudo apt-add-repository -r 'deb [arch=amd64] https://服务器地址/ stable main'

两步都成功后,定制软件仓库完整的从本地移除,之后执行一次apt update来更新一下源仓库的配置信息即可。

对于基于ubuntu的发行版的linux机器,例如Linux mint20.04,可以在软件源(Software Sources)中进行移除软件仓库和认证密钥,如下:

至此,一个完整的定制软件仓库生成,使用以及移除全部完成。

Leave a Reply

Your email address will not be published. Required fields are marked *