Skip to main content

gcs-static-site-proxy

Serve one private Google Cloud Storage static-site prefix, or an explicit catalog of prefixes, through a renewable, read-only local proxy. The GCS bucket remains private: the proxy uses the operator's Application Default Credentials (ADC) and exposes only explicitly configured object prefixes.

Status: alpha. Review the publication-prefix and network-access security model before using the proxy with protected data.

Requirements

  • Python 3.11 or newer
  • uv for the recommended isolated invocation
  • Google Cloud CLI for initializing or refreshing ADC
  • storage.objects.get on the configured objects, normally through roles/storage.objectViewer or a stronger role

Initialize ADC:

gcloud auth login --update-adc

Install and run on localhost

Run the published package in an isolated environment:

uvx gcs-static-site-proxy@0.1.0 \
  --bucket private-site-bucket \
  --prefix team/sites/my-site

Alternatively, install it with pip and use either the command or Python module entry point:

python -m pip install gcs-static-site-proxy==0.1.0
python -m gcs_static_site_proxy \
  --bucket private-site-bucket \
  --prefix team/sites/my-site

Run directly from a pinned public Git commit during development:

uvx --from 'git+https://github.com/alexei-ciobanu/gcs-static-site-proxy@COMMIT_SHA' \
  gcs-static-site-proxy \
  --bucket private-site-bucket \
  --prefix team/sites/my-site

The default listener is 127.0.0.1:8080. It accepts only GET and HEAD, rejects path traversal, and does not provide a general GCS proxy. Outbound authentication and GCS requests use the operating system trust store, including root certificate authorities installed through device management.

Multiple sites and a landing page

Catalog mode serves a landing-page prefix at / and mounts explicitly allowlisted site prefixes under /sites/<slug>/:

uvx gcs-static-site-proxy@0.1.0 \
  --bucket private-site-bucket \
  --catalog-prefix team/publication/static-sites

The catalog prefix must contain this exact object:

team/publication/static-sites/.gcs-static-site-proxy-sites.json

Example:

{
  "version": 1,
  "sites": [
    {
      "slug": "service-review",
      "title": "Service review",
      "prefix": "team/projects/service-review/publication/site"
    }
  ]
}

The landing page remains under the catalog prefix. Each mount maps only to its declared prefix; unknown slugs fail closed, and neither catalog nor site configuration objects are browser-accessible. Catalog editors can expose any prefix that their proxy operator can read, so treat the catalog as a browser publication allowlist and never mount a protected artifact prefix.

The proxy loads and validates the catalog and every site's CSP at startup. The landing page uses the catalog prefix's .gcs-static-site-proxy.json; each mounted site uses the same well-known filename under its own prefix. Explicit CLI CSP overrides apply to all mounts.

Path-mounted sites share a browser origin. Per-response CSPs remain distinct, but a script running in one mounted site can make same-origin requests to other mounted sites. Use one catalog only for sites approved for the same audience; use separate origins when stronger isolation is required.

Site security configuration

Unless overridden, the proxy requests this exact object at startup:

<prefix>/.gcs-static-site-proxy.json

Example:

{
  "version": 1,
  "contentSecurityPolicy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; object-src 'none'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'"
}

If it is absent, a strict built-in policy is used. An invalid or inaccessible configuration fails startup. The active source, generation and SHA-256 are printed.

Without an explicit CLI mode, each prefix uses its own GCS configuration and falls back to the strict built-in policy when that object is absent. The mutually exclusive global modes are:

  • --csp-override-file PATH applies one exact local policy to every route;
  • --strict-csp applies the strict built-in policy to every route; and
  • --no-csp disables CSP on every route.

In catalog mode these options affect the landing page and every mounted site. For a local override of only one site, run that prefix separately in single-site mode.

--no-csp disables only CSP. The proxy continues to send no-referrer, nosniff, and frame-denial headers.

Network access

Loopback is the safe default. Explicit non-loopback binding enables network mode:

uvx gcs-static-site-proxy@0.1.0 \
  --bucket private-site-bucket \
  --prefix team/sites/my-site \
  --bind 0.0.0.0

Network mode generates a process-lifetime access token. Opening the printed tokenized URL exchanges it for an HttpOnly, SameSite session cookie. IP-literal Host values are accepted when they match the local destination address; machine hostnames are detected automatically. Use --allow-host HOST for an additional DNS alias.

The cookie is intentionally a browser-session cookie rather than a persistent credential. If the browser is restarted while the proxy remains running, open the printed tokenized URL again.

Anyone who has the token and can reach the listener can read the site using the operator's GCS permissions. Plain HTTP does not protect content from network interception. Supply both options for HTTPS:

--tls-cert certificate.pem --tls-key private-key.pem

Remote visitors cannot launch the local ADC reauthentication command.

Local development

uv sync --dev
uv run pytest
uv run ruff check .
uv run ruff format --check .
uv run ty check src
uv build --no-sources

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gcs_static_site_proxy-0.1.0.tar.gz (114.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gcs_static_site_proxy-0.1.0-py3-none-any.whl (24.3 kB view details)

Uploaded Python 3

File details

Details for the file gcs_static_site_proxy-0.1.0.tar.gz.

File metadata

  • Download URL: gcs_static_site_proxy-0.1.0.tar.gz
  • Upload date:
  • Size: 114.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gcs_static_site_proxy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 651278ec7ec7b486778005b347ca145dc7225cbddf718a3b543b3e5fc983cce3
MD5 e177cdc3c72d124558a6558c9d1bca4e
BLAKE2b-256 a76a0d4fcce206925df1c48e1c3f2fb902db51de1f0b2ea83a44789b0d9bc52c

See more details on using hashes here.

File details

Details for the file gcs_static_site_proxy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: gcs_static_site_proxy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 24.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.4 {"installer":{"name":"uv","version":"0.12.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for gcs_static_site_proxy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cd36a066958ccdf77a685ea7c5d894e3d31f91a5b7adf82f8f63b3a655465627
MD5 d03afbda9bf4b7039810b7433e803292
BLAKE2b-256 5983ea2507497d9c68008cb4a5104ab79c7136996150d0c68dd60995a735adb0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page