{"id":26938101,"url":"https://github.com/anduin2017/learnapt","last_synced_at":"2025-04-02T13:17:19.574Z","repository":{"id":283628854,"uuid":"952054988","full_name":"Anduin2017/LearnApt","owner":"Anduin2017","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-20T16:56:32.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-30T00:27:06.764Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Anduin2017.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-20T16:56:29.000Z","updated_at":"2025-03-20T16:56:36.000Z","dependencies_parsed_at":"2025-03-21T08:50:06.676Z","dependency_job_id":"b9100d84-ed68-406c-8c6c-8fc8f05e31f2","html_url":"https://github.com/Anduin2017/LearnApt","commit_stats":null,"previous_names":["anduin2017/learnapt"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Anduin2017%2FLearnApt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Anduin2017%2FLearnApt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Anduin2017%2FLearnApt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Anduin2017%2FLearnApt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Anduin2017","download_url":"https://codeload.github.com/Anduin2017/LearnApt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246819777,"owners_count":20839095,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-02T13:17:18.935Z","updated_at":"2025-04-02T13:17:19.567Z","avatar_url":"https://github.com/Anduin2017.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learn Apt and Deb\n\n我写了一个有意思的小程序。它的名字叫 apt-vis。它是用 Python 写的。它的作用是可视化一下 apt 包的依赖关系。\n\n我已经把它写完了。但是，我想把这个小程序发给我的好朋友们，让他们可以下载。我的包依赖了 apt、python3 和 bash。\n\napt-vis 文件的开头是这样的:\n\n```python\n#!/usr/bin/env python3\nimport subprocess\nfrom collections import defaultdict, deque\nfrom concurrent.futures import ThreadPoolExecutor\nimport threading\nimport os\nimport sys\nimport webbrowser\nimport urllib.request\n```\n\n我想，如果可以把它放置在 /usr/local/bin/apt-vis 就算是安装成功了。\n\n考虑到我的所有朋友都是 debian 用户，所以我计划这么干：\n\n* 首先将 apt-vis 文件和相关的其它文件准备好，放在一个文件夹里。\n* 然后使用什么工具，把它弄成一个 deb 文件。\n* 我将签名后的 deb 文件，搭建出来一个 apt 服务器。\n* 我使用一个静态文件的 Web 服务器，承载这个 apt 服务器。\n* 签名仓库的元数据（Release 文件）而不是直接对 .deb 包做签名。\n* 我告诉我的好朋友，如何信任我的 key，并且添加我的 apt 源。\n* 我告诉我的好朋友，如何安装这个 apt 包。\n\n但是，我暂时想先测测，在我自己电脑上。所以我暂时不打算真的签名。\n\n我希望我的朋友的机器这么配置（暂时只考虑支持 Ubuntu Oracular 版本。我的所有组件都放 main 里）：\n\n/etc/apt/sources.list.d/anduins-server.list\n\n## Apt Server 的约定\n\n因为我刚刚学习了 apt 服务器建设的最佳实践，也就是当客户端写了\n\n```bash\ndeb http://localhost/path/ distro aaa bbb ccc ddd\n```\n\n时，apt 会去请求：\n\n* http://localhost/path/dist/distro/aaa/binary-\u003c你的架构\u003e/*\n* http://localhost/path/dist/distro/bbb/binary-\u003c你的架构\u003e/*\n* http://localhost/path/dist/distro/ccc/binary-\u003c你的架构\u003e/*\n* http://localhost/path/dist/distro/ddd/binary-\u003c你的架构\u003e/*\n\n其中，* 的地方需要存储 Packages, Packages.gz, Packages.xz 文件。其实它们内容是相同的。\n\n    APT 在更新源时会尝试下载 Packages.xz 或 Packages.gz 优先级较高，找不到才会回退到 Packages。\n\n而这个目录\n\n* http://localhost/path/dist/distro/*\n\n这个目录下的 * 的地方，需要存储 Release，InRelease文件，用于校验仓库的签名。\n\n    * 如果仓库同时提供 InRelease 和 Release + Release.gpg，APT 会优先使用 InRelease。\n    * 如果只提供 Release 和 Release.gpg，APT 也可以验证签名。\n\n所以我打算在客户端使用这个结构：\n\n```\ndeb [trusted=yes] http://localhost:8080/ubuntu/ oracular main\n```\n\n## 生成 Deb 文件\n\n为了生成 deb 文件，我需要一个目录结构。我把 apt-vis 文件放在 /usr/local/bin 下面。\n\n```bash\n```bash\nanduin@anduin-lunar:~/Desktop/LearnDeb$ tree\n.\n└── apt-vis_1.0.0-1\n    ├── DEBIAN\n    │   └── control\n    └── usr\n        └── local\n            └── bin\n                └── apt-vis\n```\n\n如果需要生成 deb 文件，我直接在下面执行：\n\n```bash\ndpkg-deb --build apt-vis_1.0.0-1\n```\n\n## 搭建 Apt 服务器\n\n我的目录结构已经拼成了：\n\n```bash\nanduin@anduin-lunar:~/Desktop/LearnDeb$ tree\n.\n├── apt-vis_1.0.0-1\n│   ├── DEBIAN\n│   │   └── control\n│   └── usr\n│       └── local\n│           └── bin\n│               └── apt-vis\n└── WebRoot\n    └── ubuntu\n        ├── dists\n        │   └── oracular\n        │       ├── main\n        │       │   └── binary-amd64\n        │       │       ├── Packages\n        │       │       ├── Packages.gz\n        │       │       └── Packages.xz\n        │       └── Release\n        └── pool\n            └── main\n                └── a\n                    └── apt-vis_1.0.0-1.deb\n\n15 directories, 7 files\n```\n\n如果我需要得到 Packages 的文件:\n\n```bash\n# Generate packages\ncd ~/Desktop/LearnDeb/WebRoot/ubuntu\ndpkg-scanpackages pool/ /dev/null \u003e dists/oracular/main/binary-amd64/Packages\ngzip -9c dists/oracular/main/binary-amd64/Packages \u003e dists/oracular/main/binary-amd64/Packages.gz\nxz -9 \u003c dists/oracular/main/binary-amd64/Packages \u003e dists/oracular/main/binary-amd64/Packages.xz\n\n# Generate release\ncd ~/Desktop/LearnDeb/WebRoot/ubuntu/dists/oracular\napt-ftparchive release . \u003e Release\n```\n\n接下来，我只需要去把 WebRoot 拷贝到静态文件 Web 服务器下面就可以了。如果我需要新增包，我直接放在 pool/main 的对应目录下就可以了。\n\n我这个服务器除了要server这个apt-vis，我还要 serve 其它我写的一些仓库。所以服务器就是 Anduin 的作品集。暂时只支持 Ubuntu Oracular AMD64。\n\n## 客户端配置\n\n我需要在客户端配置 /etc/apt/sources.list.d/anduin.list 文件：\n\n```bash\ndeb [trusted=yes] http://localhost:8080/ubuntu/ oracular main\n```\n\n然后我需要在客户端执行：\n\n```bash\nsudo apt update\nsudo apt install apt-vis\n```\n\n我们会观察到 apt-vis 被安装了。此时一切都是正常的。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanduin2017%2Flearnapt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanduin2017%2Flearnapt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanduin2017%2Flearnapt/lists"}