From 69d3219b333d952fabf62e547f990169dc40cc0c Mon Sep 17 00:00:00 2001 From: Logan Omelchuk <72324766+hamsandvich@users.noreply.github.com> Date: Mon, 2 Mar 2026 16:58:26 -0700 Subject: [PATCH 1/5] Add wrangler.toml for Cloudflare Worker Add a new wrangler.toml to configure the Cloudflare Worker for the git-lfs-s3-proxy project. Defines the worker name, main entry (_worker.js), and the compatibility_date (2026-03-02). --- wrangler.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 wrangler.toml diff --git a/wrangler.toml b/wrangler.toml new file mode 100644 index 0000000..f236cbd --- /dev/null +++ b/wrangler.toml @@ -0,0 +1,3 @@ +name = "git-lfs-s3-proxy" +main = "./_worker.js" +compatibility_date = "2026-03-02" From 241d0d64f052474373280360932ac24b6beaf74f Mon Sep 17 00:00:00 2001 From: Logan Omelchuk <72324766+hamsandvich@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:14:00 -0600 Subject: [PATCH 2/5] Set Worker CPU limit in wrangler.toml Add a [limits] section to wrangler.toml with cpu_ms = 300_000 to raise the Cloudflare Worker CPU allowance (300s). This accommodates longer-running operations for the git-lfs-s3-proxy worker. --- wrangler.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrangler.toml b/wrangler.toml index f236cbd..492bbf7 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,3 +1,6 @@ name = "git-lfs-s3-proxy" main = "./_worker.js" compatibility_date = "2026-03-02" + +[limits] +cpu_ms = 300_000 \ No newline at end of file From 13d6378b2f4fd65b49c36db5920f44f6e4e05620 Mon Sep 17 00:00:00 2001 From: Logan Omelchuk <72324766+hamsandvich@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:28:26 -0600 Subject: [PATCH 3/5] Remove cpu_ms limit and document Free plan caveat Remove the [limits] cpu_ms setting from wrangler.toml to avoid deployment failures for Cloudflare Pages Free accounts. Add a README note explaining that the checked-in wrangler.toml intentionally omits limits.cpu_ms because custom CPU limits are only supported on paid Workers plans, and that adding such a limit will break deployments from Free plan accounts. --- README.md | 2 +- wrangler.toml | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index 4d54cd0..6f851ad 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ To host your own instance of the proxy: - Add your GitHub account to Pages. - Grant access to your fork of `twilligon/git-lfs-s3-proxy`. - Set up your Pages site: set **Build command** to `npm install` and leave all other settings on their defaults. + - The checked-in `wrangler.toml` intentionally does not set `limits.cpu_ms`, because Cloudflare only supports custom CPU limits on paid Workers plans. If you later add `[limits] cpu_ms = ...`, deployments from a Free plan account will fail. - If you own a domain name (e.g. `example.com`), you can [add a CNAME record](https://developers.cloudflare.com/pages/platform/custom-domains/#add-a-custom-cname-record) to point a subdomain (e.g. `git-lfs-s3-proxy.example.com`) at your instance. If you don't own a domain, a `pages.dev` subdomain will work just as well, except you'll have to change your LFS server URL if you ever stop using the proxy. ### Find your LFS server URL @@ -181,4 +182,3 @@ Hopefully `aws4fetch` merges the [fix](https://github.com/mhart/aws4fetch/pull/7 For example, with a Linode bucket `my-repo` in `us-east-1` region with access key ID `foo` and secret access key `bar` via the default instance: https://foo:bar@git-lfs-s3-proxy.pages.dev/service=s3/us-east-1.linodeobjects.com/my-repo - diff --git a/wrangler.toml b/wrangler.toml index 492bbf7..f236cbd 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,6 +1,3 @@ name = "git-lfs-s3-proxy" main = "./_worker.js" compatibility_date = "2026-03-02" - -[limits] -cpu_ms = 300_000 \ No newline at end of file From 7e3091dc5161766ee66ccdf27994d772a9f1a10b Mon Sep 17 00:00:00 2001 From: Logan Omelchuk <72324766+hamsandvich@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:31:41 -0600 Subject: [PATCH 4/5] Update wrangler.toml --- wrangler.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wrangler.toml b/wrangler.toml index f236cbd..492bbf7 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,3 +1,6 @@ name = "git-lfs-s3-proxy" main = "./_worker.js" compatibility_date = "2026-03-02" + +[limits] +cpu_ms = 300_000 \ No newline at end of file From cade976b40f7befb29107a1d00d2794fabfd58e0 Mon Sep 17 00:00:00 2001 From: Logan Omelchuk <72324766+hamsandvich@users.noreply.github.com> Date: Wed, 15 Apr 2026 22:44:21 -0600 Subject: [PATCH 5/5] Configurable presigned expiry; observability Allow configuring S3 presigned URL lifetime via an EXPIRY Worker env var and clamp it to R2's 7-day max. _worker.js: add parseExpiry to validate and cap expiry, pass expiry into sign(), and use the parsed env.EXPIRY for generated actions so large/slow LFS pushes can increase the URL lifetime. README.md: document the EXPIRY environment variable and give a 24-hour example. wrangler.toml: add observability/logs/traces configuration entries (sampling, persistence, invocation logs) to enable platform telemetry. --- README.md | 1 + _worker.js | 19 ++++++++++++++----- wrangler.toml | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 6f851ad..9f9ff32 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ To host your own instance of the proxy: - Grant access to your fork of `twilligon/git-lfs-s3-proxy`. - Set up your Pages site: set **Build command** to `npm install` and leave all other settings on their defaults. - The checked-in `wrangler.toml` intentionally does not set `limits.cpu_ms`, because Cloudflare only supports custom CPU limits on paid Workers plans. If you later add `[limits] cpu_ms = ...`, deployments from a Free plan account will fail. + - For slow or very large LFS pushes, you can set a Worker environment variable named `EXPIRY` to increase the presigned URL lifetime in seconds. For example, `86400` keeps each upload URL valid for 24 hours instead of the default 3600 seconds. - If you own a domain name (e.g. `example.com`), you can [add a CNAME record](https://developers.cloudflare.com/pages/platform/custom-domains/#add-a-custom-cname-record) to point a subdomain (e.g. `git-lfs-s3-proxy.example.com`) at your instance. If you don't own a domain, a `pages.dev` subdomain will work just as well, except you'll have to change your LFS server URL if you ever stop using the proxy. ### Find your LFS server URL diff --git a/_worker.js b/_worker.js index 0c50acd..d883f15 100644 --- a/_worker.js +++ b/_worker.js @@ -10,10 +10,20 @@ const METHOD_FOR = { download: "GET", }; -async function sign(s3, bucket, path, method) { +function parseExpiry(value) { + const expiry = Number.parseInt(value, 10); + if (!Number.isFinite(expiry) || expiry < 1) { + return EXPIRY; + } + + // R2 presigned URLs support expiries up to 7 days. + return Math.min(expiry, 604800); +} + +async function sign(s3, bucket, path, method, expiry) { const info = { method }; const signed = await s3.sign( - new Request(`https://${bucket}/${path}?X-Amz-Expires=${EXPIRY}`, info), + new Request(`https://${bucket}/${path}?X-Amz-Expires=${expiry}`, info), { aws: { signQuery: true } }, ); return signed.url; @@ -69,7 +79,6 @@ async function fetch(req, env) { let s3Options = { accessKeyId: user, secretAccessKey: pass }; const segments = url.pathname.split("/").slice(1, -2); - let params = {}; let bucketIdx = 0; for (const segment of segments) { const sliceIdx = segment.indexOf("="); @@ -86,7 +95,7 @@ async function fetch(req, env) { const s3 = new AwsClient(s3Options); const bucket = segments.slice(bucketIdx).join("/"); - const expires_in = params.expiry || env.EXPIRY || EXPIRY; + const expires_in = parseExpiry(env.EXPIRY); const { objects, operation, hash_algo = "sha256" } = await req.json(); @@ -113,7 +122,7 @@ async function fetch(req, env) { authenticated: true, actions: { [operation]: { - href: await sign(s3, bucket, oid, method), + href: await sign(s3, bucket, oid, method, expires_in), expires_in, }, }, diff --git a/wrangler.toml b/wrangler.toml index 492bbf7..f557e40 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -3,4 +3,19 @@ main = "./_worker.js" compatibility_date = "2026-03-02" [limits] -cpu_ms = 300_000 \ No newline at end of file +cpu_ms = 300_000 + +[observability] +enabled = false +head_sampling_rate = 1 + +[observability.logs] +enabled = true +head_sampling_rate = 1 +persist = true +invocation_logs = true + +[observability.traces] +enabled = false +persist = true +head_sampling_rate = 1 \ No newline at end of file