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

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

Awesome Lists containing this project

README

          

apk-datasource


apk-datasource logo


Go Version
Release
CI
Container Build
OpenSSF Scorecard
GHCR
Docker Hub
License

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)