{"id":39075594,"url":"https://github.com/cloud-gov/pages-proxy","last_synced_at":"2026-01-17T18:26:26.244Z","repository":{"id":16906626,"uuid":"80066355","full_name":"cloud-gov/pages-proxy","owner":"cloud-gov","description":"Proxies traffic from the Federalist S3 bucket","archived":false,"fork":false,"pushed_at":"2025-11-25T17:36:12.000Z","size":1957,"stargazers_count":3,"open_issues_count":3,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-11-28T22:56:57.829Z","etag":null,"topics":["federalist","federalistapp"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloud-gov.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2017-01-25T22:57:09.000Z","updated_at":"2025-11-25T17:35:03.000Z","dependencies_parsed_at":"2024-03-12T20:46:23.172Z","dependency_job_id":"8ffded8f-bf03-45fb-9930-489c6b52d2a9","html_url":"https://github.com/cloud-gov/pages-proxy","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/cloud-gov/pages-proxy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloud-gov","download_url":"https://codeload.github.com/cloud-gov/pages-proxy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloud-gov%2Fpages-proxy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28515470,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T17:57:59.192Z","status":"ssl_error","status_checked_at":"2026-01-17T17:57:52.527Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["federalist","federalistapp"],"created_at":"2026-01-17T18:26:26.148Z","updated_at":"2026-01-17T18:26:26.229Z","avatar_url":"https://github.com/cloud-gov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pages-proxy\n\nProxies traffic from the Cloud.gov Pages (formerly Federalist) S3 bucket to a CDN broker. Ensures HTTPS and adds the proper headers.\n\n## Usage\n\nTo deploy the app:\n\n    $ cf push \u003capp-name\u003e --strategy rolling --vars-file \u003c/path/to/vars-file\u003e -f \u003c/path/to/manifest\u003e\n\nIf the rolling deployment fails for any reason, make sure to clean up by running:\n    $ cf cancel-deployment \u003capp-name\u003e\n\n## Proxying a Site\n\nWhen a site is added to Pages, it will be available through this proxy at `https://\u003csite-bucket\u003e.sites.pages.cloud.gov/site/\u003cowner\u003e/\u003crepo\u003e`. When the site is ready to go live, a CloudFront distribution with the proxy URL as its origin can be provisioned. This is done via the Admin UI panel in the '/domains' tab by creating a domain, ensuring [correct CNAME configuration](https://federalist.18f.gov/documentation/custom-domains/), and clicking \"Provision\".\n\n## Headers\n\nThis proxy adds the following headers to the response from the S3 bucket:\n\n- Strict-Transport-Security: max-age=31536000; preload\n- X-Frame-Options: SAMEORIGIN\n- X-Server: Cloud.gov Pages\n\n## Unique Site Headers\n\nTo support sites with expanded HSTS headers, the proxy uses the\n{{ INCLUDE_SUBDOMAINS }} environment variable to identify these requests to provide\nthe expanded header `Strict-Transport-Security: max-age=31536000; includeSubDomains; preload`.\nIf these site domains change for any reason, the {{ INCLUDE_SUBDOMAINS }}\nvariable will need to be updated in the `manifest.yml`.\n\n## Short-term Site Redirects\n\nTo support short-term site redirects, the proxy uses an included redirects config which is built during deployment via a credhub json credential named `proxy-\u003cenv\u003e-site-redirects` and set as an environment variable as `SITE_REDIRECTS`. The site redirects value is an array of objects with the following structure:\n\n|Key|Required?|Default|Description|\n--- | --- | --- | --- |\n|`subdomain`|:white_check_mark:|__N/A__|The site's Pages subdomain|\n|`target`|:white_check_mark:|__N/A__|The target domain for the redirect|\n|`path`|:x:|`''`|An optional path appended to the redirect target|\n|`usePreviewPath`|:x:|`false`|An optional boolean to append the site's preview path to redirect target|\n\n## Local setup\n### Install Depedencies\n```\n  docker compose run --no-deps --rm app npm install\n```\n\n### Running tests against the mock server\n```\n  docker compose run --no-deps --rm app npm run parse\n  docker compose run --rm app npm test\n```\n\n### Running tests against s3 buckets\n```\n  docker compose run --no-deps --rm app npm run parse:integration\n  docker compose run --rm app npm run test:integration\n```\n\n## Continuous Integration\nThe proxy uses Concourse CI to run tests and deploy to different environments in the cloud.gov Pages organization. The pipeline is defined in the [`ci/pipeline.yml`](./ci/pipeline.yml) file and supporting CI scripts are found in the [`ci`](./ci) directory. This pipeline is using Concourse's [`instanced pipeline`](https://concourse-ci.org/instanced-pipelines.html) feature to minimize boilerplate configuration when declaring tasks and resources for each deployment environment.\n\n__*\u0026#8595; NOTICE \u0026#8595;*__\n\n\u003e __Proxy Dev__ deploys the proxy app when a PR is created into the `staging` branch. This uses a unique pipeline file: [./ci/pipeline-dev.yml](./ci/pipeline-dev.yml)\n\n### Pipeline instance variables\nTwo instances of the pipeline are set for the `staging` and `production` environments. Instance variables are used to fill in Concourse pipeline parameter variables bearing the same name as the instance variable. See more on [Concourse vars](https://concourse-ci.org/vars.html).  Each instance of the pipeline has two instance variables associated to it: `deploy-env` \u0026 `git-branch`.\n\n|Instance Variable|Dev Environment|Staging Environment|Production Environment|\n--- | --- | --- | --- |\n|**`deploy-env`**|`dev`|`staging`|`production`|\n|**`git-branch`**|`staging`|`staging`|`main`|\n\n### Pipeline credentials\nConcourse CI integrates directly with [Credhub](https://docs.cloudfoundry.org/credhub/) to provide access to credentials/secrets at job runtime. When a job is started, Concourse will resolve the parameters within the pipeline with the latest credentials using the double parentheses notation (ie. `((\u003ccredential-name\u003e))`). See more about the [credentials lookup rules](https://concourse-ci.org/credhub-credential-manager.html#credential-lookup-rules).\n\nSome credentials in this pipeline are \"compound\" credentials that use the pipeline's instance variable in conjuction with its parameterized variables to pull the correct Credhub credentials based on the pipeline instance. The following parameters are used in the proxy pipeline:\n\n|Parameter|Description|Is Compound|\n--- | --- | --- |\n|**`((((deploy-env))-cf-username))`**|The deployment environments CloudFoundry deployer username based on the instanced pipeline|:white_check_mark:|\n|**`((((deploy-env))-cf-username))`**|The deployment environments CloudFoundry deployer password based on the instanced pipeline|:white_check_mark:|\n|**`((dedicated-aws-access-key-id))`**|AWS access key for testing|:x:|\n|**`((dedicated-aws-secret-access-key))`**| AWS secret key for testing|:x:|\n|**`((slack-channel))`**| Slack channel | :x:|\n|**`((slack-username))`**| Slack username | :x:|\n|**`((slack-icon-url))`**| Slack icon url | :x:|\n|**`((slack-webhook-url))`**| Slack webhook url | :x:|\n|**`((git-base-url))`**|The base url to the git server's HTTP endpoint|:x:|\n|**`((proxy-repository-path))`**|The url path to the repository|:x:|\n|**`((gh-access-token))`**| The Github access token|:x:|\n|**`((pages-proxy-((deploy-env))-site-redirects))`**|JSON array of redirect objects|:white_check_mark:|\n\n### Setting up the pipeline\nThe pipeline and each of its instances will only need to be set once per instance to create the initial pipeline. After the pipelines are set, updates to the respective `git-branch` source will automatically set the pipeline with any updates. See the [`set_pipeline` step](https://concourse-ci.org/set-pipeline-step.html) for more information. Run the following command with the fly CLI to set a pipeline instance:\n\n```bash\n$ fly -t \u003cConcourse CI Target Name\u003e set-pipeline -p proxy \\\n  -c ci/pipeline.yml \\\n  -i git-branch=main \\\n  -i deploy-env=production\n```\n\n### Getting or deleting a pipeline instance from the CLI\nTo get a pipeline instance's config or destroy a pipeline instance, Run the following command with the fly CLI to set a pipeline:\n\n```bash\n## Get a pipeline instance config\n$ fly -t \u003cConcourse CI Target Name\u003e get-pipeline \\\n  -p proxy/deploy-env:production,git-branch:main\n\n## Destroy a pipeline\n$ fly -t \u003cConcourse CI Target Name\u003e destroy-pipeline \\\n  -p proxy/deploy-env:production,git-branch:main\n```\n\n## Notes\n### When making changes\nIn order for changes to the `nginx.conf` file or mock server to be reflected when running the tests, the dockers services must be restarted. This can be done by running `docker compose down` before the above commands to parse the nginx.conf and run the tests.\n\n### Integration tests\nIntegration tests use the following S3 buckets provisioned in the `sandbox` space in the `gsa-18f-federalist` cloud.gov organization:\n- `proxy-integration-test-dedicated`\n\nBefore running the tests, make a copy of the `.env.sample` file named `.env` and populate with the credentials from corresponding service keys `proxy-integration-test-dedicated-key` in the `sandbox` space. Ex. `cf t -s sandbox \u0026\u0026 cf service-key proxy-integration-test-dedicated proxy-integration-test-dedicated-key`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Fpages-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloud-gov%2Fpages-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloud-gov%2Fpages-proxy/lists"}