Use case
Backups from CI
A nightly archive to your bucket from a workflow, with secrets from the runner and no file to check in.
- run: tar cz ./data | npx @s3nd/cli put - --name backup.tar.gz --expires-in never
env:
S3ND_BUCKET: transfers
S3ND_PREFIX: backups
S3ND_ENDPOINT: https://${{ secrets.R2_ACCOUNT_ID }}.r2.cloudflarestorage.com
S3ND_REGION: auto
AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}The situation
What is actually going on.
The problem
A workflow produces something worth keeping: a database dump, a build, a generated report. It needs to land in your bucket every night, without a config file in the repository and without a client library in the workflow.
What s3nd does about it
npx @s3nd/cli put, with the bucket and credentials in environment variables from the runner’s secret store. Two flags turn a transfer into a backup: --expires-in never, and a prefix of its own so the lifecycle rule on transfers cannot reach it.
Worth watching
The things that are easy to get wrong.
--json for the logs
Machine-readable output, and s3nd doctor --json exits non-zero when a check fails, so it doubles as a deployment smoke test.
A prefix per policy
Transfers expire, backups do not. Keeping them under different prefixes is what lets one bucket hold both.
Related
Other shapes of the same primitive.
Put a file. Hand over the code.
Point it at the bucket you already pay for. Nothing to deploy, nothing to sign up for, nothing in the middle.
npm install -g @s3nd/clis3nd init --provider r2 --bucket drops3nd put ./anything.zip