A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go

try and use pull_zone

evan.jarrett.net 434a5f1e 07bc924a

verified
+38 -4
+4
config-hold.example.yaml
··· 31 31 bucket: "" 32 32 # Custom S3 endpoint for non-AWS providers (e.g. "https://gateway.storjshare.io"). 33 33 endpoint: "" 34 + # CDN pull zone URL for downloads. When set, presigned GET/HEAD URLs use this host instead of the S3 endpoint. Uploads and API calls still use the S3 endpoint. 35 + pull_zone: "" 34 36 # HTTP server and identity settings. 35 37 server: 36 38 # Listen address, e.g. ":8080" or "0.0.0.0:8080". ··· 39 41 public_url: "" 40 42 # Allow unauthenticated blob reads. If false, readers need crew membership. 41 43 public: false 44 + # DID of successor hold for migration. Appview redirects all requests to the successor. 45 + successor: "" 42 46 # Use localhost for OAuth redirects during development. 43 47 test_mode: false 44 48 # Request crawl from this relay on startup to make the embedded PDS discoverable.
+4
deploy/upcloud/configs/hold.yaml.tmpl
··· 13 13 region: "{{.S3Region}}" 14 14 bucket: "{{.S3Bucket}}" 15 15 endpoint: "{{.S3Endpoint}}" 16 + pull_zone: "" 16 17 server: 17 18 addr: :8080 18 19 public_url: "https://{{.HoldDomain}}" 19 20 public: false 21 + successor: "" 20 22 test_mode: false 21 23 relay_endpoint: "" 22 24 read_timeout: 5m0s ··· 35 37 libsql_sync_interval: 1m0s 36 38 admin: 37 39 enabled: true 40 + gc: 41 + enabled: false 38 42 quota: 39 43 tiers: 40 44 deckhand:
+8
pkg/hold/config.go
··· 81 81 // Custom S3 endpoint for non-AWS providers. 82 82 Endpoint string `yaml:"endpoint" comment:"Custom S3 endpoint for non-AWS providers (e.g. \"https://gateway.storjshare.io\")."` 83 83 84 + // CDN pull zone URL for presigned download URLs. 85 + PullZone string `yaml:"pull_zone" comment:"CDN pull zone URL for downloads. When set, presigned GET/HEAD URLs use this host instead of the S3 endpoint. Uploads and API calls still use the S3 endpoint."` 86 + 84 87 // Internal distribution storage config, built from the above fields. 85 88 distStorage configuration.Storage `yaml:"-"` 86 89 } ··· 188 191 v.SetDefault("storage.region", "us-east-1") 189 192 v.SetDefault("storage.bucket", "") 190 193 v.SetDefault("storage.endpoint", "") 194 + v.SetDefault("storage.pull_zone", "") 191 195 192 196 // GC defaults 193 197 v.SetDefault("gc.enabled", false) ··· 244 248 _ = v.BindEnv("storage.region", "AWS_REGION") 245 249 _ = v.BindEnv("storage.bucket", "S3_BUCKET") 246 250 _ = v.BindEnv("storage.endpoint", "S3_ENDPOINT") 251 + _ = v.BindEnv("storage.pull_zone", "S3_PULL_ZONE") 247 252 248 253 // Bind legacy GC env vars (backward compat) 249 254 _ = v.BindEnv("gc.enabled", "GC_ENABLED") ··· 297 302 if sc.Endpoint != "" { 298 303 params["regionendpoint"] = sc.Endpoint 299 304 params["forcepathstyle"] = true 305 + } 306 + if sc.PullZone != "" { 307 + params["pullzone"] = sc.PullZone 300 308 } 301 309 302 310 storageCfg := configuration.Storage{}
+22 -4
pkg/s3/types.go
··· 33 33 34 34 // RealS3Client wraps AWS SDK v2 *s3.Client to implement S3Client interface 35 35 type RealS3Client struct { 36 - client *awss3.Client 37 - presign *awss3.PresignClient 36 + client *awss3.Client 37 + presign *awss3.PresignClient 38 + pullZone string // CDN pull zone URL for presigned GET/HEAD URLs 38 39 } 39 40 40 41 // NewRealS3Client creates a new RealS3Client wrapper ··· 64 65 func (r *RealS3Client) PresignGetObject(ctx context.Context, input *awss3.GetObjectInput, expires time.Duration) (string, error) { 65 66 result, err := r.presign.PresignGetObject(ctx, input, func(opts *awss3.PresignOptions) { 66 67 opts.Expires = expires 68 + if r.pullZone != "" { 69 + opts.ClientOptions = append(opts.ClientOptions, func(o *awss3.Options) { 70 + o.BaseEndpoint = aws.String(r.pullZone) 71 + }) 72 + } 67 73 }) 68 74 if err != nil { 69 75 return "", err ··· 75 81 func (r *RealS3Client) PresignHeadObject(ctx context.Context, input *awss3.HeadObjectInput, expires time.Duration) (string, error) { 76 82 result, err := r.presign.PresignHeadObject(ctx, input, func(opts *awss3.PresignOptions) { 77 83 opts.Expires = expires 84 + if r.pullZone != "" { 85 + opts.ClientOptions = append(opts.ClientOptions, func(o *awss3.Options) { 86 + o.BaseEndpoint = aws.String(r.pullZone) 87 + }) 88 + } 78 89 }) 79 90 if err != nil { 80 91 return "", err ··· 162 173 s3PathPrefix = strings.TrimPrefix(rootDir, "/") 163 174 } 164 175 176 + // CDN pull zone for presigned download URLs 177 + pullZone, _ := params["pullzone"].(string) 178 + 165 179 slog.Info("S3 presigned URLs enabled", 166 180 "bucket", bucket, 167 181 "region", region, 168 - "pathPrefix", s3PathPrefix) 182 + "pathPrefix", s3PathPrefix, 183 + "pullZone", pullZone) 169 184 170 185 // Create S3 client wrapped in RealS3Client for interface compatibility 186 + realClient := NewRealS3Client(client) 187 + realClient.pullZone = pullZone 188 + 171 189 return &S3Service{ 172 - Client: NewRealS3Client(client), 190 + Client: realClient, 173 191 Bucket: bucket, 174 192 PathPrefix: s3PathPrefix, 175 193 }, nil