Skip to main content

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

Project description

rink

Rink uploads any file or folder from your terminal directly to a Cloudflare R2 bucket and gives you a link!

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

From PyPI:

uv tool install rink     # install as a CLI on your PATH (recommended)
uv pip install rink      # or into the active environment
pip install rink         # or with plain pip

From source (for development):

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

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 1d      # 1-day presigned link (30m, 2h, 7d, 1h30m…)
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 <dur> config default_expiry presigned lifetime: 30m, 2h, 7d, 1h30m, or bare seconds (max 7d)
--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.2.tar.gz (11.9 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.2-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for rink-0.1.2.tar.gz
Algorithm Hash digest
SHA256 43e6abe4a4d87e16512d9896e6474d59c2d693058f797d98ee010b90edd06ece
MD5 f563706cd6f51b96b8a49dd48477a819
BLAKE2b-256 dc32263d827f1b6407a4a868ee55527cf953afdca7efe0ba72de9cc497c25a84

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for rink-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5f833ccd34f752de1d21a2c4eb1849c59d311beb9fea0bd464e2f9dbb160471d
MD5 fa74b74da863e05d3028ec7bb79e2811
BLAKE2b-256 cc17c990013766524805c6545c02acb96641bcc8cee71a08796121956b6c9f14

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