{"id":20678226,"url":"https://github.com/codecentric/single-page-application-server","last_synced_at":"2025-04-19T21:16:42.537Z","repository":{"id":92622113,"uuid":"318490779","full_name":"codecentric/single-page-application-server","owner":"codecentric","description":"Base image and Helm chart for serving Single Page Applications (SPAs)","archived":false,"fork":false,"pushed_at":"2024-12-27T15:08:46.000Z","size":755,"stargazers_count":17,"open_issues_count":4,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-29T13:34:41.864Z","etag":null,"topics":["angular","container-image","docker","helm","nginx","react","single-page-app","spa","webapp"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/codecentric/single-page-application-server","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codecentric.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-04T11:07:23.000Z","updated_at":"2025-03-17T07:30:30.000Z","dependencies_parsed_at":"2023-12-11T17:44:54.160Z","dependency_job_id":"e07ab7e7-7585-41a9-95dd-2512568a6930","html_url":"https://github.com/codecentric/single-page-application-server","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fsingle-page-application-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fsingle-page-application-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fsingle-page-application-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codecentric%2Fsingle-page-application-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codecentric","download_url":"https://codeload.github.com/codecentric/single-page-application-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249805614,"owners_count":21327901,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["angular","container-image","docker","helm","nginx","react","single-page-app","spa","webapp"],"created_at":"2024-11-16T21:19:28.438Z","updated_at":"2025-04-19T21:16:42.508Z","avatar_url":"https://github.com/codecentric.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Single Page Application Server\n\n![Update Docker Images](https://github.com/codecentric/single-page-application-server/workflows/Update%20Docker%20Images/badge.svg)\n\nThis container image provides a base for serving Single Page Applications (SPAs) using Nginx as its web server.\n\nFor deploying applications using this image, a corresponding Helm chart is available at [Docker Hub](https://hub.docker.com/r/codecentric/single-page-application-server-chart), too.\n\n## Tags\n\nThe following tags are updated automatically on a weekly basis with the latest Nginx base image:\n\n* `latest` (alias for `1-nginx-stable-alpine`)\n* `1` (alias for `1-nginx-stable-alpine`)\n* `latest-nginx-stable-alpine` (alias for `1-nginx-stable-alpine`)\n* `1-nginx-stable-alpine`\n* `latest-nginx-mainline-alpine` (alias for `1-nginx-mainline-alpine`)\n* `1-nginx-mainline-alpine`\n\nAdditional tags for specific Nginx versions are also available.\n\n## Examples\n\nExamples for usage with Angular and React are located in the `examples` directory.\n\n## General Features\n\n- **SPA Routes Handling**: Routes not matching static files will serve `index.html`, with exceptions for resources like `.js`, `.css`, etc.\n- **Dynamic Configuration**: Configure your SPA at container startup. The configuration is accessible via `window.spaConfig`.\n- **Environment-Specific Config**: Customize settings based on port and domain.\n- **Resource Caching**: Hashed resources are cached indefinitely. Resources must include a hash of at least 8 characters.\n- **HTTP/2**: Enabled by default for HTTPS connections.\n- **Helm Chart**: A general [Helm chart](https://github.com/codecentric/single-page-application-server/blob/master/chart/README.md) is available for applications using this image.\n\n## Security Features\n\n- **Content Security Policy**: Restrictive by default, with automatic whitelisting for server API endpoints.\n- **Referrer Policy**: Disabled by default to prevent leakage.\n- **Content Type Sniffing**: Disabled by default.\n- **HTTPS**: Enforced via HSTS if enabled; uses [recommended OWASP protocols and cipher suites.](https://github.com/OWASP/CheatSheetSeries/blob/1e07c6c894f98af58d8a417eb8df1b20e1b3337e/cheatsheets/TLS_Cipher_String_Cheat_Sheet.md)\n- **Non-Root User**: The container runs as a non-root user but can bind to ports 80 and 443.\n- **Source Maps**: Disabled by default.\n- **Read-only Root Filesystem**: [Supported at container runtime](#read-only-root-filesystem-support)\n- **Supply Chain Verification**: All images are signed using cosign. See [this section for details](#supply-chain-verification).\n\n## Configuration\n\n### App Directory\n\nPlace your SPA resources in `/app/`. All files in this directory will be served by Nginx.\n\n### YAML Configuration\n\nConfigure the application through YAML files at startup:\n\n1. **Default Configuration**: Add a default configuration file to `/config/default.yaml`. Usually added during `docker build`.\n2. **Runtime Configuration**: Mount a runtime configuration file at `/config/config.yaml`. This file will override default settings.\n\n#### Example Configuration\n\n```yaml\ndefault:\n  spa_config:\n    appTitle: \"My Application\"\n    endpoints:\n      api: \"https://api.example.com\"\n```\n\nYou can also define host-specific configurations:\n\n```yaml\ndefault:\n  spa_config:\n    appTitle: \"My Default Title\"\n    endpoints:\n      api: \"https://api.example.com\"\nspecial_host:\n  server_names:\n    - \"special.example.com\"\n  spa_config:\n    appTitle: \"My Domain-specific Title\"\n```\n\n#### Configuration Reference\n\nThe following configuration shows the default values of this base image for every available setting:\n\n```yaml\ndefault:\n  # Specifies to which host names this configuration should apply.\n  server_names:\n    # \"_\" matches any hostname\n    - \"_\"\n  # The href attribute for the base element in the index.html\n  base_href: \"/\"\n  # All options in this map will be available inside the SPA via `window.spaConfig`.\n  # To enable this feature, you also need to include spa_config.js in your index.html.\n  # An existing spa_config.js will be overridden at container startup.\n  spa_config:\n    # A map of endpoints to which the SPA will communicate.\n    # These endpoints will automatically be whitelisted in the connect-src CSP directive if .hardening.whitelist_connect_sources is enabled.\n    endpoints: {}\n  access_log:\n    # Enables access logging\n    enabled: false\n  source_maps:\n    # Enables source maps\n    enabled: false\n    # Configures the regex that is used to identify source map resources\n    regex: \"\\\\.(js|css)\\\\.map$\"\n  http:\n    enabled: true\n    port: 80\n    # Enables redirect to HTTPS if HTTPS is enabled.\n    https_redirect: true\n    # Use different https_redirect_port if application is behind a NAT.\n    # 0 = use https.port\n    https_redirect_port: 0\n    # HTTP 2 over plain text is disabled by default as Nginx supports HTTP 2 over plain text only via prior knowledge.\n    # Enabling HTTP 2 for plain text connections will prevent clients to connect without prior knowledge.\n    # https://trac.nginx.org/nginx/ticket/816\n    http2_enabled: false\n  https:\n    enabled: false\n    port: 443\n    # Enforces HTTPS permanently\n    hsts_enabled: true\n    ssl_certificate: /etc/ssl/default.crt\n    ssl_certificate_key: /etc/ssl/default.key\n    # Configures supported TLS protocols and cipher suites with recommended value\n    # https://github.com/OWASP/CheatSheetSeries/blob/1e07c6c894f98af58d8a417eb8df1b20e1b3337e/cheatsheets/TLS_Cipher_String_Cheat_Sheet.md\n    owasp_cipher_string: A\n    http2_enabled: true\n  keepalive:\n    server:\n      # Sets a timeout in seconds during which a keep-alive client connection will stay open on the server side.\n      timeout_seconds: 75\n  hardening:\n    # Disables referrer to prevent information leakage\n    referrer_policy: \"no-referrer\"\n    # Prevents browsers from guessing the content type\n    x_content_type_options: \"nosniff\"\n    # Will whitelist the endpoints listed in .spa_config.endpoints automatically in the connect-srv CSP directive if enabled.\n    whitelist_spa_config_endpoints_as_connect_sources: true\n    # Map of CSP directives, which will be added to all HTTP responses for HTML and JavaScript documents\n    content_security_policy:\n      base-uri: \"'self'\"\n      block-all-mixed-content: true\n      default-src: \"'self'\"\n      form-action: \"'self'\"\n      frame-ancestors: \"'self'\"\n      frame-src: \"'self'\"\n      object-src: \"'none'\"\n      script-src: \"'self'\"\n      style-src: \"'self'\"\n```\n\n## Read-only Root Filesystem Support\n\nFor security, use a read-only root filesystem. Ensure the following directories are writable:\n\n* `/config/.out`: Used for file generation.\n* `/tmp`: Used by Nginx for cached files and `nginx.pid`.\n\nWhen using Kubernetes, consider mounting these directories as writable volumes with `emptyDir`.\n\n## Supply Chain Verification\n\nUse [cosign](https://docs.sigstore.dev/about/tooling/#cosign) to verify the base image of your Dockerfile when a `codecentric/single-page-application-server` base image was used.\n\n```bash\ncosign dockerfile verify Dockerfile \\\n  --certificate-oidc-issuer https://token.actions.githubusercontent.com \\\n  --certificate-identity-regexp '^https\\:\\/\\/github\\.com\\/codecentric\\/single\\-page\\-application\\-server\\/' \\\n  --base-image-only\n```\n\nYou can try this by checking out this repository and executing this command in the `examples/angular` directory.\n\n## Development\n\n* **Configuration Generation**: Uses [gomplate templates](https://docs.gomplate.ca/).\n* **Image Tests**: Written in Java using [Testcontainers](https://www.testcontainers.org/).\n* **Helm Chart Tests**: Uses the [helm-unittest](https://github.com/helm-unittest/helm-unittest) Helm plugin.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fsingle-page-application-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodecentric%2Fsingle-page-application-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodecentric%2Fsingle-page-application-server/lists"}