orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1{{/*
2 The 100MB guidance, in one place because it belongs on three pages.
3
4 Where it is shown matters more than what it says. The limit bites on the first
5 push of an existing repository, so a warning that lives only on a populated
6 repository page arrives strictly after the moment it was needed. It is shown:
7
8 - on the index, before any repository exists, next to the remote-add command
9 - on an empty repository page, which is exactly the state a failed oversized
10 push leaves behind: info/refs succeeds and creates the repository, then
11 Cloudflare kills the pack upload
12 - on the settings page under a freshly minted token, since minting one is
13 what a person does immediately before their first push
14*/}}
15
16{{define "pushlimit"}}
17<div class="pushlimit">
18 <h4>If the repository is over 100 MB, seed it differently</h4>
19 <p>
20 Cloudflare refuses any single request body over 100 MB, and the tunnel
21 hostname has to stay proxied, so nothing here can raise it. This only affects
22 the <em>first</em> push of an existing repository: every push after that sends
23 new objects only and is kilobytes. Check with
24 <code>git count-objects -vH</code> and look at <code>size-pack</code>.
25 </p>
26
27 <p><strong>1. Seed over the Docker bridge</strong>, from a container on
28 <code>orchard-edge</code>. Cloudflare is not in the path, so no limit applies:</p>
29 <pre class="cmd">git push http://{{.Bridge}}:8000/{{.Name}}.git --all && git push http://{{.Bridge}}:8000/{{.Name}}.git --tags</pre>
30
31 <p><strong>2. Or push in slices</strong>, which works from anywhere. Each slice
32 is its own request, so none of them approaches the limit:</p>
33 <pre class="cmd">git log --oneline --reverse main | awk 'NR % 500 == 0' | cut -d' ' -f1 \
34 | while read sha; do git push origin +$sha:refs/heads/main; done
35git push origin main</pre>
36 <p class="hint">
37 Halve the step if a slice still fails. Raising
38 <code>http.postBuffer</code> does not help: git's own documentation says it
39 only disables chunked encoding for servers that cannot handle it.
40 </p>
41</div>
42{{end}}
43
44
45{{/* Carries Name as well as Bridge, because it forwards its dot to pushlimit. */}}
46{{define "firstpush"}}
47<details class="firstpush">
48 <summary>Pushing a repository here</summary>
49 <div class="firstpushbody">
50 <p>Any name works, and pushing to one that does not exist creates it. The
51 username is ignored, so anything will do; the password is a push token from
52 <a href="/settings">Settings</a>.</p>
53 <pre class="cmd">git remote add origin {{.CloneURL}}/<name>.git
54git push -u origin main</pre>
55 {{template "pushlimit" .}}
56 </div>
57</details>
58{{end}}