https://github.com/cwaits6/apk-datasource
Auto-update pinned APK package versions in Dockerfiles via Renovate custom datasource
https://github.com/cwaits6/apk-datasource
alpine apk datasource docker dockerfile k8s kubernetes renovate version-pinning wolfi wolfi-base
Last synced: about 2 months ago
JSON representation
Auto-update pinned APK package versions in Dockerfiles via Renovate custom datasource
- Host: GitHub
- URL: https://github.com/cwaits6/apk-datasource
- Owner: cwaits6
- License: apache-2.0
- Created: 2026-03-16T00:32:50.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-01T02:52:29.000Z (2 months ago)
- Last Synced: 2026-04-01T05:18:00.324Z (2 months ago)
- Topics: alpine, apk, datasource, docker, dockerfile, k8s, kubernetes, renovate, version-pinning, wolfi, wolfi-base
- Language: Go
- Homepage:
- Size: 675 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
apk-datasource
Auto-update pinned APK package versions in Dockerfiles using [Renovate](https://docs.renovatebot.com/).
**The problem:** Working with Wolfi or Alpine containers? You pin APK packages for reproducibility — `apk add curl=8.11.1-r0` — but Renovate can't auto-update them. It has no built-in APK datasource. This tool fills that gap. See [renovatebot/renovate#5422](https://github.com/renovatebot/renovate/issues/5422) for context.
## Why This Matters
- **Automated updates** — Stop manually tracking APK package versions
- **Reproducible builds** — Pin exact versions while staying current
- **Works with Renovate** — Integrates with your existing dependency management workflow
- **No server required** — Use the public hosted index, or deploy your own (Docker, Helm, GitLab CI, or binary)
- **Supports Wolfi & Alpine** — Works with both Chainguard Wolfi and Alpine Linux indexes
## Hosted Index (No Server Required)
A public index for Wolfi x86_64 and aarch64 packages is hosted on GitHub Pages and refreshed every 4 hours. Point your Renovate config directly at it — no server to run:
```text
https://cwaits6.github.io/apk-datasource/x86_64/{{packageName}}.json
```
(Replace `{{packageName}}` with an actual package name, e.g., `curl`)
**Test it:** Fetch the datasource for a package to see the available versions:
```bash
curl -s https://cwaits6.github.io/apk-datasource/x86_64/curl.json | jq .
```
Replace `curl` with any APK package name to test others (e.g., `go`, `git`, `busybox`).
## Renovate Setup
Add the following `customDatasources` and `customManagers` blocks to your existing `renovate.json`. Renovate will start opening PRs to update pinned APK versions (e.g. `curl=8.15.0-r2` -> `curl=8.19.0-r1`):
```json
{
"customDatasources": {
"apk-wolfi": {
"defaultRegistryUrlTemplate": "https://cwaits6.github.io/apk-datasource/x86_64/{{packageName}}.json",
"format": "json"
}
},
"customManagers": [
{
"customType": "regex",
"fileMatch": ["(^|/)Dockerfile[^/]*$"],
"matchStringsStrategy": "recursive",
"matchStrings": [
"apk\\s+add[^\\n\\\\]*(?:\\\\[^\\S\\n]*\\n[^\\n\\\\]*)*",
"(?[a-zA-Z0-9][a-zA-Z0-9._+-]*)=(?\\d+[^\\s\\\\]+)"
],
"datasourceTemplate": "custom.apk-wolfi",
"versioningTemplate": "loose"
}
]
}
```
**Want to self-host instead?** See [Deployment](#deployment) for Docker, Helm, GitLab CI, or binary options. Replace the `defaultRegistryUrlTemplate` URL with your server address (e.g. `https://apk.example.com/x86_64/{{packageName}}.json`)
## Quick Start
### Install
Download a pre-built binary from [GitHub Releases](https://github.com/cwaits6/apk-datasource/releases/latest), or install from source:
```bash
go install github.com/cwaits6/apk-datasource/cmd/apk-datasource@latest
```
### Generate static files
```bash
apk-datasource generate --output-dir ./output
```
### Serve over HTTP
```bash
apk-datasource serve
```
Both commands default to the Chainguard Wolfi index for x86_64 and aarch64. Override with `--index-url` for other indexes (see [Available Indexes](#available-indexes)).
## Deployment
### Docker Compose
```bash
docker compose -f deploy/docker/docker-compose.yml up -d
```
The server runs on port 3000 with a 4-hour refresh interval. Edit `deploy/docker/docker-compose.yml` to customize settings.
### Helm
```bash
helm install apk-datasource ./charts/apk-datasource
```
See [`charts/apk-datasource/`](charts/apk-datasource/) for all configurable values.
## CLI Reference
| Command | Description |
|---------|-------------|
| `apk-datasource generate` | Fetch indexes and write JSON files to disk |
| `apk-datasource serve` | Serve JSON over HTTP with periodic refresh |
| `apk-datasource version` | Print version info |
### Global Flags
| Flag | Default | Description |
|------|---------|-------------|
| `--log-level` | `info` | Log level (debug, info, warn, error) |
| `--log-format` | `text` | Log format (text, json) |
### `generate` Flags
| Flag | Default | Description |
|------|---------|-------------|
| `--index-url` | Chainguard Wolfi x86_64 + aarch64 | APKINDEX.tar.gz URL (repeatable) |
| `--output-dir` | `./output` | Output directory |
| `--source-url` | *(auto-detect)* | Override source URL |
| `--homepage` | *(from index)* | Override homepage |
### `serve` Flags
| Flag | Default | Description |
|------|---------|-------------|
| `--index-url` | Chainguard Wolfi x86_64 + aarch64 | APKINDEX.tar.gz URL (repeatable) |
| `--port` | `3000` | HTTP port |
| `--refresh-interval` | `4h` | Refresh interval |
| `--source-url` | *(auto-detect)* | Override source URL |
| `--homepage` | *(from index)* | Override homepage |
| `--metrics` | `true` | Enable Prometheus metrics on `/metrics` |
## Metrics
When `--metrics` is enabled (the default), the server exposes a Prometheus-compatible `/metrics` endpoint on the same port. Available metrics:
| Metric | Type | Labels | Description |
|--------|------|--------|-------------|
| `http_requests_total` | Counter | method, path, status_code | Total HTTP requests |
| `http_request_duration_seconds` | Histogram | method, path, status_code | Request latency |
| `refresh_total` | Counter | status | Index refresh attempts |
| `refresh_duration_seconds` | Histogram | status | Refresh latency |
| `refresh_packages` | Gauge | — | Package count after last refresh |
| `server_ready` | Gauge | — | Server readiness (0/1) |
Scrape with Prometheus:
```yaml
scrape_configs:
- job_name: apk-datasource
static_configs:
- targets: ["localhost:3000"]
```
The Helm chart adds `prometheus.io/*` annotations automatically when `metrics.enabled` is `true`.
## Available Indexes
The `--index-url` flag accepts any `APKINDEX.tar.gz` URL. Below are the most common public indexes:
### Chainguard Wolfi (default)
| Architecture | URL |
|--------------|-----|
| x86_64 | `https://apk.cgr.dev/chainguard/x86_64/APKINDEX.tar.gz` |
| aarch64 | `https://apk.cgr.dev/chainguard/aarch64/APKINDEX.tar.gz` |
### Alpine Linux
Replace `v3.23` with your target version, or use `edge` for rolling.
| Repository | Architecture | URL |
|------------|--------------|-----|
| main | x86_64 | `https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/APKINDEX.tar.gz` |
| main | aarch64 | `https://dl-cdn.alpinelinux.org/alpine/v3.23/main/aarch64/APKINDEX.tar.gz` |
| community | x86_64 | `https://dl-cdn.alpinelinux.org/alpine/v3.23/community/x86_64/APKINDEX.tar.gz` |
| community | aarch64 | `https://dl-cdn.alpinelinux.org/alpine/v3.23/community/aarch64/APKINDEX.tar.gz` |
Alpine also supports `armv7`, `ppc64le`, `s390x`, and `riscv64` architectures.
**Example — serve Alpine main + community:**
```bash
apk-datasource serve \
--index-url https://dl-cdn.alpinelinux.org/alpine/v3.23/main/x86_64/APKINDEX.tar.gz \
--index-url https://dl-cdn.alpinelinux.org/alpine/v3.23/community/x86_64/APKINDEX.tar.gz
```
## How It Works
`apk-datasource` fetches `APKINDEX.tar.gz` archives from Wolfi or Alpine repositories, parses the package metadata, and outputs one JSON file per package conforming to Renovate's [custom datasource schema](https://docs.renovatebot.com/modules/datasource/custom/):
```json
{
"releases": [
{ "version": "8.11.1-r0" }
],
"sourceUrl": "https://github.com/wolfi-dev/os",
"homepage": "https://curl.se"
}
```
Two modes: `generate` writes static JSON files to disk, `serve` runs an HTTP server with periodic refresh.
## Contributing
1. Fork the repo
2. Create a feature branch
3. Submit a pull request
## License
[Apache-2.0](LICENSE)