AWS S3 + DynamoDB storage plugin for Verdaccio.
Uses S3 for package tarballs and metadata, and DynamoDB for the registry database (package list, secrets, tokens).
Built with AWS SDK for JavaScript v3.
- Node.js >= 24
- Verdaccio >= 7.x
- AWS S3 Bucket β stores package tarballs and
package.jsonmetadata - AWS DynamoDB Table β stores the registry state (package list, secret, auth tokens)
- Partition key:
pk(String) - Sort key:
sk(String) - Billing mode: PAY_PER_REQUEST (recommended) or provisioned
- Partition key:
- AWS Credentials β via environment variables, IAM role, instance profile, or explicit config
The plugin requires the following IAM permissions:
S3:
s3:GetObjects3:PutObjects3:DeleteObjects3:DeleteObjects(for bulk deletes)s3:ListBucket/s3:ListObjectsV2s3:HeadObject
DynamoDB:
dynamodb:GetItemdynamodb:PutItemdynamodb:DeleteItemdynamodb:Query
npm install verdaccio-aws-s3-storageAdd to your Verdaccio config.yaml:
store:
aws-s3-storage:
bucket: your-s3-bucket
keyPrefix: some-prefix # optional, nests all files under a subdirectory
region: us-east-1 # optional, defaults to AWS SDK default
endpoint: https://s3.us-east-1.amazonaws.com # optional
s3ForcePathStyle: false # optional, required for MinIO/LocalStack
tarballACL: private # optional, use 'public-read' for CDN (e.g. CloudFront)
accessKeyId: your-key # optional, uses AWS credential chain if omitted
secretAccessKey: your-secret # optional
sessionToken: your-token # optional
proxy: https://your-proxy # optional
# DynamoDB (required)
dynamoTableName: verdaccio-registry
dynamoEndpoint: https://dynamodb.us-east-1.amazonaws.com # optional
dynamoRegion: us-east-1 # optional, defaults to 'region'Config values can reference environment variables by name. If the environment variable is set, its value is used; otherwise the literal string is used as-is.
store:
aws-s3-storage:
bucket: AWS_S3_BUCKET # uses $AWS_S3_BUCKET if set, otherwise literal "AWS_S3_BUCKET"
keyPrefix: AWS_S3_KEY_PREFIX
region: AWS_DEFAULT_REGION
endpoint: AWS_S3_ENDPOINT
accessKeyId: AWS_ACCESS_KEY_ID
secretAccessKey: AWS_SECRET_ACCESS_KEY
sessionToken: AWS_SESSION_TOKEN
dynamoTableName: AWS_DYNAMO_TABLE_NAME
dynamoEndpoint: AWS_DYNAMO_ENDPOINT
dynamoRegion: AWS_DYNAMO_REGIONThe following environment variables are used by the Docker image and the plugin when config values reference them:
| Variable | Required | Description |
|---|---|---|
AWS_S3_BUCKET |
Yes | S3 bucket name for storing packages |
AWS_S3_KEY_PREFIX |
No | Prefix (subdirectory) for all S3 keys. Default: none |
AWS_S3_ENDPOINT |
No | Custom S3 endpoint URL. Required for LocalStack or MinIO. Omit for real AWS |
AWS_DEFAULT_REGION |
No | AWS region for S3 and DynamoDB (if AWS_DYNAMO_REGION is not set). Default: SDK default |
| Variable | Required | Description |
|---|---|---|
AWS_DYNAMO_TABLE_NAME |
Yes | DynamoDB table name (must have pk/sk key schema) |
AWS_DYNAMO_ENDPOINT |
No | Custom DynamoDB endpoint URL. Required for LocalStack. Omit for real AWS |
AWS_DYNAMO_REGION |
No | AWS region for DynamoDB. Falls back to AWS_DEFAULT_REGION |
| Variable | Required | Description |
|---|---|---|
AWS_ACCESS_KEY_ID |
No | AWS access key. Omit to use IAM roles, instance profiles, or IRSA |
AWS_SECRET_ACCESS_KEY |
No | AWS secret key. Required if AWS_ACCESS_KEY_ID is set |
AWS_SESSION_TOKEN |
No | AWS session token for temporary credentials (STS) |
| Variable | Required | Description |
|---|---|---|
DEBUG |
No | Enable debug output. Set to verdaccio:plugin* for all plugin namespaces |
Available debug namespaces:
verdaccio:plugin:aws-s3-storage:databaseβ DynamoDB operations (add, remove, get, tokens, secret)verdaccio:plugin:aws-s3-storage:packageβ S3 package operations (read, write, create, delete, tarballs)verdaccio:plugin:aws-s3-storage:s3-clientβ S3 client initializationverdaccio:plugin:aws-s3-storage:dynamo-clientβ DynamoDB client initializationverdaccio:plugin:aws-s3-storage:delete-prefixβ S3 prefix deletionverdaccio:plugin:aws-s3-storage:errorsβ AWS error conversionverdaccio:plugin:aws-s3-storage:configβ config value resolution from env vars
packages:
'@scope/*':
access: $all
publish: $all
storage: 'scoped' # stored under keyPrefix/scoped/@scope/pkg/
'**':
access: $all
publish: $all
proxy: npmjs
storage: 'public'Set tarballACL: public-read to grant anonymous read access for CDN integration (e.g. Amazon CloudFront).
+-----------+
| Verdaccio |
+-----+-----+
|
+------------+------------+
| |
S3Database S3PackageManager
(registry state) (per-package storage)
| |
DynamoDB S3
+-----------------+ +------------------+
| pk=CONFIG | | pkg/package.json |
| pk=PACKAGE | | pkg/tarball.tgz |
| pk=TOKEN#user | +------------------+
+-----------------+
S3Database handles registry operations via DynamoDB:
- Package list (
add,remove,get) - Secret management (
getSecret,setSecret) - Auth tokens (
saveToken,deleteToken,readTokens)
S3PackageManager handles per-package operations via S3:
- Package metadata (
readPackage,savePackage,createPackage,deletePackage) - Tarballs (
readTarball,writeTarball)
Single-table design with partition key pk and sort key sk:
| pk | sk | Description |
|---|---|---|
CONFIG |
SECRET |
Registry secret key |
PACKAGE |
{packageName} |
Package entry |
TOKEN#{user} |
{tokenKey} |
Auth token |
See LOCAL_DEV.md for the full local development guide, including:
- Setup, build, test, and lint commands
- Running Verdaccio + LocalStack via Docker Compose
- Inspecting S3 and DynamoDB data in LocalStack
- Debug logging namespaces
- Helm + LocalStack example for Kubernetes
aws dynamodb create-table \
--table-name verdaccio-registry \
--attribute-definitions \
AttributeName=pk,AttributeType=S \
AttributeName=sk,AttributeType=S \
--key-schema \
AttributeName=pk,KeyType=HASH \
AttributeName=sk,KeyType=RANGE \
--billing-mode PAY_PER_REQUESTresource "aws_dynamodb_table" "verdaccio" {
name = "verdaccio-registry"
billing_mode = "PAY_PER_REQUEST"
hash_key = "pk"
range_key = "sk"
attribute {
name = "pk"
type = "S"
}
attribute {
name = "sk"
type = "S"
}
}Resources:
VerdaccioTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: verdaccio-registry
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: pk
AttributeType: S
- AttributeName: sk
AttributeType: S
KeySchema:
- AttributeName: pk
KeyType: HASH
- AttributeName: sk
KeyType: RANGEThe plugin is fully stateless and supports horizontal scaling. Run multiple Verdaccio instances behind a load balancer β all instances share the same S3 bucket and DynamoDB table.
- Scaling guide β architecture, concurrency safety, ECS/Fargate, Kubernetes, monitoring, cost estimation
- Helm example β deploy on Kubernetes using the official Verdaccio Helm chart with IRSA support
MIT