Pulumi Garage Provider
A Pulumi native provider for managing Garage, a self-hosted, S3-compatible distributed object storage system, through its Admin API.
It manages three resources: Bucket (with an optional global alias, static-website
hosting, and storage quotas), Key (an S3 access key), and
BucketKeyPermission (a read/write/owner grant of a Key on a Bucket). Cluster
bootstrapping (nodes, zones, capacity, layout) is out of scope - see
Known limitations.
Installing
This package is available in several languages. Only the Go and YAML SDKs are exercised by this repo's own examples and E2E tests (see Known limitations); the others are generated and published for convenience but are otherwise untested by this project beyond schema-level checks.
Node.js (JavaScript/TypeScript)
npm install @axnic/pulumi-garage
Python
pip install pulumi_garage
Go
go get github.com/axnic/pulumi-garage/sdk/go/pulumi-garage
.NET
dotnet add package Axnic.Pulumi.Garage
The provider binary itself doesn't require any of the above - pulumi plugin install resource garage <version> (or the engine's automatic resolution) fetches it directly
from this repo's GitHub Releases, no
Pulumi Registry listing required.
Quickstart
Point the provider at your Garage cluster's Admin API, either via stack config:
pulumi config set garage:endpoint http://localhost:3903
pulumi config set garage:adminToken <token> --secret
or the GARAGE_ADMIN_ENDPOINT / GARAGE_ADMIN_TOKEN environment variables. This
provider does not bootstrap a Garage cluster for you - see
garagehq.deuxfleurs.fr for setting one up
(garage layout assign/apply, or --single-node for a single-node cluster).
Then, a minimal YAML program (see examples/yaml/Pulumi.yaml,
or examples/go/main.go for the Go equivalent):
name: garage-example-yaml
runtime: yaml
resources:
myKey:
type: garage:Key
properties:
name: my-app-key
myBucket:
type: garage:Bucket
properties:
globalAlias: my-app-bucket
myPermission:
type: garage:BucketKeyPermission
properties:
bucketId: ${myBucket.id}
accessKeyId: ${myKey.accessKeyId}
permissions:
read: true
write: true
outputs:
bucketId: ${myBucket.id}
accessKeyId: ${myKey.accessKeyId}
secretAccessKey: ${myKey.secretAccessKey}
Configuration
| Key | Env var fallback | Description |
|---|---|---|
garage:endpoint |
GARAGE_ADMIN_ENDPOINT |
The base URL of the Garage Admin API, e.g. "http://localhost:3903". |
garage:adminToken (secret) |
GARAGE_ADMIN_TOKEN |
A bearer token authorized against the Garage Admin API. |
garage:s3Endpoint |
GARAGE_S3_ENDPOINT |
The base URL of the Garage S3 API, e.g. "http://localhost:3900". Only required for Bucket's lifecycleRules. |
garage:s3Region |
GARAGE_S3_REGION |
The S3 region to sign requests for. Defaults to "garage" if unset. |
garage:accessKeyId |
GARAGE_S3_ACCESS_KEY_ID |
An access key ID authorized against the Garage S3 API. Only required for lifecycleRules. |
garage:secretAccessKey (secret) |
GARAGE_S3_SECRET_ACCESS_KEY |
The secret access key paired with accessKeyId. Only required for lifecycleRules. |
endpoint/adminToken are required, one way or the other - the provider fails to
configure if neither the config key nor its env var fallback is set. The S3 fields are
optional and only needed to manage a Bucket's lifecycleRules (lifecycle rules are
reachable only over Garage's S3 API, not its Admin API); if you set any of
s3Endpoint/accessKeyId/secretAccessKey, you must set all three.
Compatibility
This provider talks to Garage's Admin API v2, introduced in Garage v2.0.0. Each version below is tested against the full example-program lifecycle (create/update/delete plus a real S3 object upload/download) in its own CI workflow, so its badge reflects that version alone rather than an aggregate:
| Garage version | Status |
|---|---|
| v2.0.0 | |
| v2.1.0 | |
| v2.2.0 | |
| v2.3.0 | |
| v2.4.0 |
Each workflow (.github/workflows/merge_group,pull_request,push.e2e-v2.*.yaml) is
a thin caller of the central reusable E2E workflow in axnic/.github with that version pinned (new versions are added by that repo's E2E Sync workflow, which opens a PR) -
GitHub Actions status badges are per-workflow-file, not per-matrix-leg, which is why
this is five small files rather than one strategy.matrix job. --single-node (the
fast layout-bootstrap path) only exists from Garage v2.3.0 onward, so
docker-compose.yml and scripts/bootstrap-garage.sh always use the manual
layout assign/apply bootstrap instead, which works identically across all five
versions.
Known limitations
This is a v1, personal/small-org provider - scope is intentionally narrow:
- No cluster layout management. Assigning nodes, zones, and capacity is not
managed by this provider; it's a one-shot bootstrap operation that doesn't fit
cleanly into idempotent IaC. Bootstrap your Garage cluster yourself (e.g.
garage layout assign/apply, or--single-nodeon Garage v2.3.0+) before pointing this provider at it. Bucketsupports only a single global alias. No local (per-key) aliases, no multiple global aliases.Key's globalcreateBucketpermission is not modelled, deliberately - it wasn't reliable enough to model without further verification against a live API.- Deleting a non-empty
Bucketfails. This mirrors Garage's (and S3's) own native behavior; it's by design, not a bug. - Only YAML and Go example programs are exercised in CI/E2E. The nodejs, python, and dotnet SDKs are generated and published (see Installing) but aren't covered by this repo's example programs or lifecycle tests.
- No Java/Maven SDK. Pulumi's Java support has too little adoption to justify the extra setup cost (Sonatype namespace verification, GPG-signed releases); the nodejs, python, dotnet, and go SDKs cover the ecosystem's actual usage.
Reference
This provider isn't (yet) listed on the Pulumi Registry,
so there's no pulumi.com/registry/packages/garage page to link to for generated,
per-resource API docs. Until then:
- The Go SDK reference on pkg.go.dev is generated from the same schema descriptions the Pulumi Registry would render, and is the most complete field-by-field reference available (populated after the first tagged release - see RELEASING.md).
- The
QuickstartandConfigurationsections above cover the three resources and provider config end to end; the underlying schema isprovider/cmd/pulumi-resource-garage/schema.json(generated, not hand-maintained).
Contributing
See CONTRIBUTING.md for building the provider, the test layers (including how to run the E2E suite locally), generating the SDKs, and the devcontainer setup. See also our Code of Conduct.
License
Metadata
Release files for pulumi-garage 1.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pulumi_garage-1.1.2.tar.gz | 20.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pulumi_garage-1.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.7 kB
Release files / pulumi_garage-1.1.2.tar.gz
| Download URL | pulumi_garage-1.1.2.tar.gz |
|---|---|
| Size | 20.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
603788ead9102fb1c71d4c7ca1fc91b47325134a988296c0bca8f996c90085dc
|
|
BLAKE2b-256 checksum How to use checksums |
f958165899aa15c1306a367fa5099e46fca0d392c9bab20ad08248c474603c8f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / pulumi_garage-1.1.2-py3-none-any.whl
| Download URL | pulumi_garage-1.1.2-py3-none-any.whl |
|---|---|
| Size | 24.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7759cfc36f9ca5b4fd77911a9193f046957ddaace5867a2a88f534e9bd3a2151
|
|
BLAKE2b-256 checksum How to use checksums |
fb94837bdc9d99103ed3720345e795b3dd2b0e6765e69c90d2a207cb11719917
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|