diff --git a/INSTALLATION.md b/INSTALLATION.md
index 91f2a66..92579c0 100644
--- a/INSTALLATION.md
+++ b/INSTALLATION.md
@@ -8,13 +8,13 @@ The ATCR credential helper enables Docker to authenticate with ATCR registries u
**Linux/macOS:**
```bash
-curl -fsSL https://atcr.io/install.sh | bash
+curl -fsSL https://atcr.io/static/install.sh | bash
```
Or download and run manually:
```bash
-curl -fsSLO https://atcr.io/install.sh
+curl -fsSLO https://atcr.io/static/install.sh
chmod +x install.sh
./install.sh
```
@@ -22,7 +22,7 @@ chmod +x install.sh
Custom installation directory:
```bash
-INSTALL_DIR=$HOME/.local/bin curl -fsSL https://atcr.io/install.sh | bash
+INSTALL_DIR=$HOME/.local/bin curl -fsSL https://atcr.io/static/install.sh | bash
```
**Windows (PowerShell as Administrator):**
@@ -85,7 +85,7 @@ Homebrew will automatically download the correct binary for your platform.
docker-credential-atcr version
```
-### From Source (requires Go 1.23+)
+### From Source (requires Go 1.26+)
```bash
go install atcr.io/cmd/credential-helper@latest
diff --git a/README.md b/README.md
index bb66a87..72d1ff3 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ atcr.io/did:plc:xyz123/myapp:latest
**1. Install credential helper:**
```bash
-curl -fsSL https://atcr.io/install.sh | bash
+curl -fsSL https://atcr.io/static/install.sh | bash
```
**2. Configure Docker** (add to `~/.docker/config.json`):
diff --git a/docs/CREDENTIAL_HELPER.md b/docs/CREDENTIAL_HELPER.md
index 408fdd1..4291e33 100644
--- a/docs/CREDENTIAL_HELPER.md
+++ b/docs/CREDENTIAL_HELPER.md
@@ -68,7 +68,7 @@ git push origin v1.0.0
**Usage:**
```bash
# Linux/macOS
-curl -fsSL https://atcr.io/install.sh | bash
+curl -fsSL https://atcr.io/static/install.sh | bash
# Windows (PowerShell)
iwr -useb https://atcr.io/install.ps1 | iex
@@ -113,7 +113,7 @@ go install atcr.io/cmd/credential-helper@latest
sudo mv $(go env GOPATH)/bin/credential-helper /usr/local/bin/docker-credential-atcr
```
-**Note:** This requires Go 1.23+ and compiles locally.
+**Note:** This requires Go 1.26+ and compiles locally.
## Release Process
@@ -138,7 +138,7 @@ sudo mv $(go env GOPATH)/bin/credential-helper /usr/local/bin/docker-credential-
- Visit: https://github.com/atcr-io/atcr/releases
- Test install script:
```bash
- ATCR_VERSION=v1.0.0 curl -fsSL https://atcr.io/install.sh | bash
+ ATCR_VERSION=v1.0.0 curl -fsSL https://atcr.io/static/install.sh | bash
docker-credential-atcr version
```
@@ -266,7 +266,7 @@ Docker looks for binaries named `docker-credential-*` in PATH:
# Clean install in fresh environment
docker run --rm -it ubuntu:latest bash
apt update && apt install -y curl
- curl -fsSL https://atcr.io/install.sh | bash
+ curl -fsSL https://atcr.io/static/install.sh | bash
```
2. **Test Docker integration:**
diff --git a/pkg/appview/middleware/goimport.go b/pkg/appview/middleware/goimport.go
new file mode 100644
index 0000000..1815058
--- /dev/null
+++ b/pkg/appview/middleware/goimport.go
@@ -0,0 +1,43 @@
+package middleware
+
+import (
+ "fmt"
+ "html"
+ "net/http"
+)
+
+// GoImport serves the `` tag required by `go install` /
+// `go get` to resolve the vanity path `atcr.io/...` to the source repository.
+//
+// Go tooling requests `https://atcr.io/?go-get=1` and expects an HTML
+// document with a meta tag of the form:
+//
+//
+//
+// The meta tag must be present on every subpath under the module root, so this
+// runs as middleware at the top of the chain and short-circuits any request
+// carrying `?go-get=1`.
+func GoImport(modulePath, repoURL string) func(http.Handler) http.Handler {
+ body := fmt.Sprintf(
+ `go get %s`,
+ html.EscapeString(modulePath),
+ html.EscapeString(repoURL),
+ html.EscapeString(modulePath),
+ html.EscapeString(repoURL),
+ html.EscapeString(repoURL),
+ html.EscapeString(repoURL),
+ html.EscapeString(modulePath),
+ )
+
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Query().Get("go-get") != "1" {
+ next.ServeHTTP(w, r)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.Header().Set("Cache-Control", "public, max-age=300")
+ _, _ = w.Write([]byte(body))
+ })
+ }
+}
diff --git a/pkg/appview/public/static/install.sh b/pkg/appview/public/static/install.sh
index b6d8c2c..282f883 100755
--- a/pkg/appview/public/static/install.sh
+++ b/pkg/appview/public/static/install.sh
@@ -1,6 +1,6 @@
#!/bin/bash
# ATCR Credential Helper Installation Script
-# Usage: curl -fsSL https://atcr.io/install.sh | bash
+# Usage: curl -fsSL https://atcr.io/static/install.sh | bash
set -e
diff --git a/pkg/appview/server.go b/pkg/appview/server.go
index cd5d791..d55c4ee 100644
--- a/pkg/appview/server.go
+++ b/pkg/appview/server.go
@@ -298,6 +298,9 @@ func NewAppViewServer(cfg *Config, branding *BrandingOverrides) (*AppViewServer,
mainRouter.Use(chimiddleware.Recoverer)
mainRouter.Use(chimiddleware.GetHead)
mainRouter.Use(routes.CORSMiddleware())
+ // Vanity import prefix must match the `module` line in go.mod exactly,
+ // otherwise `go install` fails the module-path check.
+ mainRouter.Use(middleware.GoImport("atcr.io", cfg.UI.SourceURL))
// Domain routing middleware
if len(cfg.Server.RegistryDomains) > 0 {