serve the contents of buckets simply
  • Go 67.7%
  • Shell 8.7%
  • JavaScript 7%
  • PowerShell 6.6%
  • HTML 5.1%
  • Other 4.9%
Find a file
Charley Sheets cf39a6eccf
Some checks failed
Lint / Lint (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
Build and Push Docker Image / tag (push) Has been cancelled
Test / Test with Coverage (push) Has been cancelled
Build and Push Docker Image / build-amd64 (push) Has been cancelled
Build and Push Docker Image / build-arm64 (push) Has been cancelled
Build and Push Docker Image / create-manifest (push) Has been cancelled
Build and Push Docker Image / create-release (push) Has been cancelled
Test / Integration Tests (push) Has been cancelled
docs: update references from GitHub/ghcr.io to git.brooktrails.org
Update all project-hosting URLs, container registry references, and
GCS-centric website copy to reflect the migration to Forgejo and
S3-compatible storage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:52:21 +00:00
.github/workflows fix(ci): update coverage upload configuration to use coverage.out instead of lcov 2025-06-21 19:59:49 -07:00
deployment docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00
docs feat(cache): implement HTTP cache feature with configurable options 2025-06-27 12:56:38 -07:00
scripts feat(cache): implement HTTP cache feature with configurable options 2025-06-27 12:56:38 -07:00
testdata feat(cache): implement HTTP cache feature with configurable options 2025-06-27 12:56:38 -07:00
website docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00
.gitignore feat(tests): add comprehensive coverage tests for logging and server setup 2025-06-15 19:21:34 -07:00
config.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
config_coverage_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
config_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
Dockerfile feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
go.mod feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
go.sum feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
headers_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
interfaces.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
LICENSE.md fix: license 2025-01-08 01:36:19 -08:00
logging.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
logging_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
main.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
main_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
metrics.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
metrics_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
object_store_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
README.md docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00
redirects_test.go docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00
s3.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server.go docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00
server_coverage_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server_integration_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server_setup.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server_setup_enhanced_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server_setup_test.go feat: add S3-compatible storage backend, decouple from GCS 2026-03-15 20:47:06 +00:00
server_test.go docs: update references from GitHub/ghcr.io to git.brooktrails.org 2026-03-16 15:52:21 +00:00

Spray

Spray is a minimal Go web server that serves static files from S3-compatible object storage (such as minio or AWS S3). It also supports Google Cloud Storage as an alternative backend.

Features

  • Simple and lightweight
  • S3-compatible storage as default backend (minio, AWS S3, etc.)
  • Google Cloud Storage support (optional)
  • Prometheus metrics
  • Custom redirects support
  • HTTP cache with configurable rollout
  • Health check endpoints
  • Configurable port

Configuration

Environment Variables

Storage Backend

Variable Description Default
STORAGE_BACKEND Storage backend to use: s3 or gcs s3
BUCKET_NAME Name of the bucket to serve files from (required)

S3 Backend (STORAGE_BACKEND=s3)

Variable Description Default
S3_ENDPOINT S3-compatible endpoint URL (e.g. http://minio:9000) (AWS default)
S3_REGION S3 region us-east-1
AWS_ACCESS_KEY_ID AWS/S3 access key (from environment/IAM)
AWS_SECRET_ACCESS_KEY AWS/S3 secret key (from environment/IAM)

GCS Backend (STORAGE_BACKEND=gcs)

Variable Description Default
GOOGLE_PROJECT_ID Google Cloud project ID (required for GCS)
GOOGLE_APPLICATION_CREDENTIALS Path to GCP service account JSON (from environment)

Logging

Variable Description Default
LOGGING_BACKEND Logging backend: zap or gcp zap

Zap produces structured JSON logs to stderr. GCP logging requires valid Google Cloud credentials and is only useful when running on GCP.

Other

Variable Description Default
SPRAY_POWERED_BY_HEADER Custom X-Powered-By header value (empty string disables) spray/<version>
STORAGE_MOCK Set to true for a built-in mock store (debugging only) false

Metrics

The following Prometheus metrics are exposed at /metrics:

  • spray_requests_total - Total HTTP requests, labeled by bucket, path, method and status
  • spray_request_duration_seconds - Request duration histogram
  • spray_bytes_transferred_total - Total bytes transferred
  • spray_active_requests - Currently active requests
  • spray_cache_total - Cache hit/miss/bypass counter
  • spray_errors_total - Errors by type
  • spray_object_size_bytes - Served object sizes
  • spray_storage_operation_duration_seconds - Storage operation latency

Custom Redirects

Configure redirects by creating a .spray/redirects.toml file in your bucket:

[redirects]
"/old-path" = "https://example.com/new-path"
"/another-path" = "https://example.com/destination"

Redirects take precedence over files at the same path. The server returns a 302 Found response.

Inspect the current redirect configuration at /config/redirects:

{
  "redirects": {
    "/old-path": "https://example.com/new-path",
    "/source": "https://git.brooktrails.org/picotechllc/spray"
  },
  "count": 2,
  "config_source": ".spray/redirects.toml",
  "bucket_name": "your-bucket-name"
}

X-Powered-By Header

Spray adds an X-Powered-By header to responses. Control it with:

  • Server admin: Set SPRAY_POWERED_BY_HEADER env var (empty string disables entirely)
  • Site owner: Create .spray/headers.toml in your bucket with [powered_by] / enabled = false

Server admin settings take precedence. If the env var disables the header, site owners cannot re-enable it.

Endpoints

  • / - Serves static files from the configured bucket
  • /metrics - Prometheus metrics
  • /readyz - Readiness probe
  • /livez - Liveness probe
  • /config/redirects - Current redirect configuration (JSON)

Usage

With minio (S3-compatible)

docker run \
  -e BUCKET_NAME=my-site \
  -e S3_ENDPOINT=http://minio:9000 \
  -e AWS_ACCESS_KEY_ID=minioadmin \
  -e AWS_SECRET_ACCESS_KEY=minioadmin \
  -p 8080:8080 \
  git.brooktrails.org/picotechllc/spray:latest

With AWS S3

docker run \
  -e BUCKET_NAME=my-site \
  -e S3_REGION=us-west-2 \
  -e AWS_ACCESS_KEY_ID=AKIA... \
  -e AWS_SECRET_ACCESS_KEY=... \
  -p 8080:8080 \
  git.brooktrails.org/picotechllc/spray:latest

With Google Cloud Storage

docker run \
  -e STORAGE_BACKEND=gcs \
  -e BUCKET_NAME=my-site \
  -e GOOGLE_PROJECT_ID=my-project \
  -p 8080:8080 \
  git.brooktrails.org/picotechllc/spray:latest

Building from source

git clone https://git.brooktrails.org/picotechllc/spray.git
cd spray
go build

License

This project is licensed under the MIT License. See the LICENSE file for details.

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Website

The Spray project website is hosted using Spray itself at spray.picote.ch.

Contact

For any questions or suggestions, please open an issue.