summaryrefslogtreecommitdiffstats
path: root/GIT_AND_GOMOD_PLAN.md
diff options
context:
space:
mode:
authorbndw <ben@bdw.to>2026-02-15 17:17:18 -0800
committerbndw <ben@bdw.to>2026-02-15 17:17:18 -0800
commit7a29f83af2d23f6f3399e19f3879c667287252ed (patch)
tree561bfc460759333196da687a6d93014e59ac4b36 /GIT_AND_GOMOD_PLAN.md
parent702cb02831be836eeda91cd58504aeca45b1a260 (diff)
random design files
Diffstat (limited to 'GIT_AND_GOMOD_PLAN.md')
-rw-r--r--GIT_AND_GOMOD_PLAN.md230
1 files changed, 230 insertions, 0 deletions
diff --git a/GIT_AND_GOMOD_PLAN.md b/GIT_AND_GOMOD_PLAN.md
new file mode 100644
index 0000000..183154f
--- /dev/null
+++ b/GIT_AND_GOMOD_PLAN.md
@@ -0,0 +1,230 @@
1# Go Vanity Import + Git Server Architecture
2
3This document describes a **simple, robust architecture** for hosting Go module source code and enabling `go get` on a **custom domain**, using:
4
5* A basic Git server (authoritative source)
6* Go vanity imports
7* Caddy for HTTPS with automatic TLS
8
9The design prioritizes:
10
11* Simplicity
12* Long-term correctness
13* Zero client-side configuration
14* Easy future migration to a module proxy if needed
15
16---
17
18## Goals
19
20* Host all authored Go modules under a single domain (e.g. `yourdomain.com/foo`)
21* Allow anyone to run:
22
23 ```bash
24 go get yourdomain.com/foo
25 ```
26
27 with no environment variables or flags
28* Retain full control of source code and hosting
29* Avoid unnecessary complexity (S3 proxies, CI artifact pipelines) for a single author
30
31---
32
33## High-Level Architecture
34
35```
36yourdomain.com
37 ├─ /<module> → Vanity import discovery (?go-get=1)
38 ├─ /<module>.git → Git repository (HTTPS, read-only)
39 └─ ssh://git@yourdomain.com/<module>.git → Git writes (SSH)
40```
41
42Components:
43
44* **Caddy**: Fronts everything, provides HTTPS automatically
45* **Vanity Import Server**: Tiny Go HTTP server that serves `<meta go-import>` tags
46* **Git Server**: Bare Git repositories served over HTTPS and SSH
47
48---
49
50## How `go get` Works in This Setup
51
52When a user runs:
53
54```bash
55go get yourdomain.com/foo
56```
57
58Go performs the following steps:
59
601. **Vanity discovery**
61
62 ```
63 GET https://yourdomain.com/foo?go-get=1
64 ```
65
662. **Vanity server responds** with:
67
68 ```html
69 <meta name="go-import"
70 content="yourdomain.com/foo git https://yourdomain.com/foo.git">
71 ```
72
733. **Go clones the repository**:
74
75 ```
76 git clone https://yourdomain.com/foo.git
77 ```
78
794. **Go reads `go.mod`**, checks tags (e.g. `v1.2.3`), and builds the module
80
81No Go module proxy is involved.
82
83---
84
85## Module Requirements
86
87Each module repository **must**:
88
89* Be located at `/srv/git/<module>.git`
90* Have a `go.mod` file with:
91
92 ```go
93 module yourdomain.com/<module>
94 ```
95* Use semantic version tags:
96
97 ```
98 v1.0.0
99 v1.2.3
100 ```
101
102Tags must not be rewritten after publication.
103
104---
105
106## Vanity Import Server
107
108A single Go HTTP server can serve vanity imports for **all modules**.
109
110### Responsibilities
111
112* Respond only to `?go-get=1` requests
113* Dynamically map paths to Git repositories
114* Serve static HTML with `<meta name="go-import">`
115
116### Behavior
117
118For a request to:
119
120```
121/foo?go-get=1
122```
123
124The server returns:
125
126```html
127<meta name="go-import"
128 content="yourdomain.com/foo git https://yourdomain.com/foo.git">
129```
130
131All non-`go-get` requests return `404` (or are handled elsewhere).
132
133---
134
135## Git Server
136
137### Repository Layout
138
139```
140/srv/git/
141 ├─ foo.git
142 ├─ bar.git
143 └─ baz.git
144```
145
146Repositories are:
147
148* **Bare**
149* Read-only over HTTPS
150* Writable only via SSH
151
152### Write Access
153
154* SSH only
155* Single `git` user
156* Access controlled via `authorized_keys`
157
158Example push:
159
160```bash
161git push git@yourdomain.com:/srv/git/foo.git
162```
163
164---
165
166## Caddy Configuration
167
168Caddy is used as the front-facing server.
169
170### Responsibilities
171
172* Automatic HTTPS (Let’s Encrypt)
173* Route `.git` paths to `git-http-backend`
174* Route all other paths to the vanity import server
175
176### Conceptual Routing
177
178* `/*.git*` → Git HTTP backend
179* `/*` → Vanity import server
180
181This keeps TLS, routing, and process management simple and centralized.
182
183---
184
185## Why This Design Is “Bullet-Proof Simple”
186
187### Advantages
188
189* No module proxy implementation required
190* No S3, CloudFront, or artifact format rules
191* No CI publishing pipeline needed
192* Fully compatible with Go tooling
193* Easy to debug (if `git clone` works, `go get` works)
194* Mirrors Go’s original and still-supported design
195
196### Trade-offs
197
198* Git-based fetching is slower than a proxy
199* No immutable release guarantees beyond Git tags
200* Less suitable for very high traffic
201
202For a single-author, self-hosted setup, these trade-offs are acceptable.
203
204---
205
206## Future Migration Path (Optional)
207
208If needed later, this setup can evolve into a module proxy:
209
210* Keep vanity import paths unchanged
211* Switch `<meta go-import>` from `git` → `mod`
212* Introduce an S3-backed module proxy
213* Users do not need to change imports or commands
214
215This design does not lock you into Git forever.
216
217---
218
219## Summary
220
221This architecture provides:
222
223* A single, authoritative domain for all Go modules
224* Simple Git-based source hosting
225* Zero-config `go get` for users
226* Minimal operational complexity
227* A clean upgrade path to a full module proxy
228
229It is the simplest solution that is still fully correct and future-proof for Go modules.
230