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
- Account ID — Cloudflare dashboard → R2 → copy the Account ID.
- Create a bucket — dashboard → R2 → Create bucket, or
wrangler r2 bucket create <name>. - API token — dashboard → R2 → Manage R2 API Tokens → Create API Token with Object Read & Write. Copy the Access Key ID and Secret Access Key.
- (public links only) bucket → Settings → enable Public Development URL, and
copy the
pub-xxxx.r2.devdomain.
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 linkpermanent— shared via a public link (never expires)untracked— object exists in the bucket but wasn't uploaded byrink, 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43e6abe4a4d87e16512d9896e6474d59c2d693058f797d98ee010b90edd06ece
|
|
| MD5 |
f563706cd6f51b96b8a49dd48477a819
|
|
| BLAKE2b-256 |
dc32263d827f1b6407a4a868ee55527cf953afdca7efe0ba72de9cc497c25a84
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f833ccd34f752de1d21a2c4eb1849c59d311beb9fea0bd464e2f9dbb160471d
|
|
| MD5 |
fa74b74da863e05d3028ec7bb79e2811
|
|
| BLAKE2b-256 |
cc17c990013766524805c6545c02acb96641bcc8cee71a08796121956b6c9f14
|