Skip to content

Commit

Permalink
Fix Hugging Face Spaces permissions (#2925)
Browse files Browse the repository at this point in the history
* fix docs import

* fix CORS issue in docker file

* update user entries for CSP env var

* update docs
  • Loading branch information
strickvl authored Aug 16, 2024
1 parent e41b791 commit 65776bc
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docker/zenml-server-hf-spaces.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ FROM zenmldocker/zenml-server:latest
ENV ZENML_ANALYTICS_OPT_IN=true
ENV ZENML_SERVER_DEPLOYMENT_TYPE="hf_spaces"

# fixes iframe / CORS issue for HF deployments
ENV ZENML_SERVER_SECURE_HEADERS_CSP="frame-ancestors *;"

################################################################################
#
# CONFIGURING YOUR ZENML HF SPACES SERVER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ description: Deploying ZenML to Huggingface Spaces.
A quick way to deploy ZenML and get started is to use [HuggingFace Spaces](https://huggingface.co/spaces). HuggingFace Spaces is a platform for hosting and sharing ML projects and workflows, and it also works to deploy ZenML. You can be up and running in minutes (for free) with a hosted ZenML server, so it's a good option if you want to try out ZenML without any infrastructure overhead.

{% hint style="info" %}
Note that it is not recommended to use HuggingFace Spaces for production use as by default the data stored there is non-persistent and the underlying machine is not as available to you as a dedicated machine. See our [other deployment options](./README.md) if you want to use ZenML in production.
If you are planning to use HuggingFace Spaces for production use, make sure you have [persistent storage turned on](https://huggingface.co/docs/hub/en/spaces-storage) so as to prevent loss of data. See our [other deployment options](./README.md) if you want alternative options.
{% endhint %}

![ZenML on HuggingFace Spaces -- default deployment](../../../.gitbook/assets/hf\_spaces\_chart.png)
![ZenML on HuggingFace Spaces -- default deployment](../../.gitbook/assets/hf-spaces-chart.png)

In this diagram, you can see what the default deployment of ZenML on HuggingFace looks like.

Expand Down Expand Up @@ -48,10 +48,6 @@ zenml connect --url '<YOUR_HF_SPACES_DIRECT_URL>'

You can also use the Direct URL in your browser to use the ZenML dashboard as a fullscreen application (i.e. without the HuggingFace Spaces wrapper around it).

{% hint style="warning" %}
The ZenML dashboard will currently not work when viewed from within the Huggingface webpage (i.e. wrapped in the main `https://huggingface.co/...` website). This is on account of a limitation in how cookies are handled between ZenML and Huggingface. You **must** view the dashboard from the 'Direct URL' (see above).
{% endhint %}

## Extra configuration options

By default, the ZenML application will be configured to use an SQLite non-persistent database. If you want to use a persistent database, you can configure this by amending the `Dockerfile` to your Space's root directory. For full details on the various parameters you can change, see [our reference documentation](deploy-with-docker.md#advanced-server-configuration-options) on configuring ZenML when deployed with Docker.
Expand Down
30 changes: 30 additions & 0 deletions src/zenml/config/server_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,36 @@ def _validate_config(cls, data: Dict[str, Any]) -> Dict[str, Any]:
# Revert to the default value if the header is enabled
del data[k]

# Handle merging of user-defined secure_headers_csp value with the default value
if "secure_headers_csp" in data:
user_defined_csp = data["secure_headers_csp"]
if isinstance(user_defined_csp, str):
# Parse the user-defined CSP string into a dictionary
user_defined_csp_dict = {}
for directive in user_defined_csp.split(";"):
directive = directive.strip()
if directive:
key, value = directive.split(" ", 1)
user_defined_csp_dict[key] = value.strip("'\"")

# Merge the user-defined CSP dictionary with the default CSP dictionary
default_csp_dict = {}
for directive in DEFAULT_ZENML_SERVER_SECURE_HEADERS_CSP.split(
";"
):
directive = directive.strip()
if directive:
key, value = directive.split(" ", 1)
default_csp_dict[key] = value.strip("'\"")

merged_csp_dict = {**default_csp_dict, **user_defined_csp_dict}

# Convert the merged CSP dictionary back to a string
merged_csp_str = "; ".join(
f"{key} {value}" for key, value in merged_csp_dict.items()
)
data["secure_headers_csp"] = merged_csp_str

return data

@property
Expand Down

0 comments on commit 65776bc

Please sign in to comment.