S3 / RustFS / MinIO / R2
Driver: s3
This storage driver stores the cache in a S3 compatible storage, e.g. AWS S3 or RustFS.
Configuration
docker-compose RustFS example
version: '3.9'
services:
cache-server:
image: ghcr.io/falcondev-oss/github-actions-cache-server:latest
ports:
- '3000:3000'
environment:
API_BASE_URL: http://localhost:3000
STORAGE_DRIVER: s3
STORAGE_S3_BUCKET: gh-actions-cache
AWS_ACCESS_KEY_ID: access_key
AWS_SECRET_ACCESS_KEY: secret_key
AWS_ENDPOINT_URL: http://rustfs:9000
volumes:
- cache-data:/app/.data
rustfs:
image: rustfs/rustfs:latest
ports:
- '9000:9000'
- '9001:9001'
environment:
RUSTFS_ACCESS_KEY: access_key
RUSTFS_SECRET_KEY: secret_key
volumes:
- rustfs-data:/data
volumes:
cache-data:
rustfs-data:docker-compose AWS S3 example
This example assumes that credentials are being provided by the environment, e.g. via an instance profile or EKS IRSA.
version: '3.9'
services:
cache-server:
image: ghcr.io/falcondev-oss/github-actions-cache-server:latest
ports:
- '3000:3000'
environment:
API_BASE_URL: http://localhost:3000
STORAGE_DRIVER: s3
STORAGE_S3_BUCKET: gh-actions-cache
volumes:
- cache-data:/app/.data
volumes:
cache-data:Environment Variables
The only required S3-related environment variables are STORAGE_DRIVER: s3 and STORAGE_S3_BUCKET. The rest of the environment variables are optional and depend on your S3-compatible storage provider.
The server picks up AWS credentials from the environment: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (with AWS_SESSION_TOKEN), a web identity token (EKS IRSA), ECS task credentials or EC2 instance metadata. Outside of AWS, the access key variables authenticate with S3-compatible storage, as seen in the RustFS example above. Shared credential files and AWS_PROFILE are not supported.
Common environment variables are listed below. For a full list, see AmazonS3Builder::from_env.
STORAGE_S3_BUCKET
Example: gh-actions-cache
The name of the S3 bucket used for storage. This environment variable is always required.
AWS_REGION
Example: us-east-1
Defaults to us-east-1. This has no effect if you are using a non-AWS S3-compatible storage provider, such as RustFS.
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
Example: AWS_ACCESS_KEY_ID: access_keyAWS_SECRET_ACCESS_KEY: secret_key
This is the access key/secret key used to authenticate with S3-compatible storage. If required to authenticate with your provider, these should be provided by the provider.
AWS_ENDPOINT_URL
Example: http://rustfs:9000
This is the endpoint URL for the S3-compatible storage. This is only required if you are using a non-AWS S3-compatible storage provider, such as RustFS.
STORAGE_S3_SOCKET_TIMEOUT_MS
- Default:
10000
How long a request to S3 may go without making progress before it fails. 0 disables it.
Minimal IAM permissions
The cache server only ever touches objects under the gh-actions-cache/ prefix in the bucket. These are all the actions it performs:
| Action | Used for |
|---|---|
s3:ListBucket | Startup bucket check, listing/counting cache objects |
s3:GetObject | Downloading cache entries, existence checks |
s3:PutObject | Uploading cache entries, merging parts |
s3:AbortMultipartUpload | Cleaning up failed multipart uploads |
s3:DeleteObject | Cache cleanup and abandoned uploads |
A minimal policy, scoped to the bucket and prefix (replace YOUR_BUCKET):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "github-actions-cache-server-bucket",
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::YOUR_BUCKET"
},
{
"Sid": "github-actions-cache-server-objects",
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:AbortMultipartUpload", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::YOUR_BUCKET/gh-actions-cache/*"
}
]
}Parts are uploaded through presigned URLs, which the server signs with its own credentials. If they can't sign, uploads fall back to multipart.
Incomplete multipart uploads
A server killed mid-upload or mid-merge leaves an incomplete multipart upload that S3 keeps and bills. Add a lifecycle rule that aborts them:
{
"Rules": [
{
"ID": "abort-incomplete-uploads",
"Status": "Enabled",
"Filter": { "Prefix": "gh-actions-cache/" },
"AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 1 }
}
]
}