A lightweight, on-premises Debian package artifact repository service.
- Debian Package Storage: Upload, download, list, and delete
.debpackages - API Key Authentication: Role-based access control (admin, write, read)
- REST API: Simple JSON API for CI/CD integration
- Filesystem Backend: Configurable local storage with metadata tracking
- Validation: Debian package structure validation on upload
- Observability: Health endpoints, Prometheus metrics, structured JSON logging
- Systemd Integration: Runs as a managed service on Debian/Ubuntu systems
# Install dependencies
npm install
# Set environment variables for development
export POSITORY_DATA_ROOT=/tmp/pository/data
export POSITORY_LOG_PATH=/tmp/pository/logs
export POSITORY_API_KEYS_PATH=/tmp/pository/api-keys.json
export POSITORY_ADMIN_KEY=your-secret-admin-key
export POSITORY_PORT=3000
# Start the server
npm start# Build the Debian package
sudo apt-get install -y devscripts debhelper dh-exec
dpkg-buildpackage -us -uc -b
# Install
sudo dpkg -i ../pository_*.deb
# The service will auto-start and an admin key will be generated
# Check the admin key in /etc/pository/config.yamlAll API endpoints (except health checks) require authentication via the X-Api-Key header:
curl -H "X-Api-Key: your-api-key" http://localhost:3000/api/v1/packages| Method | Path | Description |
|---|---|---|
| GET | /healthz |
Liveness probe |
| GET | /readyz |
Readiness probe |
| GET | /metrics |
Prometheus metrics |
| Method | Path | Description | Required Role |
|---|---|---|---|
| POST | /api/v1/packages |
Upload package | write |
| GET | /api/v1/packages |
List packages | read |
| GET | /api/v1/packages/:repo/:dist/:comp/:arch/:name/:version |
Get metadata | read |
| GET | /repo/:dist/:comp/:arch/:name_:version.deb |
Download package | read |
| DELETE | /api/v1/packages/:repo/:dist/:comp/:arch/:name/:version |
Delete package | admin |
| Method | Path | Description | Required Role |
|---|---|---|---|
| POST | /api/v1/keys |
Create API key | admin |
| GET | /api/v1/keys |
List API keys | admin |
| DELETE | /api/v1/keys/:id |
Delete API key | admin |
curl -X POST http://localhost:3000/api/v1/packages \
-H "X-Api-Key: your-write-key" \
-F "repo=default" \
-F "distribution=stable" \
-F "component=main" \
-F "file=@mypackage_1.0.0_amd64.deb"Note: Package metadata (name, version, architecture) is extracted from the Debian control file for gzip-compressed packages. For packages using xz or zstd compression (common in modern Debian packages), metadata must be provided via the filename format name_version_arch.deb.
curl -H "X-Api-Key: your-read-key" \
-O http://localhost:3000/repo/stable/main/amd64/mypackage_1.0.0.debcurl -X POST http://localhost:3000/api/v1/keys \
-H "X-Api-Key: your-admin-key" \
-H "Content-Type: application/json" \
-d '{"role": "write", "description": "CI/CD upload key"}'Configuration is loaded from /etc/pository/config.yaml or the path specified by POSITORY_CONFIG environment variable.
# Data storage root directory
dataRoot: /var/lib/pository
# Log file directory
logPath: /var/log/pository
# Server settings
port: 3000
bindAddress: 0.0.0.0
# TLS configuration
tls:
enabled: false
cert: /etc/pository/server.crt
key: /etc/pository/server.key
# Upload size limit (bytes)
maxUploadSize: 104857600 # 100MB
# Allowed repository names
allowedRepos:
- default
- releases
- snapshots
# Path to API keys storage
apiKeysPath: /etc/pository/api-keys.json
# Bootstrap admin key
adminKey: your-secret-admin-keyAll configuration options can be overridden with environment variables:
| Variable | Description |
|---|---|
POSITORY_CONFIG |
Path to config file |
POSITORY_DATA_ROOT |
Data storage directory |
POSITORY_LOG_PATH |
Log directory |
POSITORY_PORT |
Server port |
POSITORY_BIND_ADDRESS |
Bind address |
POSITORY_ADMIN_KEY |
Bootstrap admin API key |
POSITORY_API_KEYS_PATH |
API keys file path |
POSITORY_TLS_CERT |
TLS certificate path |
POSITORY_TLS_KEY |
TLS key path |
POSITORY_MAX_UPLOAD_SIZE |
Max upload size (bytes) |
/var/lib/pository/
{repo}/
index.json
{distribution}/
{component}/
{architecture}/
{name}/{version}/
package.deb
metadata.json
This repository provides a reusable GitHub Action for uploading Debian packages to a Pository instance.
- name: Upload to Pository
uses: rsxdalv/pository@main
with:
host: ${{ secrets.POSITORY_URL }}
api-key: ${{ secrets.POSITORY_API_KEY }}
file: path/to/package.deb
repo: 'default' # optional, defaults to 'default'
distribution: 'stable' # optional, defaults to 'stable'
component: 'main' # optional, defaults to 'main'Inputs:
host(required): URL of your Pository instance (e.g.,https://pository.example.com)api-key(required): API key with write permissionfile(required): Path to the Debian package file to uploadrepo(optional): Repository name, defaults todefaultdistribution(optional): Distribution name, defaults tostablecomponent(optional): Component name, defaults tomain
Outputs:
package-name: Name of the uploaded packagepackage-version: Version of the uploaded packagepackage-architecture: Architecture of the uploaded package
Security Note: Always store your Pository URL and API key as GitHub secrets for additional security.
See .github/workflows/publish-example.yaml for a complete example workflow that builds and publishes a Debian package to a pository instance.
Required secrets:
POSITORY_URL: URL of your pository instancePOSITORY_API_KEY: API key with write permission
# Install dependencies
npm install
# Run tests
npm test
# Run linter
npm run lint
# Start in development mode (with auto-reload)
npm run dev# Run all tests
npm test
# Run specific test file
node --import=tsx --test tests/storage.test.ts- Always use HTTPS in production (configure TLS or use a reverse proxy)
- Store the admin key securely and rotate regularly
- Create scoped API keys with minimal required permissions
- Use firewall rules to restrict access
- Regularly review access logs
- Built-in rate limiting (100 requests/minute per API key or IP)
MIT