An open API service indexing awesome lists of open source software.

https://github.com/anduin2017/learnapt


https://github.com/anduin2017/learnapt

Last synced: about 1 year ago
JSON representation

Awesome Lists containing this project

README

          

# Learn Apt and Deb

我写了一个有意思的小程序。它的名字叫 apt-vis。它是用 Python 写的。它的作用是可视化一下 apt 包的依赖关系。

我已经把它写完了。但是,我想把这个小程序发给我的好朋友们,让他们可以下载。我的包依赖了 apt、python3 和 bash。

apt-vis 文件的开头是这样的:

```python
#!/usr/bin/env python3
import subprocess
from collections import defaultdict, deque
from concurrent.futures import ThreadPoolExecutor
import threading
import os
import sys
import webbrowser
import urllib.request
```

我想,如果可以把它放置在 /usr/local/bin/apt-vis 就算是安装成功了。

考虑到我的所有朋友都是 debian 用户,所以我计划这么干:

* 首先将 apt-vis 文件和相关的其它文件准备好,放在一个文件夹里。
* 然后使用什么工具,把它弄成一个 deb 文件。
* 我将签名后的 deb 文件,搭建出来一个 apt 服务器。
* 我使用一个静态文件的 Web 服务器,承载这个 apt 服务器。
* 签名仓库的元数据(Release 文件)而不是直接对 .deb 包做签名。
* 我告诉我的好朋友,如何信任我的 key,并且添加我的 apt 源。
* 我告诉我的好朋友,如何安装这个 apt 包。

但是,我暂时想先测测,在我自己电脑上。所以我暂时不打算真的签名。

我希望我的朋友的机器这么配置(暂时只考虑支持 Ubuntu Oracular 版本。我的所有组件都放 main 里):

/etc/apt/sources.list.d/anduins-server.list

## Apt Server 的约定

因为我刚刚学习了 apt 服务器建设的最佳实践,也就是当客户端写了

```bash
deb http://localhost/path/ distro aaa bbb ccc ddd
```

时,apt 会去请求:

* http://localhost/path/dist/distro/aaa/binary-<你的架构>/*
* http://localhost/path/dist/distro/bbb/binary-<你的架构>/*
* http://localhost/path/dist/distro/ccc/binary-<你的架构>/*
* http://localhost/path/dist/distro/ddd/binary-<你的架构>/*

其中,* 的地方需要存储 Packages, Packages.gz, Packages.xz 文件。其实它们内容是相同的。

APT 在更新源时会尝试下载 Packages.xz 或 Packages.gz 优先级较高,找不到才会回退到 Packages。

而这个目录

* http://localhost/path/dist/distro/*

这个目录下的 * 的地方,需要存储 Release,InRelease文件,用于校验仓库的签名。

* 如果仓库同时提供 InRelease 和 Release + Release.gpg,APT 会优先使用 InRelease。
* 如果只提供 Release 和 Release.gpg,APT 也可以验证签名。

所以我打算在客户端使用这个结构:

```
deb [trusted=yes] http://localhost:8080/ubuntu/ oracular main
```

## 生成 Deb 文件

为了生成 deb 文件,我需要一个目录结构。我把 apt-vis 文件放在 /usr/local/bin 下面。

```bash
```bash
anduin@anduin-lunar:~/Desktop/LearnDeb$ tree
.
└── apt-vis_1.0.0-1
├── DEBIAN
│ └── control
└── usr
└── local
└── bin
└── apt-vis
```

如果需要生成 deb 文件,我直接在下面执行:

```bash
dpkg-deb --build apt-vis_1.0.0-1
```

## 搭建 Apt 服务器

我的目录结构已经拼成了:

```bash
anduin@anduin-lunar:~/Desktop/LearnDeb$ tree
.
├── apt-vis_1.0.0-1
│ ├── DEBIAN
│ │ └── control
│ └── usr
│ └── local
│ └── bin
│ └── apt-vis
└── WebRoot
└── ubuntu
├── dists
│ └── oracular
│ ├── main
│ │ └── binary-amd64
│ │ ├── Packages
│ │ ├── Packages.gz
│ │ └── Packages.xz
│ └── Release
└── pool
└── main
└── a
└── apt-vis_1.0.0-1.deb

15 directories, 7 files
```

如果我需要得到 Packages 的文件:

```bash
# Generate packages
cd ~/Desktop/LearnDeb/WebRoot/ubuntu
dpkg-scanpackages pool/ /dev/null > dists/oracular/main/binary-amd64/Packages
gzip -9c dists/oracular/main/binary-amd64/Packages > dists/oracular/main/binary-amd64/Packages.gz
xz -9 < dists/oracular/main/binary-amd64/Packages > dists/oracular/main/binary-amd64/Packages.xz

# Generate release
cd ~/Desktop/LearnDeb/WebRoot/ubuntu/dists/oracular
apt-ftparchive release . > Release
```

接下来,我只需要去把 WebRoot 拷贝到静态文件 Web 服务器下面就可以了。如果我需要新增包,我直接放在 pool/main 的对应目录下就可以了。

我这个服务器除了要server这个apt-vis,我还要 serve 其它我写的一些仓库。所以服务器就是 Anduin 的作品集。暂时只支持 Ubuntu Oracular AMD64。

## 客户端配置

我需要在客户端配置 /etc/apt/sources.list.d/anduin.list 文件:

```bash
deb [trusted=yes] http://localhost:8080/ubuntu/ oracular main
```

然后我需要在客户端执行:

```bash
sudo apt update
sudo apt install apt-vis
```

我们会观察到 apt-vis 被安装了。此时一切都是正常的。