docs: add self-contained usage guide #2
1 changed files with 295 additions and 1 deletions
296
README.md
296
README.md
|
|
@ -1,3 +1,297 @@
|
|||
# dynapt
|
||||
|
||||
**Dyn**amic **APT** repository
|
||||
**Dyn**amic **APT** repository.
|
||||
|
||||
> [!WARNING]
|
||||
> dynapt is experimental. The configuration format and package compatibility can change, and the project does not yet provide a stable CLI/GUI or APT transport.
|
||||
|
||||
dynapt runs a local APT repository server. When APT requests repository metadata, dynapt downloads the configured packages, generates Debian repository metadata, and serves the resulting files over HTTP.
|
||||
|
||||
It supports direct links to DEB packages and AppImages. AppImages are extracted and wrapped into DEB packages using their desktop entry and icon. Packages from GitHub releases can also be downloaded and filtered by file name.
|
||||
|
||||
dynapt is not a package manager. It makes packages available to APT, so upgrades, searches, installation, and removal can continue using `apt`, `aptitude`, Synaptic, or other APT frontends.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Linux with APT.
|
||||
- `amd64` (`x86_64`) or `arm64` (`aarch64`).
|
||||
- The repository commands rely on `bash`, `coreutils`, `dpkg`, `dpkg-scanpackages`, `apt-ftparchive`, `apt`, `dpkg-deb`, `unsquashfs`, `file`, `chmod`, and `ln`.
|
||||
|
||||
`apt-ftparchive` is provided by `apt-utils`. Install it first on minimal systems where `apt` did not pull it in:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install apt-utils
|
||||
```
|
||||
|
||||
The APT source below uses `trusted=yes` because dynapt currently does not sign repository metadata. Only use this setup on a trusted local machine and do not expose the dynapt port to the network.
|
||||
|
||||
## Installation
|
||||
|
||||
Download and install the current development release automatically:
|
||||
|
||||
```bash
|
||||
wget https://git.kaki87.net/KaKi87/dynapt/releases/download/0.0.0-dev.9b8fa75/dynapt-"$(dpkg --print-architecture)".deb
|
||||
sudo apt install ./dynapt-"$(dpkg --print-architecture)".deb
|
||||
```
|
||||
|
||||
Or download the package manually for:
|
||||
|
||||
- [`amd64` (`x86_64`)](https://git.kaki87.net/KaKi87/dynapt/releases/download/0.0.0-dev.9b8fa75/dynapt-amd64.deb)
|
||||
- [`arm64` (`aarch64`)](https://git.kaki87.net/KaKi87/dynapt/releases/download/0.0.0-dev.9b8fa75/dynapt-arm64.deb)
|
||||
|
||||
The packages are also listed on the [release page](https://git.kaki87.net/KaKi87/dynapt/releases).
|
||||
|
||||
## Configuration
|
||||
|
||||
Create `/opt/dynapt/config.json`:
|
||||
|
||||
```bash
|
||||
sudo nano /opt/dynapt/config.json
|
||||
```
|
||||
|
||||
Start with an empty application list:
|
||||
|
||||
```json
|
||||
{
|
||||
"port": 3000,
|
||||
"concurrency": null,
|
||||
"apps": []
|
||||
}
|
||||
```
|
||||
|
||||
Change `port` if another service already uses port 3000. `concurrency` limits how many applications are downloaded and packaged at the same time. Use `1` on slower connections or lower-powered devices, or `null` to let all applications run concurrently.
|
||||
|
||||
Add the local repository to APT. Replace `3000` if you changed the port in `config.json`:
|
||||
|
||||
```bash
|
||||
echo "deb [trusted=yes] http://127.0.0.1:3000/ /" | sudo tee /etc/apt/sources.list.d/dynapt.list
|
||||
```
|
||||
|
||||
Start the server. It must run as a user that can write to `/opt/dynapt`:
|
||||
|
||||
```bash
|
||||
sudo nohup dynapt >/dev/null 2>&1 &
|
||||
```
|
||||
|
||||
Make it start at boot. Run this as `root`:
|
||||
|
||||
```bash
|
||||
crontab -l | { cat; echo "@reboot dynapt"; } | crontab -
|
||||
```
|
||||
|
||||
The first time APT reads the repository, dynapt downloads and packages the configured applications. It can take longer than a normal APT mirror update.
|
||||
|
||||
## Application configuration
|
||||
|
||||
Each item in `apps` configures one upstream application.
|
||||
|
||||
A direct DEB link uses `url`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Example",
|
||||
"url": "https://example.com/download/package.deb"
|
||||
}
|
||||
```
|
||||
|
||||
A direct AppImage link must set `appimage` to `true`. If the command name should be available in `PATH`, set an object with `bin`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Example",
|
||||
"url": "https://example.com/download/package.AppImage",
|
||||
"appimage": {
|
||||
"bin": "example"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A GitHub release uses `github` instead of `url`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Example",
|
||||
"github": {
|
||||
"repo": "example/example",
|
||||
"filter": "*.deb",
|
||||
"prerelease": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If a direct URL returns JSON instead of a package, use a `jq` expression to extract the package URL:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Example",
|
||||
"url": "https://example.com/download/latest.json",
|
||||
"jq": ".downloads[0].url",
|
||||
"appimage": true
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration fields
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `name` | Yes | Display name used by dynapt. |
|
||||
| `url` | One of `url` or `github` | Direct HTTPS download URL for a DEB or AppImage. |
|
||||
| `github.repo` | With `github` | GitHub repository in `owner/name` format. |
|
||||
| `github.filter` | No | Glob expression used to select release assets. |
|
||||
| `github.prerelease` | No | Inspect prereleases when `true`. |
|
||||
| `appimage` | No | Use `true` for an AppImage, or an object containing `bin`. |
|
||||
| `appimage.bin` | No | Command name to link from `/usr/bin`. |
|
||||
| `jq` | No | Applied to JSON returned by `url`; requires `url`. |
|
||||
| `id` | No | Internal UUID used for cache metadata. dynapt creates it automatically. |
|
||||
|
||||
If APT updates many GitHub-hosted applications, GitHub API rate limits can interrupt metadata requests. Add a personal access token to the root configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"githubAccessToken": "github_pat_example_placeholder"
|
||||
}
|
||||
```
|
||||
|
||||
## Complete example
|
||||
|
||||
The following example contains direct-download configurations that have been useful in the current experimental stage:
|
||||
|
||||
```json
|
||||
{
|
||||
"port": 3000,
|
||||
"concurrency": null,
|
||||
"apps": [
|
||||
{
|
||||
"name": "Discord",
|
||||
"url": "https://discord.com/api/download?platform=linux&format=deb"
|
||||
},
|
||||
{
|
||||
"name": "Free Download Manager",
|
||||
"url": "https://files2.freedownloadmanager.org/6/latest/freedownloadmanager.deb"
|
||||
},
|
||||
{
|
||||
"name": "kDrive",
|
||||
"url": "https://www.infomaniak.com/drive/latest",
|
||||
"jq": ".[\"linux-amd64\"].downloadurl",
|
||||
"appimage": true
|
||||
},
|
||||
{
|
||||
"name": "Kiro",
|
||||
"url": "https://prod.download.desktop.kiro.dev/stable/metadata-linux-x64-deb-stable.json",
|
||||
"jq": ".releases[].updateTo.url | select(endswith(\".deb\"))"
|
||||
},
|
||||
{
|
||||
"name": "LM Studio",
|
||||
"url": "https://lmstudio.ai/download/latest/linux/x64",
|
||||
"appimage": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
For an `arm64` kDrive client, replace `linux-amd64` in its `jq` filter with `linux-arm64`. The LM Studio example shown here uses the current `x64` download URL.
|
||||
|
||||
## Using the repository
|
||||
|
||||
After dynapt is configured, refresh APT and install packages using their Debian package names:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
apt search example
|
||||
sudo apt install example-package
|
||||
```
|
||||
|
||||
For AppImages, dynapt derives the package name, version, description, architecture, and icon from the desktop entry inside the AppImage. Direct DEBs retain the metadata supplied by their upstream.
|
||||
|
||||
The server generates repository metadata when APT requests `/Packages` or `/Release`. Downloads are cached and ETag/GitHub release metadata is reused on later requests.
|
||||
|
||||
## Commands
|
||||
|
||||
dynapt also includes commands for debugging and maintenance.
|
||||
|
||||
Fetch and package applications without first installing an APT package:
|
||||
|
||||
```bash
|
||||
sudo dynapt update
|
||||
```
|
||||
|
||||
Show configured applications and compare their available versions with the versions installed through APT:
|
||||
|
||||
```bash
|
||||
sudo dynapt list
|
||||
```
|
||||
|
||||
Remove downloaded files, generated package data, and cache data:
|
||||
|
||||
```bash
|
||||
sudo dynapt clean
|
||||
```
|
||||
|
||||
Refresh only the dynapt APT source:
|
||||
|
||||
```bash
|
||||
sudo apt update \
|
||||
-o Dir::Etc::sourcelist="sources.list.d/dynapt.list" \
|
||||
-o Dir::Etc::sourceparts="-" \
|
||||
-o APT::Get::List-Cleanup="0"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Logs
|
||||
|
||||
Read `/opt/dynapt/dynapt.log` and include the relevant lines together with the APT output when asking for help.
|
||||
|
||||
### Download failures
|
||||
|
||||
Try `sudo dynapt update` to see fetch, download, AppImage extraction, or package generation errors without involving APT. A missing `unsquashfs`, `file`, `apt-ftparchive`, or disk space can prevent packaging from completing.
|
||||
|
||||
### Package appears changed by upstream
|
||||
|
||||
Run `dynapt clean`, then refresh from APT:
|
||||
|
||||
```bash
|
||||
sudo dynapt clean
|
||||
sudo apt update
|
||||
```
|
||||
|
||||
### GitHub rate limits
|
||||
|
||||
Requests to GitHub release metadata can be anonymous or authenticated with `githubAccessToken`. Use a token with the minimum public repository read access and do not include the token in a publicly shared configuration file.
|
||||
|
||||
### Port is already in use
|
||||
|
||||
Either stop the process using port 3000 or change `port` in `/opt/dynapt/config.json` and update the APT source to use the new port.
|
||||
|
||||
## Development
|
||||
|
||||
dynapt is written in JavaScript and runs on [Deno](https://deno.com/). Install Deno and the Debian packaging and AppImage tools listed in the requirements.
|
||||
|
||||
Run the CLI from a checkout:
|
||||
|
||||
```bash
|
||||
./dynapt --version
|
||||
./dynapt list
|
||||
./dynapt update
|
||||
./dynapt serve
|
||||
```
|
||||
|
||||
When run from source, dynapt uses `config.json` and writes cache and package data beneath the checkout rather than `/opt/dynapt`.
|
||||
|
||||
Build both Debian packages:
|
||||
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
Deno compiles `main.js` for `x86_64-unknown-linux-gnu` and `aarch64-unknown-linux-gnu`, and `dpkg-deb` creates:
|
||||
|
||||
- `build/dynapt-amd64.deb`
|
||||
- `build/dynapt-arm64.deb`
|
||||
|
||||
There is not a separate automated test command at the moment. Changes should be checked against the affected CLI commands, server routes, and the packaging steps they touch.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
This README incorporates the experimental setup tutorial originally shared as a [Gist by KaKi87](https://gist.github.com/KaKi87/f620788e9901abbfef4978eb7ad358b4). It is now maintained with the code in this repository, as requested in [issue #1](https://git.kaki87.net/KaKi87/dynapt/issues/1).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue