{"slug": "dumbforge-host-your-git-repo-from-an-s3-bucket-for-free", "title": "Dumbforge: Host your Git repo from an S3 bucket for free", "summary": "A developer released Dumbforge, a tool that lets users host Git repositories on an S3 bucket and browse them through a GitHub-like static UI without running a server or forge daemon. The project, created by the developer known as superdisk, uses Git's dumb HTTP protocol and Cloudflare R2 for free storage up to 10 GB, aiming to provide a decentralized alternative to GitHub that is fast and easy to set up.", "body_md": "# dumbforge\n\n**the following text is not LLM generated**\n\nWell, everyone's [been talking about GitHub alternatives](https://mitchellh.com/writing/ghostty-leaving-github) lately. I'm pretty sympathetic to that on an ideological level (and just the fundamental problem of it being down all the time), but historically the alternatives kind of suck, and I think still miss the point of Git being decentralized in the first place. [Gitea](https://gitea.com/)/[Forgejo](https://forgejo.org/) are cool, but require you to set up a server and configure it. Even though it's pretty easy, it's still annoying and requires you to pay for and babysit a VPS or whatever to run the forge program. [Codeberg](https://codeberg.org/) has been a platform of choice for freedom-heads to get away from GitHub, but they recently instituted a no-crypto and no-LLM rule. I respect what they're doing, but I'm pretty AI-pilled so that's not going to work for me.\n\nIt occurred to me that you don't actually need to run a forge or git daemon at all, since Git supports cloning via the so-called [\"dumb\" HTTP protocol](https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols). You could theoretically just throw your git repo into an s3 bucket, and it would be clone-able, no daemon or VPS required. So that's cool, and even more decentralized; but the problem with self-hosting git like that, is that then you don't have the nice landing page, file browser, commit log, etc etc. It's small, but it makes a big difference to have a GitHubby UI for each project. [SourceHut](https://sourcehut.org/) and [Savannah](https://savannah.gnu.org/) struggle with this I think, since they're pretty alien to normies.\n\nSo I slopped `dumbforge`\n\ntogether as a proof of concept; it's a git remote helper that also functions as a static-site-generator-like-thing, which pushes directly to an s3 bucket, and generates a GitHub-like UI. So you get some really nice advantages:\n\n- It's super fast to browse, since it's just static HTML. GitLab and GitHub itself are really slow clunky beasts.\n- You don't need to administer a git daemon or forge server.\n- It's free if you're storing less than 10 gigs, using CloudFlare R2.\n- You're decentralized, bro! Well, mostly.\n\nI'll grant that the implementation could most certainly use some improvement but this is mostly just to show off the idea. I hope it piques your curiosity. 🤔\n\nIf you want to see one of my actual repos presented by `dumbforge`\n\n, [check here.](https://dumbforge.dev/hUGETracker.git)\n\n**the following text is LLM generated**\n\n## Install\n\n```\nnpm install --global @superdisk/dumbforge\n```\n\nGit itself must also be installed. The implementation deliberately asks Git to create packfiles instead of reimplementing its storage format.\n\n## Configure an R2 remote\n\nAn R2 remote has two addresses:\n\n- the\n**S3 API endpoint**, which dumbforge uses to push with your credentials; - a\n**public URL**, which browsers and ordinary Git use without credentials.\n\nThe S3 API endpoint is not the public URL. It normally looks like\n`https://ACCOUNT_ID.r2.cloudflarestorage.com`\n\n. The public URL is either an\n`r2.dev`\n\ndevelopment URL or a custom domain such as `https://git.example.com`\n\n.\n\n### 1. Create a bucket and make it public\n\nIn the Cloudflare dashboard, open **Storage & databases → R2**, create a bucket,\nand open its **Settings** page. Give it either a Public Development URL or a\ncustom domain. A custom domain is preferable for anything you intend to keep;\nthe `r2.dev`\n\nURL is fine for testing.\n\nYou do not need to configure CORS. You should now have these three values:\n\n```\nBucket:       my-bucket\nS3 endpoint:  https://ACCOUNT_ID.r2.cloudflarestorage.com\nPublic URL:   https://git.example.com\n```\n\n### 2. Create credentials for dumbforge\n\nFrom the R2 overview, select **Manage R2 API tokens → Create API token**. Give\nthe token **Object Read & Write** access and scope it to the new bucket. When\nCloudflare creates it, copy the **Access Key ID** and **Secret Access Key**. The\nsecret is only shown once.\n\nThese are S3 credentials, not your normal Cloudflare API bearer token. You do not need an AWS account. R2 implements the S3 protocol, and dumbforge directs the S3 client to Cloudflare's endpoint.\n\nThe easiest way to save the credentials is with the AWS CLI:\n\n```\naws configure --profile my-r2\n```\n\nAnswer its prompts like this:\n\n```\nAWS Access Key ID:     <the R2 Access Key ID>\nAWS Secret Access Key: <the R2 Secret Access Key>\nDefault region name:   auto\nDefault output format: <press Enter>\n```\n\n`aws configure`\n\nonly writes a standard local credentials file. It does not\ncontact AWS or copy anything there. You can confirm that the profile can reach\nyour bucket before involving Git:\n\n```\naws s3api list-objects-v2 \\\n  --profile my-r2 \\\n  --bucket my-bucket \\\n  --endpoint-url https://ACCOUNT_ID.r2.cloudflarestorage.com \\\n  --max-items 1\n```\n\nAn empty bucket may return no objects, which is fine. An `AccessDenied`\n\nerror\nusually means the token was scoped to a different bucket or was not given\nObject Read & Write access.\n\nIf you do not want to install the AWS CLI, export the standard\n`AWS_ACCESS_KEY_ID`\n\n, `AWS_SECRET_ACCESS_KEY`\n\n, and `AWS_REGION=auto`\n\nenvironment\nvariables instead. Omit `--profile`\n\nfrom the next command in that case, and\nmake sure those variables are present in every shell from which you push.\n\n### 3. Add the Git remote\n\nRun this inside the local Git repository you want to publish:\n\n```\ndumbforge remote add forge \\\n  --bucket my-bucket \\\n  --prefix projects/example.git \\\n  --endpoint https://ACCOUNT_ID.r2.cloudflarestorage.com \\\n  --profile my-r2 \\\n  --public-url https://git.example.com\n```\n\n`forge`\n\nis merely the local name of the Git remote; choose another name if you\nprefer. Using `forge`\n\nalso leaves an existing `origin`\n\nremote alone.\n\nThe prefix is where this repository lives inside the bucket. It should normally\nend in `.git`\n\n. You can host multiple repositories in one bucket by giving each\none a different prefix. Pass only the base domain to `--public-url`\n\n; dumbforge\nappends the prefix itself.\n\nThe command configures separate fetch and push URLs:\n\n- fetch:\n`https://git.example.com/projects/example.git`\n\n; - push: a\n`dumbforge://`\n\nURL containing the bucket, endpoint, and profile.\n\nCheck them with:\n\n```\ngit remote -v\n```\n\n### 4. Push\n\nPush the repository's current branch. Most new repositories call it `main`\n\n:\n\n```\ngit push --set-upstream forge main\n```\n\nIf your branch has another name, replace `main`\n\nwith the output of\n`git branch --show-current`\n\n. The first push publishes the complete Git history\nand builds the initial website. Later pushes upload only new Git objects and use\nthe old and new commits to rebuild changed files and affected shared pages.\n\nOpen the repository URL in a browser:\n\n```\nhttps://git.example.com/projects/example.git\n```\n\nAnyone can clone that same URL with ordinary Git. They do not need dumbforge, an R2 account, or your credentials:\n\n```\ngit clone https://git.example.com/projects/example.git\n```\n\nThe repository browser is served from that exact URL. Git appends\n`/info/refs`\n\n; browsers receive the HTML object stored at the repository prefix.\n\nIf Git reports that `remote-dumbforge`\n\nis not a Git command, the npm global bin\ndirectory is not on your `PATH`\n\n. `command -v git-remote-dumbforge`\n\nshould print\nthe installed helper's path before you push.\n\n## License\n\ndumbforge is licensed under the GNU Affero General Public License v3.0 only.\nSee [LICENSE](LICENSE). Third-party notices and license texts are included in\n[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).\n\n## Development\n\n```\ngo test ./...\ngo build ./cmd/dumbforge\n```\n\n", "url": "https://wpnews.pro/news/dumbforge-host-your-git-repo-from-an-s3-bucket-for-free", "canonical_source": "https://dumbforge.dev/dumbforge.git", "published_at": "2026-07-27 15:11:36+00:00", "updated_at": "2026-07-27 15:23:03.941817+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Dumbforge", "Cloudflare R2", "GitHub", "superdisk"], "alternates": {"html": "https://wpnews.pro/news/dumbforge-host-your-git-repo-from-an-s3-bucket-for-free", "markdown": "https://wpnews.pro/news/dumbforge-host-your-git-repo-from-an-s3-bucket-for-free.md", "text": "https://wpnews.pro/news/dumbforge-host-your-git-repo-from-an-s3-bucket-for-free.txt", "jsonld": "https://wpnews.pro/news/dumbforge-host-your-git-repo-from-an-s3-bucket-for-free.jsonld"}}