From 0f5d29319f0cb9f7e86cd09b0f7bf05d00b0a47c Mon Sep 17 00:00:00 2001 From: Petra Vankova Date: Tue, 13 May 2025 14:41:22 +0200 Subject: [PATCH 1/2] env variable isolation --- apps/docs/content/features/env-variables.mdx | 157 +++++++++++++++++-- apps/docs/static/llms-full.txt | 113 +++++++++++-- apps/docs/static/llms-small.txt | 113 +++++++++++-- 3 files changed, 343 insertions(+), 40 deletions(-) diff --git a/apps/docs/content/features/env-variables.mdx b/apps/docs/content/features/env-variables.mdx index fe48aea2..ade3140d 100644 --- a/apps/docs/content/features/env-variables.mdx +++ b/apps/docs/content/features/env-variables.mdx @@ -1,6 +1,6 @@ --- title: Environment Variables -description: Learn how to use and manage environment variables in Zerops. +description: Learn how to use, manage, and isolate environment variables in Zerops. --- import Image from '/src/components/Image'; @@ -44,7 +44,7 @@ Your application must be redeployed when updating environmental variables in `ze #### 2. Secret Variables -For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be restarted). +For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be reloaded). Secret variables can be managed through: @@ -87,7 +87,7 @@ These variables can also be [referenced](#referencing-variables). Variables that apply across all services within a [project](/features/infrastructure#projects). These provide a way to share common configuration across services. -They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be restarted). +They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be reloaded). ### User-Defined Variables @@ -98,7 +98,7 @@ You can set project-wide variables through: Access **Project environment variables** in your project detail to: - Add individual variables one by one - Edit individual variables -- Use the bulk editor with .env format: +- Use the bulk editor with .env format #### Import Configuration @@ -114,7 +114,97 @@ project: ### System-Generated Variables -Zerops automatically generates project-level variables containing that can be [referenced](#referencing-variables) from services. +Zerops automatically generates project-level variables that can be [referenced](#referencing-variables) from services. + +## Environment Variable Isolation + +A security feature that controls the **visibility** of environment variables across services within a project. + +By default, Zerops isolates environment variables between services to enhance security and prevent unintended access to sensitive information. This isolation can be configured at both project and service levels. + +### Isolation Modes + +Zerops supports two isolation modes: + + + + + + + + + + + + + + + + + + +
ModeDescription
serviceDefault mode. Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services.
noneLegacy mode. All variables from all services are automatically shared and accessible via prefixing.
+### Configuring Isolation + +#### Project-Level Isolation + +Zerops automatically creates the `envIsolation` project variable with the default value `service`. You only need to modify this if you want to disable isolation: + +```yaml title="import.yaml" +project: + ... + envVariables: + envIsolation: none # Disables isolation, sharing all variables +``` + +This can also be set through the Project Environment Variables section in the GUI. + +#### Service-Level Override + +Individual services can override the project-level isolation setting: + +```yaml title="import.yaml" +services: + - hostname: db + ... + envSecrets: + envIsolation: none # This service's variables will be visible to all services +``` +:::tip +You might set a database service to `envIsolation: none` to expose its connection details to other services, without having to manually reference them, while keeping the rest of your services isolated. +::: + +### Accessing Variables Across Services + +#### With Isolation Enabled (`service` mode) + +When isolation is enabled, you must explicitly create reference variables to access variables from other services: + +```yaml title="zerops.yaml" +# In the 'app' service: +run: + envVariables: + # Create a local reference to the 'password' variable from the 'db' service + DB_PASSWORD: ${db_password} +``` + +This approach gives you complete control over which variables are shared between services. + +#### With Isolation Disabled (`none` mode) + +When isolation is disabled, variables are automatically available across all services with the service name prefix: + +```yaml +# In any service, you can directly access: +${db_password} # Accesses the 'password' variable from the 'db' service +``` + +### Best Practices for Variable Isolation + +1. **Use Default Isolation**: Keep the default `service` isolation for enhanced security. +2. **Explicit References**: Create explicit references only for variables that need to be shared. +3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g. `DB_PASSWORD` for a reference to `db_password`). +4. **Service-Level Exceptions**: Use service-level isolation overrides sparingly and only for services that need to expose their variables widely. ## Variable Restrictions @@ -153,17 +243,23 @@ envVariables: ``` #### Across Services -Prefix variables with their respective service name: + +How this works depends on your environment variable isolation setting: + +**With Isolation Enabled** (`service` mode - default) +* Create an explicit reference in the destination service: ```yaml -setup: dbtest - run: - envVariables: - connectionString: 127.0.0.1 +# In the 'app' service +envVariables: + # Creating a reference to the 'connectionString' from 'dbtest' service + dbConnection: ${dbtest_connectionString} +``` -setup: app - run: - envVariables: - dbConnection: ${dbtest_connectionString} +**With Isolation Disabled** (`none` mode) +* Variables from other services are automatically injected into the container and available using the service prefix format `servicename_variablename`: +```yaml +# In any container, you can directly access variables from other services: +# ${dbtest_connectionString} ``` #### Between Build and Runtime Environments @@ -201,4 +297,37 @@ envVariables: name: ${projectName}-${hostname} # Results in: devel-app ``` +## Environment Variable Examples + +### Variable Isolation Example + +Consider a project with three services: `api`, `db`, and `cache`: + +```yaml title="Project structure" +project: + name: my-project +services: + - hostname: api + envSecrets: + # Creating explicit references to needed variables + DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} + CACHE_URL: ${cache_hostname}:${cache_port} + - hostname: db + envSecrets: + password: secureDbPassword + user: dbuser + port: 5432 + - hostname: cache + envSecrets: + password: cacheServerPass + port: 6379 +``` + +With this setup: +- The `api` service can only access the specific `db` and `cache` variables it explicitly references +- The `db` service cannot see any variables from `api` or `cache` +- The `cache` service cannot see any variables from `api` or `db` + +If we changed the project's `envIsolation` to `none`, all services would be able to see all variables from all other services (prefixed with the service name). + *Need help? Join our [Discord community](https://discord.gg/zeropsio).* \ No newline at end of file diff --git a/apps/docs/static/llms-full.txt b/apps/docs/static/llms-full.txt index d0c0bff5..905cd07a 100644 --- a/apps/docs/static/llms-full.txt +++ b/apps/docs/static/llms-full.txt @@ -8122,7 +8122,7 @@ See how to [reference variables](#referencing-variables) between services and be Your application must be redeployed when updating environmental variables in `zerops.yaml`. ::: #### 2. Secret Variables -For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be restarted). +For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be reloaded). Secret variables can be managed through: ##### GUI Interface Navigate to service details and find **Environment variables** in the menu. You can: @@ -8145,14 +8145,14 @@ These variables cannot be deleted and are always listed at the bottom of the env These variables can also be [referenced](#referencing-variables). ## Project Variables Variables that apply across all services within a [project](/features/infrastructure#projects). These provide a way to share common configuration across services. -They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be restarted). +They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be reloaded). ### User-Defined Variables You can set project-wide variables through: #### GUI Interface Access **Project environment variables** in your project detail to: - Add individual variables one by one - Edit individual variables -- Use the bulk editor with .env format: +- Use the bulk editor with .env format #### Import Configuration Create project variables with `envVariables` attribute. See the complete [import.yaml structure](/reference/import). ```yaml title="import.yaml" @@ -8163,7 +8163,61 @@ project: API_VERSION: v1 ``` ### System-Generated Variables -Zerops automatically generates project-level variables containing that can be [referenced](#referencing-variables) from services. +Zerops automatically generates project-level variables that can be [referenced](#referencing-variables) from services. +## Environment Variable Isolation +> A security feature that controls the visibility of environment variables across services within a project. +By default, Zerops isolates environment variables between services to enhance security and prevent unintended access to sensitive information. This isolation can be configured at both project and service levels. +### Isolation Modes +Zerops supports two isolation modes: +| Mode | Description | +|-----------|-------------| +| `service` | **Default mode.** Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. | +| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | +| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | +### Configuring Isolation +#### Project-Level Isolation +Zerops automatically creates the `envIsolation` project variable with the default value `service`. You only need to modify this if you want to disable isolation: +```yaml title="import.yaml" +project: + ... + envVariables: + envIsolation: none # Disables isolation, sharing all variables +``` +This can also be set through the Project Environment Variables section in the GUI. +#### Service-Level Override +Individual services can override the project-level isolation setting: +```yaml title="import.yaml" +services: + - hostname: db + ... + envSecrets: + envIsolation: none # This service's variables will be visible to all services +``` +:::note +You might set a database service to `envIsolation: none` to expose its connection details to other services, without having to manually reference them, while keeping the rest of your services isolated. +::: +### Accessing Variables Across Services +#### With Isolation Enabled (`service` mode) +When isolation is enabled, you must explicitly create reference variables to access variables from other services: +```yaml title="zerops.yaml" +# In the 'app' service: +run: + envVariables: + # Create a local reference to the 'password' variable from the 'db' service + DB_PASSWORD: ${db_password} +``` +This approach gives you complete control over which variables are shared between services. +#### With Isolation Disabled (`none` mode) +When isolation is disabled, variables are automatically available across all services with the service name prefix: +```yaml +# In any service, you can directly access: +${db_password} # Accesses the 'password' variable from the 'db' service +``` +### Best Practices for Variable Isolation +1. **Use Default Isolation**: Keep the default `service` isolation for enhanced security. +2. **Explicit References**: Create explicit references only for variables that need to be shared. +3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g., `DB_PASSWORD` for a reference to `db_password`). +4. **Service-Level Exceptions**: Use service-level isolation overrides sparingly and only for services that need to expose their variables widely. ## Variable Restrictions All environment variables must follow these restrictions: ### Key @@ -8190,17 +8244,22 @@ envVariables: name: ${id}-${hostname} # Results in: 42069-app ``` #### Across Services -Prefix variables with their respective service name: +How this works depends on your environment variable isolation setting: +**With Isolation Enabled** (`service` mode - default): +1. Create an explicit reference in the destination service: ```yaml -setup: dbtest - run: - envVariables: - connectionString: 127.0.0.1 -setup: app - run: - envVariables: - dbConnection: ${dbtest_connectionString} +# In the 'app' service +envVariables: + # Creating a reference to the 'connectionString' from 'dbtest' service + dbConnection: ${dbtest_connectionString} +``` +**With Isolation Disabled** (`none` mode): +Variables from other services are automatically available using the service prefix format `servicename_variablename`: +```yaml +# In any container, you can directly access variables from other services: +# ${dbtest_connectionString} ``` +You don't need to define these in your environment variables - they're automatically injected into the container. #### Between Build and Runtime Environments Build and runtime are two distinct environments in Zerops. Each environment can have its own set of variables, and you can use the same variable names in both environments since they are separate. Due to this separation, variables defined in one are not automatically accessible in the other. To share variables between environments, you need to use specific prefixes: @@ -8229,6 +8288,34 @@ envVariables: hostname: app name: ${projectName}-${hostname} # Results in: devel-app ``` +## Environment Variable Examples +### Variable Isolation Example +Consider a project with three services: `api`, `db`, and `cache`: +```yaml title="Project structure" +project: + name: my-project +services: + - hostname: db + envSecrets: + password: secureDbPassword + user: dbuser + port: 5432 + - hostname: cache + envSecrets: + password: cacheServerPass + port: 6379 + - hostname: api + envSecrets: + # Creating explicit references to needed variables + DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} + CACHE_URL: ${cache_hostname}:${cache_port} + # Notice we didn't reference cache_password since we don't need it +``` +With this setup: +- The `api` service can only access the specific `db` and `cache` variables it explicitly references +- The `db` service cannot see any variables from `api` or `cache` +- The `cache` service cannot see any variables from `api` or `db` +If we changed the project's `envIsolation` to `none`, all services would be able to see all variables from all other services (prefixed with the service name). *Need help? Join our [Discord community](https://discord.gg/zeropsio).* ---------------------------------------- diff --git a/apps/docs/static/llms-small.txt b/apps/docs/static/llms-small.txt index 6fd46787..5de21679 100644 --- a/apps/docs/static/llms-small.txt +++ b/apps/docs/static/llms-small.txt @@ -7941,7 +7941,7 @@ See how to [reference variables](#referencing-variables) between services and be Your application must be redeployed when updating environmental variables in `zerops.yaml`. ::: #### 2. Secret Variables -For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be restarted). +For storing sensitive data you don't want in your source repository. They can be updated without redeployment (though services need to be reloaded). Secret variables can be managed through: ##### GUI Interface Navigate to service details and find **Environment variables** in the menu. You can: @@ -7964,14 +7964,14 @@ These variables cannot be deleted and are always listed at the bottom of the env These variables can also be [referenced](#referencing-variables). ## Project Variables Variables that apply across all services within a [project](/features/infrastructure#projects). These provide a way to share common configuration across services. -They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be restarted). +They work similarly to service secret variables but at project scope - they're managed through the GUI and can be updated without redeployment (though services need to be reloaded). ### User-Defined Variables You can set project-wide variables through: #### GUI Interface Access **Project environment variables** in your project detail to: - Add individual variables one by one - Edit individual variables -- Use the bulk editor with .env format: +- Use the bulk editor with .env format #### Import Configuration Create project variables with `envVariables` attribute. See the complete [import.yaml structure](/reference/import). ```yaml title="import.yaml" @@ -7982,7 +7982,61 @@ project: API_VERSION: v1 ``` ### System-Generated Variables -Zerops automatically generates project-level variables containing that can be [referenced](#referencing-variables) from services. +Zerops automatically generates project-level variables that can be [referenced](#referencing-variables) from services. +## Environment Variable Isolation +> A security feature that controls the visibility of environment variables across services within a project. +By default, Zerops isolates environment variables between services to enhance security and prevent unintended access to sensitive information. This isolation can be configured at both project and service levels. +### Isolation Modes +Zerops supports two isolation modes: +| Mode | Description | +|-----------|-------------| +| `service` | **Default mode.** Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. | +| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | +| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | +### Configuring Isolation +#### Project-Level Isolation +Zerops automatically creates the `envIsolation` project variable with the default value `service`. You only need to modify this if you want to disable isolation: +```yaml title="import.yaml" +project: + ... + envVariables: + envIsolation: none # Disables isolation, sharing all variables +``` +This can also be set through the Project Environment Variables section in the GUI. +#### Service-Level Override +Individual services can override the project-level isolation setting: +```yaml title="import.yaml" +services: + - hostname: db + ... + envSecrets: + envIsolation: none # This service's variables will be visible to all services +``` +:::note +You might set a database service to `envIsolation: none` to expose its connection details to other services, without having to manually reference them, while keeping the rest of your services isolated. +::: +### Accessing Variables Across Services +#### With Isolation Enabled (`service` mode) +When isolation is enabled, you must explicitly create reference variables to access variables from other services: +```yaml title="zerops.yaml" +# In the 'app' service: +run: + envVariables: + # Create a local reference to the 'password' variable from the 'db' service + DB_PASSWORD: ${db_password} +``` +This approach gives you complete control over which variables are shared between services. +#### With Isolation Disabled (`none` mode) +When isolation is disabled, variables are automatically available across all services with the service name prefix: +```yaml +# In any service, you can directly access: +${db_password} # Accesses the 'password' variable from the 'db' service +``` +### Best Practices for Variable Isolation +1. **Use Default Isolation**: Keep the default `service` isolation for enhanced security. +2. **Explicit References**: Create explicit references only for variables that need to be shared. +3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g., `DB_PASSWORD` for a reference to `db_password`). +4. **Service-Level Exceptions**: Use service-level isolation overrides sparingly and only for services that need to expose their variables widely. ## Variable Restrictions All environment variables must follow these restrictions: ### Key @@ -8009,17 +8063,22 @@ envVariables: name: ${id}-${hostname} # Results in: 42069-app ``` #### Across Services -Prefix variables with their respective service name: +How this works depends on your environment variable isolation setting: +**With Isolation Enabled** (`service` mode - default): +1. Create an explicit reference in the destination service: ```yaml -setup: dbtest - run: - envVariables: - connectionString: 127.0.0.1 -setup: app - run: - envVariables: - dbConnection: ${dbtest_connectionString} +# In the 'app' service +envVariables: + # Creating a reference to the 'connectionString' from 'dbtest' service + dbConnection: ${dbtest_connectionString} +``` +**With Isolation Disabled** (`none` mode): +Variables from other services are automatically available using the service prefix format `servicename_variablename`: +```yaml +# In any container, you can directly access variables from other services: +# ${dbtest_connectionString} ``` +You don't need to define these in your environment variables - they're automatically injected into the container. #### Between Build and Runtime Environments Build and runtime are two distinct environments in Zerops. Each environment can have its own set of variables, and you can use the same variable names in both environments since they are separate. Due to this separation, variables defined in one are not automatically accessible in the other. To share variables between environments, you need to use specific prefixes: @@ -8048,6 +8107,34 @@ envVariables: hostname: app name: ${projectName}-${hostname} # Results in: devel-app ``` +## Environment Variable Examples +### Variable Isolation Example +Consider a project with three services: `api`, `db`, and `cache`: +```yaml title="Project structure" +project: + name: my-project +services: + - hostname: db + envSecrets: + password: secureDbPassword + user: dbuser + port: 5432 + - hostname: cache + envSecrets: + password: cacheServerPass + port: 6379 + - hostname: api + envSecrets: + # Creating explicit references to needed variables + DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} + CACHE_URL: ${cache_hostname}:${cache_port} + # Notice we didn't reference cache_password since we don't need it +``` +With this setup: +- The `api` service can only access the specific `db` and `cache` variables it explicitly references +- The `db` service cannot see any variables from `api` or `cache` +- The `cache` service cannot see any variables from `api` or `db` +If we changed the project's `envIsolation` to `none`, all services would be able to see all variables from all other services (prefixed with the service name). *Need help? Join our [Discord community](https://discord.gg/zeropsio).* ---------------------------------------- From d0ee1ae63f7321e28ac19d030445320eb2f1fcf0 Mon Sep 17 00:00:00 2001 From: Petra Vankova Date: Tue, 13 May 2025 22:44:45 +0200 Subject: [PATCH 2/2] static update --- apps/docs/content/static/overview.mdx | 94 ++++++++----------- apps/docs/static/llms-full.txt | 129 ++++++++++++-------------- apps/docs/static/llms-small.txt | 129 ++++++++++++-------------- 3 files changed, 161 insertions(+), 191 deletions(-) diff --git a/apps/docs/content/static/overview.mdx b/apps/docs/content/static/overview.mdx index 6c5709f1..fa2c7c6a 100644 --- a/apps/docs/content/static/overview.mdx +++ b/apps/docs/content/static/overview.mdx @@ -6,7 +6,7 @@ desc: A comprehensive guide to Zerops' Static service, covering configuration, r import DeployButton from '@site/src/components/DeployButton'; import CustomCard from '@site/src/components/CustomCard'; -The Static service provides a streamlined way to serve static content through a pre-configured Nginx setup. It's designed to be simple to use while maintaining the flexibility needed for modern web applications. +The Static service provides a way to serve static content through a pre-configured Nginx setup. It balances simplicity with the flexibility needed for modern web applications. Deploy an Analog app with static hosting in seconds. All you need is a Zerops account. @@ -26,31 +26,34 @@ zerops: base: static ``` -The Static service comes with sensible defaults that work out of the box for most SPAs and static websites. By default, without any `routing` configuration, the service will: +## Default Behavior + +Every Static service in Zerops comes with built-in defaults optimized for modern web applications, including Single Page Applications. By default, for any incoming request, the service will: 1. Try to serve the exact path (`$uri`) 2. Try with .html extension (`$uri.html`) 3. Look for an index.html in the directory (`$uri/index.html`) -4. Fall back to `/index.html` +4. Fall back to `/index.html` (suitable for SPAs) 5. Return 404 if none of the above exist -:::note Zero Configuration for SPAs -This means for basic SPA deployments or static file hosting, you don't need to specify any redirects at all! +:::important SPAs +Single Page Applications work out of the box without any additional configuration. The built-in fallback to `/index.html` ensures that client-side routing functions properly. ::: ## Routing Configuration -The Static service allows you to configure URL routing and redirects through a simple YAML configuration, abstracting away the complexity of Nginx configuration. +The Static service allows you to configure additional URL routing and redirects through simple YAML configuration, abstracting away the complexity of Nginx configuration. -### Basic Structure +### Custom Routing Configuration -Configure routing in the `run.routing` section of your `zerops.yaml`: +Configure custom routing beyond the default behavior in the `run.routing` section of your `zerops.yaml`: ```yaml title="zerops.yaml" run: routing: redirects: - - from: /* - to: /index.html + # Only needed for custom redirect scenarios + - from: /special-path/* + to: /specific-landing-page status: 302 ``` @@ -58,14 +61,18 @@ run: #### Relative Redirects +:::note +Remember that SPA routing is already built into the default behavior. You don't need to add any custom redirects for client-side routing to work. +::: + Use relative redirects to route paths within your application. When both `from` and `to` are relative paths, you can omit the `status` code to create a masked redirect that shows the content of the target page while preserving the original URL: ```yaml title="zerops.yaml" routing: redirects: - # Masked redirect - URL stays the same but shows content from index.html - - from: /* - to: /index.html + # Masked redirect - URL stays the same but shows content from about-us + - from: /about + to: /about-us # Standard redirect with status code - from: /old-page @@ -118,7 +125,7 @@ Use `*` as a wildcard in your paths: - **At the end of a path**: Matches any subsequent content - **At the start of a domain** (after `https://`): Enables regex matching for subdomains -Example of complex domain management: +Example of domain management: ```yaml title="zerops.yaml" run: @@ -141,7 +148,7 @@ When multiple redirects are configured, they follow Nginx's matching priority sy 1. Exact matches are checked first 2. Simple path matches (without wildcards) are checked next -3. Pattern matches (with wildcards) are checked last, in the order they appear in your configuration +3. Pattern matches (with wildcards) are checked last For example: @@ -162,21 +169,17 @@ routing: to: /articles/ preservePath: true status: 302 - - # Catch-all pattern - masked redirect for SPA - - from: /* - to: /index.html ``` In this configuration: - `/` will redirect to `/home` with a 302 status - `/about` will show content from `/about-us` but keep the URL as `/about` - `/blog/post-123.html` will redirect to `/articles/post-123.html` -- Any other path will show the content from `/index.html` while preserving the original URL (common for SPAs) +- Any other path will use the [default behavior](#default-behavior) ### CORS Configuration -You can easily enable CORS for your static service by adding a `cors` directive: +You can enable CORS for your static service by adding a `cors` directive: ```yaml title="zerops.yaml" run: @@ -188,13 +191,19 @@ run: cors: "'*' always" ``` +The `cors` directive sets the following headers: +- `Access-Control-Allow-Origin` +- `Access-Control-Allow-Methods` +- `Access-Control-Allow-Headers` +- `Access-Control-Expose-Headers` + :::note The `cors` directive has a special case: if you specify just `"*"`, it's automatically converted to `'*'`. For any other values, you need to include the proper Nginx syntax including quotes. ::: ### Custom Headers -For more fine-grained control over HTTP headers, use the `headers` directive: +For more control over HTTP headers, use the `headers` directive: ```yaml title="zerops.yaml" run: @@ -250,7 +259,7 @@ add_header Content-Security-Policy "default-src 'self' https://cdn.example.com; ``` :::important Path Handling -When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same default behavior as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). +When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same [default behavior](#default-behavior) as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). If you add headers for a path that already has a location block, your headers will be merged with the existing configuration. ::: @@ -277,7 +286,7 @@ If you specify Access-Control headers in the `headers` directive, they will over ## Prerender Integration -The Static service includes built-in support for Prerender.io, making it easy to implement server-side rendering for search engines and social media crawlers. +The Static service includes built-in support for Prerender.io for server-side rendering for search engines and social media crawlers. ### Basic Prerender Setup @@ -311,22 +320,12 @@ If you need more control over your Nginx configuration: 5. Use this configuration as a starting point for a full Nginx service :::tip -This allows you to graduate to a more customizable setup while maintaining your existing routing logic. +This allows you to move to a more customizable setup while maintaining your existing routing logic. ::: ## Best Practices -1. **SPA Configuration** - ```yaml title="zerops.yaml" - routing: - redirects: - - from: /* - to: /index.html - status: 302 - ``` - Use this configuration for Single Page Applications to ensure all routes are handled by your application. - -2. **Domain Migration** +1. **Domain Migration** ```yaml title="zerops.yaml" routing: redirects: @@ -336,20 +335,17 @@ This allows you to graduate to a more customizable setup while maintaining your ``` Use permanent (301) redirects when permanently moving content to maintain SEO value. -3. **Complex Redirects** - Order your redirects from most specific to most general to ensure proper routing: +2. **Complex Redirects** ```yaml title="zerops.yaml" routing: redirects: - from: /specific-path/* to: /specific-landing status: 302 - - from: /* - to: /index.html - status: 302 + # Additional specific redirects go here ``` -4. **Security Headers** +3. **Security Headers** Add security headers to protect your application: ```yaml title="zerops.yaml" routing: @@ -364,11 +360,11 @@ This allows you to graduate to a more customizable setup while maintaining your ## Frontend Framework Integration -The Static service seamlessly integrates with modern frontend frameworks. It can serve built static files from any framework while maintaining the option to add custom routing and Prerender.io integration if needed. +The Static service works with modern frontend frameworks. It can serve built static files from any framework with options for custom routing and Prerender.io integration if needed. ### Example: Analog App Deployment -Here's a simple configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): +Here's a configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): ```yaml title="zerops.yaml" zerops: @@ -390,7 +386,7 @@ This configuration: 3. Builds the application 4. Deploys the resulting static files to the Static service -You can enhance this basic setup by adding: +You can enhance this basic setup with: - Custom redirects for URL management - Prerender.io integration for SEO - Additional routing rules as needed @@ -429,11 +425,6 @@ run: - from: /api/* to: https://api.your-domain.com status: 302 - - # SPA fallback - - from: /* - to: /index.html - status: 302 ``` ### Security-Enhanced Configuration @@ -448,7 +439,4 @@ run: X-Content-Type-Options: "'nosniff' always" # Note the proper escaping of single quotes Content-Security-Policy: '"default-src ''self''" always' - redirects: - - from: /* - to: /index.html ``` \ No newline at end of file diff --git a/apps/docs/static/llms-full.txt b/apps/docs/static/llms-full.txt index 905cd07a..ac25d8cb 100644 --- a/apps/docs/static/llms-full.txt +++ b/apps/docs/static/llms-full.txt @@ -8165,15 +8165,20 @@ project: ### System-Generated Variables Zerops automatically generates project-level variables that can be [referenced](#referencing-variables) from services. ## Environment Variable Isolation -> A security feature that controls the visibility of environment variables across services within a project. +A security feature that controls the **visibility** of environment variables across services within a project. By default, Zerops isolates environment variables between services to enhance security and prevent unintended access to sensitive information. This isolation can be configured at both project and service levels. ### Isolation Modes Zerops supports two isolation modes: -| Mode | Description | -|-----------|-------------| -| `service` | **Default mode.** Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. | -| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | -| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | + + Mode + Description + + service + Default mode. Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. + + none + Legacy mode. All variables from all services are automatically shared and accessible via prefixing. + ### Configuring Isolation #### Project-Level Isolation Zerops automatically creates the `envIsolation` project variable with the default value `service`. You only need to modify this if you want to disable isolation: @@ -8193,7 +8198,7 @@ services: envSecrets: envIsolation: none # This service's variables will be visible to all services ``` -:::note +:::tip You might set a database service to `envIsolation: none` to expose its connection details to other services, without having to manually reference them, while keeping the rest of your services isolated. ::: ### Accessing Variables Across Services @@ -8216,7 +8221,7 @@ ${db_password} # Accesses the 'password' variable from the 'db' service ### Best Practices for Variable Isolation 1. **Use Default Isolation**: Keep the default `service` isolation for enhanced security. 2. **Explicit References**: Create explicit references only for variables that need to be shared. -3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g., `DB_PASSWORD` for a reference to `db_password`). +3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g. `DB_PASSWORD` for a reference to `db_password`). 4. **Service-Level Exceptions**: Use service-level isolation overrides sparingly and only for services that need to expose their variables widely. ## Variable Restrictions All environment variables must follow these restrictions: @@ -8245,21 +8250,20 @@ envVariables: ``` #### Across Services How this works depends on your environment variable isolation setting: -**With Isolation Enabled** (`service` mode - default): -1. Create an explicit reference in the destination service: +**With Isolation Enabled** (`service` mode - default) +* Create an explicit reference in the destination service: ```yaml # In the 'app' service envVariables: # Creating a reference to the 'connectionString' from 'dbtest' service dbConnection: ${dbtest_connectionString} ``` -**With Isolation Disabled** (`none` mode): -Variables from other services are automatically available using the service prefix format `servicename_variablename`: +**With Isolation Disabled** (`none` mode) +* Variables from other services are automatically injected into the container and available using the service prefix format `servicename_variablename`: ```yaml # In any container, you can directly access variables from other services: # ${dbtest_connectionString} ``` -You don't need to define these in your environment variables - they're automatically injected into the container. #### Between Build and Runtime Environments Build and runtime are two distinct environments in Zerops. Each environment can have its own set of variables, and you can use the same variable names in both environments since they are separate. Due to this separation, variables defined in one are not automatically accessible in the other. To share variables between environments, you need to use specific prefixes: @@ -8295,6 +8299,11 @@ Consider a project with three services: `api`, `db`, and `cache`: project: name: my-project services: + - hostname: api + envSecrets: + # Creating explicit references to needed variables + DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} + CACHE_URL: ${cache_hostname}:${cache_port} - hostname: db envSecrets: password: secureDbPassword @@ -8304,12 +8313,6 @@ services: envSecrets: password: cacheServerPass port: 6379 - - hostname: api - envSecrets: - # Creating explicit references to needed variables - DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} - CACHE_URL: ${cache_hostname}:${cache_port} - # Notice we didn't reference cache_password since we don't need it ``` With this setup: - The `api` service can only access the specific `db` and `cache` variables it explicitly references @@ -31073,7 +31076,7 @@ You can change the auto scaling parameters later. # Static > Overview -The Static service provides a streamlined way to serve static content through a pre-configured Nginx setup. It's designed to be simple to use while maintaining the flexibility needed for modern web applications. +The Static service provides a way to serve static content through a pre-configured Nginx setup. It balances simplicity with the flexibility needed for modern web applications. Deploy an Analog app with static hosting in seconds. All you need is a Zerops account. ## Quick Start @@ -31085,36 +31088,41 @@ zerops: os: alpine base: static ``` -The Static service comes with sensible defaults that work out of the box for most SPAs and static websites. By default, without any `routing` configuration, the service will: +## Default Behavior +Every Static service in Zerops comes with built-in defaults optimized for modern web applications, including Single Page Applications. By default, for any incoming request, the service will: 1. Try to serve the exact path (`$uri`) 2. Try with .html extension (`$uri.html`) 3. Look for an index.html in the directory (`$uri/index.html`) -4. Fall back to `/index.html` +4. Fall back to `/index.html` (suitable for SPAs) 5. Return 404 if none of the above exist -:::note Zero Configuration for SPAs -This means for basic SPA deployments or static file hosting, you don't need to specify any redirects at all! +:::important SPAs +Single Page Applications work out of the box without any additional configuration. The built-in fallback to `/index.html` ensures that client-side routing functions properly. ::: ## Routing Configuration -The Static service allows you to configure URL routing and redirects through a simple YAML configuration, abstracting away the complexity of Nginx configuration. -### Basic Structure -Configure routing in the `run.routing` section of your `zerops.yaml`: +The Static service allows you to configure additional URL routing and redirects through simple YAML configuration, abstracting away the complexity of Nginx configuration. +### Custom Routing Configuration +Configure custom routing beyond the default behavior in the `run.routing` section of your `zerops.yaml`: ```yaml title="zerops.yaml" run: routing: redirects: - - from: /* - to: /index.html + # Only needed for custom redirect scenarios + - from: /special-path/* + to: /specific-landing-page status: 302 ``` ### Redirect Types #### Relative Redirects +:::note +Remember that SPA routing is already built into the default behavior. You don't need to add any custom redirects for client-side routing to work. +::: Use relative redirects to route paths within your application. When both `from` and `to` are relative paths, you can omit the `status` code to create a masked redirect that shows the content of the target page while preserving the original URL: ```yaml title="zerops.yaml" routing: redirects: - # Masked redirect - URL stays the same but shows content from index.html - - from: /* - to: /index.html + # Masked redirect - URL stays the same but shows content from about-us + - from: /about + to: /about-us # Standard redirect with status code - from: /old-page to: /new-page @@ -31155,7 +31163,7 @@ routing: Use `*` as a wildcard in your paths: - **At the end of a path**: Matches any subsequent content - **At the start of a domain** (after `https://`): Enables regex matching for subdomains -Example of complex domain management: +Example of domain management: ```yaml title="zerops.yaml" run: routing: @@ -31173,7 +31181,7 @@ run: When multiple redirects are configured, they follow Nginx's matching priority system: 1. Exact matches are checked first 2. Simple path matches (without wildcards) are checked next -3. Pattern matches (with wildcards) are checked last, in the order they appear in your configuration +3. Pattern matches (with wildcards) are checked last For example: ```yaml title="zerops.yaml" routing: @@ -31190,17 +31198,14 @@ routing: to: /articles/ preservePath: true status: 302 - # Catch-all pattern - masked redirect for SPA - - from: /* - to: /index.html ``` In this configuration: - `/` will redirect to `/home` with a 302 status - `/about` will show content from `/about-us` but keep the URL as `/about` - `/blog/post-123.html` will redirect to `/articles/post-123.html` -- Any other path will show the content from `/index.html` while preserving the original URL (common for SPAs) +- Any other path will use the [default behavior](#default-behavior) ### CORS Configuration -You can easily enable CORS for your static service by adding a `cors` directive: +You can enable CORS for your static service by adding a `cors` directive: ```yaml title="zerops.yaml" run: routing: @@ -31209,11 +31214,16 @@ run: # Full syntax with proper quoting cors: "'*' always" ``` +The `cors` directive sets the following headers: +- `Access-Control-Allow-Origin` +- `Access-Control-Allow-Methods` +- `Access-Control-Allow-Headers` +- `Access-Control-Expose-Headers` :::note The `cors` directive has a special case: if you specify just `"*"`, it's automatically converted to `'*'`. For any other values, you need to include the proper Nginx syntax including quotes. ::: ### Custom Headers -For more fine-grained control over HTTP headers, use the `headers` directive: +For more control over HTTP headers, use the `headers` directive: ```yaml title="zerops.yaml" run: routing: @@ -31257,7 +31267,7 @@ add_header Content-Security-Policy "default-src 'self' https://cdn.example.com"; add_header Content-Security-Policy "default-src 'self' https://cdn.example.com; script-src 'self' 'unsafe-inline'; img-src * data:" always; ``` :::important Path Handling -When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same default behavior as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). +When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same [default behavior](#default-behavior) as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). If you add headers for a path that already has a location block, your headers will be merged with the existing configuration. ::: ### Combining CORS and Custom Headers @@ -31276,7 +31286,7 @@ The `cors` directive sets default Access-Control headers for all routes, while t If you specify Access-Control headers in the `headers` directive, they will override the ones set by `cors` for that specific path. ::: ## Prerender Integration -The Static service includes built-in support for Prerender.io, making it easy to implement server-side rendering for search engines and social media crawlers. +The Static service includes built-in support for Prerender.io for server-side rendering for search engines and social media crawlers. ### Basic Prerender Setup 1. Set the `PRERENDER_TOKEN` secret variable with your Prerender.io token 2. The service automatically configures necessary rewrites based on user agents @@ -31299,19 +31309,10 @@ If you need more control over your Nginx configuration: 4. Copy the generated Nginx configuration 5. Use this configuration as a starting point for a full Nginx service :::tip -This allows you to graduate to a more customizable setup while maintaining your existing routing logic. +This allows you to move to a more customizable setup while maintaining your existing routing logic. ::: ## Best Practices -1. **SPA Configuration** - ```yaml title="zerops.yaml" - routing: - redirects: - - from: /* - to: /index.html - status: 302 - ``` - Use this configuration for Single Page Applications to ensure all routes are handled by your application. -2. **Domain Migration** +1. **Domain Migration** ```yaml title="zerops.yaml" routing: redirects: @@ -31320,19 +31321,16 @@ This allows you to graduate to a more customizable setup while maintaining your status: 301 ``` Use permanent (301) redirects when permanently moving content to maintain SEO value. -3. **Complex Redirects** - Order your redirects from most specific to most general to ensure proper routing: +2. **Complex Redirects** ```yaml title="zerops.yaml" routing: redirects: - from: /specific-path/* to: /specific-landing status: 302 - - from: /* - to: /index.html - status: 302 + # Additional specific redirects go here ``` -4. **Security Headers** +3. **Security Headers** Add security headers to protect your application: ```yaml title="zerops.yaml" routing: @@ -31345,9 +31343,9 @@ This allows you to graduate to a more customizable setup while maintaining your Content-Security-Policy: '"default-src ''self''"' ``` ## Frontend Framework Integration -The Static service seamlessly integrates with modern frontend frameworks. It can serve built static files from any framework while maintaining the option to add custom routing and Prerender.io integration if needed. +The Static service works with modern frontend frameworks. It can serve built static files from any framework with options for custom routing and Prerender.io integration if needed. ### Example: Analog App Deployment -Here's a simple configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): +Here's a configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): ```yaml title="zerops.yaml" zerops: - setup: app @@ -31366,7 +31364,7 @@ This configuration: 2. Installs dependencies with pnpm 3. Builds the application 4. Deploys the resulting static files to the Static service -You can enhance this basic setup by adding: +You can enhance this basic setup with: - Custom redirects for URL management - Prerender.io integration for SEO - Additional routing rules as needed @@ -31400,10 +31398,6 @@ run: - from: /api/* to: https://api.your-domain.com status: 302 - # SPA fallback - - from: /* - to: /index.html - status: 302 ``` ### Security-Enhanced Configuration ```yaml title="zerops.yaml" @@ -31417,9 +31411,6 @@ run: X-Content-Type-Options: "'nosniff' always" # Note the proper escaping of single quotes Content-Security-Policy: '"default-src ''self''" always' - redirects: - - from: /* - to: /index.html ``` ---------------------------------------- diff --git a/apps/docs/static/llms-small.txt b/apps/docs/static/llms-small.txt index 5de21679..e16ee7d7 100644 --- a/apps/docs/static/llms-small.txt +++ b/apps/docs/static/llms-small.txt @@ -7984,15 +7984,20 @@ project: ### System-Generated Variables Zerops automatically generates project-level variables that can be [referenced](#referencing-variables) from services. ## Environment Variable Isolation -> A security feature that controls the visibility of environment variables across services within a project. +A security feature that controls the **visibility** of environment variables across services within a project. By default, Zerops isolates environment variables between services to enhance security and prevent unintended access to sensitive information. This isolation can be configured at both project and service levels. ### Isolation Modes Zerops supports two isolation modes: -| Mode | Description | -|-----------|-------------| -| `service` | **Default mode.** Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. | -| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | -| `none` | Legacy mode. All variables from all services are automatically shared and accessible via prefixing. | + + Mode + Description + + service + Default mode. Variables are isolated to their respective services. Services can only access their own variables and must explicitly reference variables from other services. + + none + Legacy mode. All variables from all services are automatically shared and accessible via prefixing. + ### Configuring Isolation #### Project-Level Isolation Zerops automatically creates the `envIsolation` project variable with the default value `service`. You only need to modify this if you want to disable isolation: @@ -8012,7 +8017,7 @@ services: envSecrets: envIsolation: none # This service's variables will be visible to all services ``` -:::note +:::tip You might set a database service to `envIsolation: none` to expose its connection details to other services, without having to manually reference them, while keeping the rest of your services isolated. ::: ### Accessing Variables Across Services @@ -8035,7 +8040,7 @@ ${db_password} # Accesses the 'password' variable from the 'db' service ### Best Practices for Variable Isolation 1. **Use Default Isolation**: Keep the default `service` isolation for enhanced security. 2. **Explicit References**: Create explicit references only for variables that need to be shared. -3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g., `DB_PASSWORD` for a reference to `db_password`). +3. **Naming Conventions**: Use clear naming patterns for reference variables (e.g. `DB_PASSWORD` for a reference to `db_password`). 4. **Service-Level Exceptions**: Use service-level isolation overrides sparingly and only for services that need to expose their variables widely. ## Variable Restrictions All environment variables must follow these restrictions: @@ -8064,21 +8069,20 @@ envVariables: ``` #### Across Services How this works depends on your environment variable isolation setting: -**With Isolation Enabled** (`service` mode - default): -1. Create an explicit reference in the destination service: +**With Isolation Enabled** (`service` mode - default) +* Create an explicit reference in the destination service: ```yaml # In the 'app' service envVariables: # Creating a reference to the 'connectionString' from 'dbtest' service dbConnection: ${dbtest_connectionString} ``` -**With Isolation Disabled** (`none` mode): -Variables from other services are automatically available using the service prefix format `servicename_variablename`: +**With Isolation Disabled** (`none` mode) +* Variables from other services are automatically injected into the container and available using the service prefix format `servicename_variablename`: ```yaml # In any container, you can directly access variables from other services: # ${dbtest_connectionString} ``` -You don't need to define these in your environment variables - they're automatically injected into the container. #### Between Build and Runtime Environments Build and runtime are two distinct environments in Zerops. Each environment can have its own set of variables, and you can use the same variable names in both environments since they are separate. Due to this separation, variables defined in one are not automatically accessible in the other. To share variables between environments, you need to use specific prefixes: @@ -8114,6 +8118,11 @@ Consider a project with three services: `api`, `db`, and `cache`: project: name: my-project services: + - hostname: api + envSecrets: + # Creating explicit references to needed variables + DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} + CACHE_URL: ${cache_hostname}:${cache_port} - hostname: db envSecrets: password: secureDbPassword @@ -8123,12 +8132,6 @@ services: envSecrets: password: cacheServerPass port: 6379 - - hostname: api - envSecrets: - # Creating explicit references to needed variables - DB_CONNECTION: ${db_user}:${db_password}@${db_hostname}:${db_port} - CACHE_URL: ${cache_hostname}:${cache_port} - # Notice we didn't reference cache_password since we don't need it ``` With this setup: - The `api` service can only access the specific `db` and `cache` variables it explicitly references @@ -27665,7 +27668,7 @@ You can change the auto scaling parameters later. # Static > Overview -The Static service provides a streamlined way to serve static content through a pre-configured Nginx setup. It's designed to be simple to use while maintaining the flexibility needed for modern web applications. +The Static service provides a way to serve static content through a pre-configured Nginx setup. It balances simplicity with the flexibility needed for modern web applications. Deploy an Analog app with static hosting in seconds. All you need is a Zerops account. ## Quick Start @@ -27677,36 +27680,41 @@ zerops: os: alpine base: static ``` -The Static service comes with sensible defaults that work out of the box for most SPAs and static websites. By default, without any `routing` configuration, the service will: +## Default Behavior +Every Static service in Zerops comes with built-in defaults optimized for modern web applications, including Single Page Applications. By default, for any incoming request, the service will: 1. Try to serve the exact path (`$uri`) 2. Try with .html extension (`$uri.html`) 3. Look for an index.html in the directory (`$uri/index.html`) -4. Fall back to `/index.html` +4. Fall back to `/index.html` (suitable for SPAs) 5. Return 404 if none of the above exist -:::note Zero Configuration for SPAs -This means for basic SPA deployments or static file hosting, you don't need to specify any redirects at all! +:::important SPAs +Single Page Applications work out of the box without any additional configuration. The built-in fallback to `/index.html` ensures that client-side routing functions properly. ::: ## Routing Configuration -The Static service allows you to configure URL routing and redirects through a simple YAML configuration, abstracting away the complexity of Nginx configuration. -### Basic Structure -Configure routing in the `run.routing` section of your `zerops.yaml`: +The Static service allows you to configure additional URL routing and redirects through simple YAML configuration, abstracting away the complexity of Nginx configuration. +### Custom Routing Configuration +Configure custom routing beyond the default behavior in the `run.routing` section of your `zerops.yaml`: ```yaml title="zerops.yaml" run: routing: redirects: - - from: /* - to: /index.html + # Only needed for custom redirect scenarios + - from: /special-path/* + to: /specific-landing-page status: 302 ``` ### Redirect Types #### Relative Redirects +:::note +Remember that SPA routing is already built into the default behavior. You don't need to add any custom redirects for client-side routing to work. +::: Use relative redirects to route paths within your application. When both `from` and `to` are relative paths, you can omit the `status` code to create a masked redirect that shows the content of the target page while preserving the original URL: ```yaml title="zerops.yaml" routing: redirects: - # Masked redirect - URL stays the same but shows content from index.html - - from: /* - to: /index.html + # Masked redirect - URL stays the same but shows content from about-us + - from: /about + to: /about-us # Standard redirect with status code - from: /old-page to: /new-page @@ -27747,7 +27755,7 @@ routing: Use `*` as a wildcard in your paths: - **At the end of a path**: Matches any subsequent content - **At the start of a domain** (after `https://`): Enables regex matching for subdomains -Example of complex domain management: +Example of domain management: ```yaml title="zerops.yaml" run: routing: @@ -27765,7 +27773,7 @@ run: When multiple redirects are configured, they follow Nginx's matching priority system: 1. Exact matches are checked first 2. Simple path matches (without wildcards) are checked next -3. Pattern matches (with wildcards) are checked last, in the order they appear in your configuration +3. Pattern matches (with wildcards) are checked last For example: ```yaml title="zerops.yaml" routing: @@ -27782,17 +27790,14 @@ routing: to: /articles/ preservePath: true status: 302 - # Catch-all pattern - masked redirect for SPA - - from: /* - to: /index.html ``` In this configuration: - `/` will redirect to `/home` with a 302 status - `/about` will show content from `/about-us` but keep the URL as `/about` - `/blog/post-123.html` will redirect to `/articles/post-123.html` -- Any other path will show the content from `/index.html` while preserving the original URL (common for SPAs) +- Any other path will use the [default behavior](#default-behavior) ### CORS Configuration -You can easily enable CORS for your static service by adding a `cors` directive: +You can enable CORS for your static service by adding a `cors` directive: ```yaml title="zerops.yaml" run: routing: @@ -27801,11 +27806,16 @@ run: # Full syntax with proper quoting cors: "'*' always" ``` +The `cors` directive sets the following headers: +- `Access-Control-Allow-Origin` +- `Access-Control-Allow-Methods` +- `Access-Control-Allow-Headers` +- `Access-Control-Expose-Headers` :::note The `cors` directive has a special case: if you specify just `"*"`, it's automatically converted to `'*'`. For any other values, you need to include the proper Nginx syntax including quotes. ::: ### Custom Headers -For more fine-grained control over HTTP headers, use the `headers` directive: +For more control over HTTP headers, use the `headers` directive: ```yaml title="zerops.yaml" run: routing: @@ -27849,7 +27859,7 @@ add_header Content-Security-Policy "default-src 'self' https://cdn.example.com"; add_header Content-Security-Policy "default-src 'self' https://cdn.example.com; script-src 'self' 'unsafe-inline'; img-src * data:" always; ``` :::important Path Handling -When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same default behavior as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). +When you specify headers for a path that doesn't have an existing location block, the Static service automatically creates a location with the same [default behavior](#default-behavior) as the root path (trying files in order: `$uri`, `$uri.html`, `$uri/index.html`, `/index.html` or returning 404). If you add headers for a path that already has a location block, your headers will be merged with the existing configuration. ::: ### Combining CORS and Custom Headers @@ -27868,7 +27878,7 @@ The `cors` directive sets default Access-Control headers for all routes, while t If you specify Access-Control headers in the `headers` directive, they will override the ones set by `cors` for that specific path. ::: ## Prerender Integration -The Static service includes built-in support for Prerender.io, making it easy to implement server-side rendering for search engines and social media crawlers. +The Static service includes built-in support for Prerender.io for server-side rendering for search engines and social media crawlers. ### Basic Prerender Setup 1. Set the `PRERENDER_TOKEN` secret variable with your Prerender.io token 2. The service automatically configures necessary rewrites based on user agents @@ -27891,19 +27901,10 @@ If you need more control over your Nginx configuration: 4. Copy the generated Nginx configuration 5. Use this configuration as a starting point for a full Nginx service :::tip -This allows you to graduate to a more customizable setup while maintaining your existing routing logic. +This allows you to move to a more customizable setup while maintaining your existing routing logic. ::: ## Best Practices -1. **SPA Configuration** - ```yaml title="zerops.yaml" - routing: - redirects: - - from: /* - to: /index.html - status: 302 - ``` - Use this configuration for Single Page Applications to ensure all routes are handled by your application. -2. **Domain Migration** +1. **Domain Migration** ```yaml title="zerops.yaml" routing: redirects: @@ -27912,19 +27913,16 @@ This allows you to graduate to a more customizable setup while maintaining your status: 301 ``` Use permanent (301) redirects when permanently moving content to maintain SEO value. -3. **Complex Redirects** - Order your redirects from most specific to most general to ensure proper routing: +2. **Complex Redirects** ```yaml title="zerops.yaml" routing: redirects: - from: /specific-path/* to: /specific-landing status: 302 - - from: /* - to: /index.html - status: 302 + # Additional specific redirects go here ``` -4. **Security Headers** +3. **Security Headers** Add security headers to protect your application: ```yaml title="zerops.yaml" routing: @@ -27937,9 +27935,9 @@ This allows you to graduate to a more customizable setup while maintaining your Content-Security-Policy: '"default-src ''self''"' ``` ## Frontend Framework Integration -The Static service seamlessly integrates with modern frontend frameworks. It can serve built static files from any framework while maintaining the option to add custom routing and Prerender.io integration if needed. +The Static service works with modern frontend frameworks. It can serve built static files from any framework with options for custom routing and Prerender.io integration if needed. ### Example: Analog App Deployment -Here's a simple configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): +Here's a configuration for deploying an [Analog application](https://github.com/zeropsio/recipe-analog-static): ```yaml title="zerops.yaml" zerops: - setup: app @@ -27958,7 +27956,7 @@ This configuration: 2. Installs dependencies with pnpm 3. Builds the application 4. Deploys the resulting static files to the Static service -You can enhance this basic setup by adding: +You can enhance this basic setup with: - Custom redirects for URL management - Prerender.io integration for SEO - Additional routing rules as needed @@ -27992,10 +27990,6 @@ run: - from: /api/* to: https://api.your-domain.com status: 302 - # SPA fallback - - from: /* - to: /index.html - status: 302 ``` ### Security-Enhanced Configuration ```yaml title="zerops.yaml" @@ -28009,9 +28003,6 @@ run: X-Content-Type-Options: "'nosniff' always" # Note the proper escaping of single quotes Content-Security-Policy: '"default-src ''self''" always' - redirects: - - from: /* - to: /index.html ``` ----------------------------------------