Skip to main content

Upload files/folders to Cloudflare R2 and get a shareable link

Project description

rink

A small CLI that uploads a file or folder to a Cloudflare R2 bucket and prints a shareable link. R2 is S3-compatible, so rink talks to it with boto3.

R2 objects are private by default, so rink gives you two kinds of link:

  • Presigned (default) — a signed, self-expiring URL (up to 7 days). No bucket config needed.
  • Public — a permanent https://pub-xxxx.r2.dev/<key> (or custom-domain) URL, available after you enable public access on the bucket.

One-time Cloudflare setup

  1. Account ID — Cloudflare dashboard → R2 → copy the Account ID.
  2. Create a bucket — dashboard → R2 → Create bucket, or wrangler r2 bucket create <name>.
  3. API token — dashboard → R2 → Manage R2 API TokensCreate API Token with Object Read & Write. Copy the Access Key ID and Secret Access Key.
  4. (public links only) bucket → Settings → enable Public Development URL, and copy the pub-xxxx.r2.dev domain.

Install

uv sync                 # install deps into the project venv
uv run rink --help      # run from the project
# or install as a tool on your PATH:
uv tool install .

Configure

rink config             # interactive wizard

Writes ~/.config/rink/config.toml (mode 600). Every field can also be supplied via environment variables, which override the file: RINK_ACCOUNT_ID, RINK_ACCESS_KEY_ID, RINK_SECRET_ACCESS_KEY, RINK_BUCKET, RINK_PUBLIC_BASE_URL.

Buckets

rink buckets            # list all buckets in the account (default is marked ●)
rink use                # interactive picker to choose the default bucket
rink use my-bucket      # set the default bucket directly

rink up --bucket <name> still overrides the bucket for a single upload without changing the default.

Usage

rink up ./report.pdf                  # presigned link (default expiry)
rink up ./report.pdf --expiry 86400   # 1-day presigned link
rink up ./report.pdf --public         # permanent public link
rink up ./mydir                       # zip the folder, one link (default)
rink up ./mydir --recursive           # upload each file, one link per file
rink up ./big.bin --prefix backups/   # store under a key prefix
rink up ./f.txt --bucket other-bucket # override the configured bucket

Options:

flag default meaning
--public / --presigned --presigned link type
--expiry <sec> config default_expiry presigned lifetime (≤ 604800)
--zip / --recursive --zip folder handling
--prefix <str> none key prefix in the bucket
--bucket <name> configured bucket override target bucket

Large files (≥ 8 MiB) upload via multipart automatically with a progress bar. The URL(s) are printed on their own line(s) so they're easy to copy or pipe.

Listing, expiry, and deleting

rink ls                 # list objects in the bucket with each link's time-left
rink ls backups/        # only keys under a prefix
rink ls --expired       # only entries whose presigned link has already expired
rink rm myfile.zip      # delete an object (this is how you revoke access)
rink rm a.txt b.txt -y  # delete several, skip the confirmation

rink ls reads the live bucket and joins it with a local log to show the link column:

  • 2h / 1d 3h — time left on the presigned link
  • permanent — shared via a public link (never expires)
  • untracked — object exists in the bucket but wasn't uploaded by rink, so we don't know its link expiry

Why a local log? R2 stores files, not links. A presigned URL's expiry is baked into the URL string at generation time — R2 keeps no record of it. So rink logs each upload to a small SQLite database at ~/.local/share/rink/rink.db (stdlib, no extra deps) to report time-left. Deleting with rink rm removes both the object and its log row.

Note: the file itself never expires — only the share link does. To make a file unreachable, delete it with rink rm. (R2 has no per-object private/public switch; publicity is bucket-wide, so deletion is the way to revoke.)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rink-0.1.0.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rink-0.1.0-py3-none-any.whl (14.0 kB view details)

Uploaded Python 3

File details

Details for the file rink-0.1.0.tar.gz.

File metadata

  • Download URL: rink-0.1.0.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for rink-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f43d30566052a5b5be8f9a0807cda8e5f842412315b2c9c36fd8466698ab2539
MD5 1b697351ab662aa68a590a6366fe5e3e
BLAKE2b-256 f6ab59285eb3ee1df597b02b2942de345a3fed11b3b57775b79d90d68a5e9200

See more details on using hashes here.

File details

Details for the file rink-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: rink-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for rink-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b77fab6807ba974a2d00808fb61bc663c730b5d5d9389b17ff771bd51814527
MD5 c4f6fc491dda66b2809e8ffcfed0ad89
BLAKE2b-256 a3923c324f8a299794e55501e590e4692e9b311628f487b642dded09ab53142e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page