Connecting Composer
Configure composer.json, mint a token, and authenticate Composer against your Packyard registry.
Updated April 27, 2026
Once Packyard is running, point your project at it from composer.json, mint a token in the dashboard, and authenticate Composer with HTTP Basic. Three steps, all local to the project that wants to install your private packages.
Every Packyard install ships with a default organization on first
boot; URLs always include the org slug. Replace default with whatever
slug you've set up if you've added more orgs (see Organizations).
Add the registry to composer.json
{
"repositories": [
{
"type": "composer",
"url": "https://repo.example.com/default"
}
]
}The hostname is whatever you set as PACKYARD_BASE_URL; the path
suffix is the org slug. Composer treats the resulting URL as a
packages.json endpoint and fetches metadata, providers, and dist
zips from there.
Mint a token
In the Packyard dashboard, open Tokens → New token. The dashboard generates the token and a unique password together, displayed exactly once. Copy them now — they're not retrievable later.
| Field | Notes |
|---|---|
| Name | A label for your records ("CI: production", "ci-acme", etc.). |
| Expiry | Optional. Use short-lived tokens for CI; longer for development workstations. |
| Scope | Tokens are scoped to one organization. They cannot reach another org's packages. |
The token is hashed (SHA-256) at rest. The password is hashed with bcrypt. Neither is recoverable; rotate by minting a new one and revoking the old.
Authenticate Composer
Tell Composer to send the token as HTTP Basic credentials for that hostname:
composer config --auth http-basic.repo.example.com YOUR_TOKEN YOUR_PASSWORDThis writes to ~/.composer/auth.json (or auth.json next to composer.json if you pass --global=false). Composer will now send Authorization: Basic <base64(token:password)> on every request to repo.example.com.
Verify:
composer config --auth --list | grep repo.example.com
composer installIf the install resolves your private packages without a 401, you're done.
CI / automation
For unattended environments, prefer auth.json next to composer.json:
{
"http-basic": {
"repo.example.com": {
"username": "YOUR_TOKEN",
"password": "YOUR_PASSWORD"
}
}
}Then:
COMPOSER_AUTH=$(cat auth.json) composer installOr expose the same JSON via the COMPOSER_AUTH env var directly so you never have to write the file in CI:
export COMPOSER_AUTH='{"http-basic":{"repo.example.com":{"username":"'"$TOKEN"'","password":"'"$PASS"'"}}}'
composer install --no-interaction --prefer-distHeads up. Composer matches
http-basicentries byhost:portexactly. If your registry runs at a non-standard port, the key must berepo.example.com:9090, notrepo.example.com.
Token rotation
- Mint a new token in the dashboard.
- Update
auth.json(or your CI secret) with the new credentials. - Confirm
composer installstill resolves. - Revoke the old token in the dashboard.
For audit purposes, every token has a "last used" timestamp and a per-token download counter — both visible from the dashboard.
Troubleshooting
- 401 Unauthorized: confirm the host key in
auth.jsonmatches the registry host (and port, if non-standard). Re-runcomposer config --auth --listto inspect what Composer thinks it has. - 404 on a known package: double-check the URL has the right org slug.
https://repo.example.com/default/packages.jsonandhttps://repo.example.com/acme/packages.jsonare different endpoints; a token from one org cannot read the other. - TLS errors: Packyard binds plain HTTP. For public deployments, terminate TLS at a reverse proxy — see the recipes in the installation guide.
- Slow first install: metadata builds the first time it's requested, then caches in memory. Subsequent installs hit the in-memory cache. Restarting Packyard clears it; the rebuild is automatic on next request.