# Use an Object Storage Bucket as Origin

import DocButton from '~/components/webkit/DocButton.vue';
import Tabs from '~/components/tabs/Tabs'

import Code from '~/components/Code/Code.astro'
import Apiv4Rollout from '~/includes/snippets/apiv4Rollout/en/snippet.mdx'

<Apiv4Rollout />

This guide walks you through setting a bucket as origin of an applications using the [Azion API](https://api.azion.com/), [Azion CLI](/en/documentation/products/azion-cli/overview/), and [Azion Runtime](/en/documentation/runtime/api-reference/storage/).

<DocButton href="/en/documentation/products/store/object-storage/" label="go to Object Storage reference" kind="secondary" target="_blank" size="medium" />

There are separate instructions for API v3 using [legacy Origin](/en/documentation/products/build/applications/domains/) settings and API v4 using the new [Connector](/en/documentation/products/secure/connectors) product.

:::tip
In this guide, there are separate instructions for API v3 and API v4. If you're not sure which steps apply to your account, see [the Verify Your Account Migration guide](/en/documentation/products/guides/verify-account-migration/) to determine if your account has already been migrated.
:::

---


## Create a bucket and upload files

This section describes how you can upload objects to a bucket and maintain project structure using the [Azion API](https://api.azion.com). In this scenario, you'll create a static application using two files, distributed into folders as follows:

<Code lang="txt" code={`src/index.html
src/styles/style.css
`} />

1. Create the following `index.html` file inside of a local `src` directory:

<Code lang="html" code={`<!-- src/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="styles/style.css">
</head>
<body>
    <h1>Hello world!</h1>
    <p>I am an object from a bucket.</p>
</body>
</html>
`} />

2. Now create the `style.css` file, which is referenced in the HTML, under the `styles` folder in the same directory:

<Code lang="css" code={`/* src/styles/style.css */
body {
background-color: black;
}

h1, p {
    color: #F3652B;
}
`} />

3. Run the following `POST` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/) and writing the desired bucket name in `name` to create a read-only bucket:

<Code lang="bash" code={`curl --location 'https://api.azion.com/v4/storage/buckets' \
--header 'Accept: application/json;' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token [TOKEN VALUE]' \
--data '{
    "name": "app-origin",
    "edge_access": "read_only"
}'
`} />

4. You should receive the following response:

<Code lang="json" code={`{
  "state": "executed",
  "data": {
    "name": "app-origin",
    "edge_access": "read_only"
  }
}
`} />

5. Run the following `POST` requests in your terminal for each file, replacing `<bucket_name>` with the name of the bucket you just created:

    - For the `index.html` file, run the following command using `src/index.html` as the object key, and adding the object path as data:

<Code lang="bash" code={`curl --location 'https://api.azion.com/v4/storage/buckets/<bucket_name>/objects/src/index.html' \
--header 'Accept: application/json;' \
--header 'Content-Type: text/html' \
--header 'Authorization: Token [TOKEN VALUE]' \
--data '@./src/index.html'
`} />

    - For the `styles.css` file, run the following command using `src/styles/style.css` as the object key, and adding the object path as data:

<Code lang="bash" code={`curl --location 'https://api.azion.com/v4/storage/buckets/<bucket_name>/objects/src/styles/style.css' \
--header 'Accept: application/json;' \
--header 'Content-Type: text/css' \
--header 'Authorization: Token [TOKEN VALUE]' \
--data '@./src/styles/style.css'
`} />

6. You should receive the following responses for the files:

<Code lang="json" code={`{
    "state": "executed",
    "data": {
        "object_key": "src/index.html"
    }
}
`} />

<Code lang="json" code={`{
    "state": "executed",
    "data": {
        "object_key": "src/styles/style.css"
    }
}
`} />

:::caution[Warning]
When a bucket is configured with **read-write permissions**, any user can access and modify its content (for example, by sending a PUT request to overwrite files). If the bucket is used as an origin for an applications, this configuration may expose the content to unauthorized modifications. However, suppose the bucket is accessed through an function. In that case, the risk is managed by the logic implemented in the function code, allowing developers to enforce stricter controls over who can access or modify the data. To mitigate risks, always verify the required permissions for each use case and implement proper access controls. Read more on [Authentication and permissions](/en/documentation/products/store/object-storage/#authentication-and-permissions).
:::

---

## Create an applications and set origin type to Object Storage

Now that your bucket is populated with files, you can create a new applications and a domain to set the bucket as the origin of the content and serve these objects.

<Tabs client:visible>
    <Fragment slot="tab.consoleedgeconnector">Console - Connectors</Fragment>
    <Fragment slot="tab.consoleorigins">Console - Origins</Fragment>
    <Fragment slot="tab.apiv4">API v4</Fragment>
    <Fragment slot="tab.apiv3">API v3</Fragment>
    <Fragment slot="tab.cli">CLI </Fragment>


<Fragment slot="panel.consoleedgeconnector">
To facilitate this process, use the [Applications Proxy](/en/documentation/products/guides/edge-application-proxy-template/) template:

1. Access [Azion Console](https://console.azion.com).
    - If you don't have an account yet, create a new one [by visiting the sign-up page](https://console.azion.com/signup).
2. On the homepage, select the **+ Create** option.
3. Find the **Applications Proxy** card in the templates section and select it.
4. Give your application an easy-to-remember name.
5. In **Route to bypass**, type `/` to specify the root path of the application.
6. Wait for the deployment process to finish.
7. Copy the domain of the application, in the format `http://xxxxxxxxxx.map.azionedge.net/`.

:::note
The link to the applications allows you to see it on the browser. However, it takes a certain time to propagate and configure the application in Azion’s edge locations. It may be necessary to wait a few minutes for the URL to be activated and for the application page to be effectively displayed in the browser.
:::

Now you need to configure a new **Connector** to link your application to your Object Storage bucket. To do so:

1. [Access Azion Console](/en/documentation/products/guides/how-to-access-azion-console/) > **Connectors**.
2. Click the **+ Connector** button.
3. In the **General** section, give your connector a unique and descriptive name (e.g., `My Object Storage Connector`).
4. In the **Connector Type** section, select **Object Storage**.
5. In the **Connection Options** section:
    - For **Bucket**, select the name of the bucket you created in the previous steps. The bucket selector lists your existing buckets and provides a search field.
    - For **Prefix**, enter `/src` (or the prefix you used when uploading your objects).
6. Set the **Status** to **Active**.
7. Click the **Save** button.

To activate the Connector in your applications:

1. Access the **Rules Engine** tab.
2. Edit the default rule or add a new request rule.
3. In the **Criteria** section, to apply the Connector for your whole application, set the **criteria** to `If ${uri} starts with /`.
4. In the **Behavior** section, select the Set Connector behavior.
5. Select the Connector you want to apply.
6. Click the **Save** button.
7. Wait some time for the changes to propagate to the edge.

Once the changes have been made, access `http://xxxxxxxxxx.map.azionedge.net/index.html` to see the HTML file you uploaded with the applied CSS style.
</Fragment>

<Fragment slot="panel.consoleorigins">

:::caution
Using Object Storage as an origin directly in **Applications > Origins** is a legacy flow. For migrated accounts, the official and recommended configuration is via **Connectors** and the **Set Connector** behavior.
:::
To facilitate this process, use the [Applications Proxy](/en/documentation/products/guides/edge-application-proxy-template/) template:

1. Access [Azion Console](https://console.azion.com).
    - If you don't have an account yet, create a new one [by visiting the sign-up page](https://console.azion.com/signup).
2. On the homepage, select the **+ Create** option.
3. Find the **Applications Proxy** card in the templates section and select it.
4. Give your application an easy-to-remember name.
5. In **Origin Address**, type `httpbin.org`. 
    - This is a temporary origin that will later be replaced with an Object Storage origin.
6. In **Route to bypass**, type `/` to specify the root path of the application.
7. Wait for the deployment process to finish.
8. Copy the domain of the application, in the format `http://xxxxxxxxxx.map.azionedge.net/`.

:::note
The link to the applications allows you to see it on the browser. However, it takes a certain time to propagate and configure the application in Azion’s edge locations. It may be necessary to wait a few minutes for the URL to be activated and for the application page to be effectively displayed in the browser.
:::

Now you need to configure a new **Object Storage** origin and determine that your application should retrieve content from the bucket and prefix you created. To do so:

1. [Access Azion Console](/en/documentation/products/guides/how-to-access-azion-console/) > **Applications**.
2. Click the proxy application you created in the previous steps.
3. Navigate to the **Origins** tab.
4. Click the **+ Origin** button.
5. Give your origin an easy-to-remember name.
6. In **Origin Type**, select **Object Storage**.
7. In **Bucket Name**, add the name of the bucket you created in the previous steps.
8. In **Prefix**, add `/src`, which is the prefix you added to the object keys uploaded previously.
9. Click the **Save** button.

To activate the origin in your applications:

10. Navigate to the **Rules Engine** tab.
11. Select the **Default Rule**.
12. Under **Behaviors**, in the **Set Origin** behavior, replace the **Default Origin** with the origin you created for your bucket.
13. Click the **Save** button.
14. Wait some time for the changes to propagate to the edge.

Once the changes have been made, access `http://xxxxxxxxxx.map.azionedge.net/index.html` to see the HTML file you uploaded with the applied CSS style.
</Fragment>

<Fragment slot="panel.apiv4">
1. Run the following `POST` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/):

<Code lang="bash" code={`curl --request POST \
  --url https://api.azion.com/v4/edge_application/applications \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "object storage app",
  "modules": {
    "edge_cache": {
      "enabled": true
    },
    "edge_functions": {
      "enabled": true
    },
    "application_accelerator": {
      "enabled": false
    },
    "image_processor": {
      "enabled": false
    },
    "tiered_cache": {
      "enabled": false
    }
  },
  "active": true,
  "debug": false
}'`} />




2. You should receive a response similar to:

<Code lang="json" code={`{
  "state": "pending",
  "data": {
    "id": "edge_application_id",
    "name": "object storage app",
    "last_editor": "education1@azion.com",
    "last_modified": "2025-07-25T19:06:13.854005Z",
    "modules": {
      "edge_cache": {
        "enabled": true
      },
      "edge_functions": {
        "enabled": true
      },
      "application_accelerator": {
        "enabled": false
      },
      "image_processor": {
        "enabled": false
      },
      "tiered_cache": {
        "enabled": false
      }
    },
    "active": true,
    "debug": false,
    "product_version": "3.0"
  }
}`} />

3. Copy the value from the `edge_application_id` field and paste it in a text editing app to save it for later requests.

4. Run the following `POST` request in your terminal to create an Connector, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/)

<Code lang="bash" code={`curl --request POST \
  --url https://api.azion.com/v4/edge_connector/connectors \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "object storage connector",
  "active": true,
  "type": "edge_storage",
  "attributes": {
    "bucket": "app-origin",
    "prefix": "/"
  }
}'
`} />

5. Copy the value from the `<connector_id>` field and paste it in a text editing app to save it for later requests.

6. You should receive a response similar to:

<Code lang="json" code={`{
  "id": "<connector_id>",
  "name": "object storage connector",
  "last_editor": "your-email@example.com",
  "last_modified": "2025-07-22T14:34:31.009649Z",
  "active": true,
  "product_version": "1.0",
  "type": "edge_storage",
  "attributes": {
    "bucket": "app-origin",
    "prefix": "/"
  }
}`} />

7. Run the following `POST` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/)

<Code lang="bash" code={`curl --request POST \
  --url https://api.azion.com/v4/workspace/workloads \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "object storage domain",
  "active": true,
  "infrastructure": 1,
  "protocols": {
    "http": {
      "versions": [
        "http1",
        "http2"
      ]
    }
  },
  "workload_domain_allow_access": true
}'`} />

8. You should receive a response similar to:

<Code lang="json" code={`{
  "state": "pending",
  "data": {
    "id": "workload_id",
    "name": "object storage domain",
    "active": true,
    "last_editor": "your-email@example.com",
    "last_modified": "2025-07-25T18:58:25.817955Z",
    "infrastructure": 1,
    "tls": {
      "certificate": null,
      "ciphers": 7,
      "minimum_version": "tls_1_3"
    },
    "protocols": {
      "http": {
        "versions": [
          "http1",
          "http2"
        ],
        "http_ports": [
          80
        ],
        "https_ports": [
          443
        ],
        "quic_ports": null
      }
    },
    "mtls": {
      "verification": null,
      "certificate": null,
      "crl": null
    },
    "domains": [],
    "workload_domain_allow_access": true,
    "workload_domain": "xxxxxxxxxxx.azionedge.net",
    "product_version": "1.0"
  }
}`} />

9. Copy the URL in the `workload_domain` value and paste it in a text editing app to access later. 

10. Run the following `POST` request to bind the Workload to your Applications, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/), `<edge_application_id>` with the ID of the applications and `<workload_id>` with the id of the Workload.

<Code lang="bash" code={`curl --request POST \
  --url https://api.azion.com/v4/workspace/workloads/<workload_id>/deployments \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "Object Storage App",
  "current": true,
  "active": true,
  "strategy": {
    "type": "default",
    "attributes": {
      "edge_application": "<edge_application_id>"
    }
  }
}'`} />


11. Run the following `POST` request in your terminal to create a **Rules Engine** rule, replacing `<edge_application_id>` variable with the Applications ID and `<connector_id>`with the Connector ID you copied previously:

<Code lang="bash" code={`curl --request POST \
  --url https://api.azion.com/v4/edge_application/applications/<edge_application_id>/request_rules \
  --header 'Accept: application/json' \
  --header 'Authorization: Token [TOKEN VALUE]' \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "string",
  "active": true,
  "criteria":
    [
      {
        "conditional": "if",
        "variable": "\${uri}",
        "operator": "starts_with",
        "argument": "/"
      }
    ]
  ],
  "behaviors": [
    {
      "type": "set_edge_connector",
      "attributes": {
        "value": "<connector_id>"
      }
    }
  ]
}'
`} />

12. You should receive a response similar to:

<Code lang="json" code={`{
  "state": "pending",
  "data": {
    "id": "<rule_id>",
    "name": "string",
    "active": true,
    "criteria": [
      [
        {
          "conditional": "if",
          "variable": "\${uri}",
          "operator": "starts_with",
          "argument": "/"
        }
      ]
    ],
    "behaviors": [
      {
        "type": "set_edge_connector",
        "attributes": {
          "value": "<connector_id>"
        }
      }
    ],
    "description": "",
    "order": 1,
    "last_editor": "your-email@example.com",
    "last_modified": "2025-07-25T19:29:30.684210Z"
  }
}`} />



13. Wait some time for the changes to propagate.

Once the changes have been made, access the domain you created, in the format `http://xxxxxxxxxx.map.azionedge.net/index.html`, to see the HTML file you uploaded with the applied CSS style.

</Fragment>

<Fragment slot="panel.apiv3">
1. Run the following `POST` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/):

<Code lang="bash" code={`curl --location 'https://api.azionapi.net/edge_applications' \
--header 'Accept: application/json;' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
    "name": "object storage app",
    "delivery_protocol": "http",
    "http3": false,
    "origin_type": "single_origin",
    "address": "httpbin.org",
    "origin_protocol_policy": "preserve",
    "host_header": "\${host}",
    "browser_cache_settings": "honor",
    "browser_cache_settings_maximum_ttl": 0,
    "cdn_cache_settings": "override",
    "cdn_cache_settings_maximum_ttl": 0
}'`} />

2. You should receive a response similar to:

<Code lang="json" code={`{
    "results": {
        "id": "<edge_application_id>",
        "name": "object storage app",
        "delivery_protocol": "http"
        ...
    },
    "schema_version": 3
}`} />

3. Copy the value from the `edge_application_id` field and paste it in a text editing app to save it for later requests.
4. Run the following `POST` request in your terminal, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/) and `<edge_application_id>` with the ID of the applications you created:

<Code lang="bash" code={`curl --location 'https://api.azionapi.net/domains' \
--header 'Accept: application/json;' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
    "name": "object storage domain",
    "cname_access_only": false,
    "digital_certificate_id": null,
    "edge_application_id": "<edge_application_id>"
}'`} />

5. You should receive a response similar to:

<Code lang="json" code={`{
    "results": {
        "id": "<domain_id>",
        "name": "object storage domain",
        ...
        "edge_application_id": "<edge_application_id>",
        "is_active": true,
        "domain_name": "xxxxxxxxxx.map.azionedge.net",
        ...
    },
    "schema_version": 3
}`} />

6. Copy the URL in the `domain_name` value and paste it in a text editing app to access later. 
7. Run the following `POST` request to create an object storage origin for the application, replacing `[TOKEN VALUE]` with your [personal token](/en/documentation/products/guides/personal-tokens/), `<edge_application_id>` with the ID of the applications, and the value of `bucket` with the name of the bucket you created:

<Code lang="bash" code={`curl --location 'https://api.azionapi.net/edge_applications/<edge_application_id>/origins' \
--header 'Accept: application/json;' \
--header 'Authorization: Token [TOKEN VALUE]' \
--header 'Content-Type: application/json' \
--data '{
    "name": "object storage origin",
    "origin_type": "object_storage",
    "bucket": "app-origin",
    "prefix": "/src"
}'`} />

8. You should receive a response similar to:

<Code lang="json" code={`{
  "results": {
    "origin_id": "<origin_id>",
    "origin_key": "bdcd7003-ba53-4ed8-8ca0-05b1357cdafd",
    "name": "New Object Storage origin",
    "origin_type": "object_storage",
    ...
    "bucket": "new-bucket-rw",
    "prefix": "/"
  },
  "schema_version": 3
}`} />

9. Copy the value from the `origin_id` field and paste it in a text editing app to save it for later requests.
10. Run the following `GET` request in your terminal to retrieve the ID of the default rule of your applications's **Rules Engine**, replacing `<edge_application_id>` variable with the applications ID you copied previously:

<Code lang="bash" code={`curl --location 'https://api.azionapi.net/edge_applications/<edge_application_id>/rules_engine/request/rules' \
--header 'Accept: application/json;' \
--header 'Authorization: Token [TOKEN VALUE]'
`} />

11. You should receive a response similar to:

<Code lang="json" code={`{
    ...
    "results": [
        {
            "id": "<rule_id>",
            "name": "Default Rule",
            "phase": "default",
            "behaviors": [
                {
                    "name": "set_origin",
                    "target": "<origin_id>"
                },
                {
                    "name": "set_cache_policy",
                    "target": "<cache_setting_id>"
                }
            ],
            ...
            "description": ""
        }
    ]
}`} />

12. Copy the value from the `rule_id` field and paste it in a text editing app to save it for later requests.
13. Run the following `PATCH` request to modify the default rule, replacing `<rule_id>` with the ID of the rule you retrieved in the previous step, leaving the `set_cache_policy` object the same as received in the response:

<Code lang="bash" code={`curl --location --request PATCH 'https://api.azionapi.net/edge_applications/<edge_application_id>/rules_engine/request/rules/<rule_id>' \
--header 'Accept: application/json;' \
--header 'Content-Type: application/json' \
--header 'Authorization: Token [TOKEN VALUE]' \
--data '{
    "behaviors": [
        {
            "name": "set_origin",
            "target": "<origin_id>"
        },
        {
            "name": "set_cache_policy",
            "target": "<cache_setting_id>"
        }
    ]
}'`} />

14. Wait some time for the changes to propagate.

Once the changes have been made, access the domain you created, in the format `http://xxxxxxxxxx.map.azionedge.net/index.html`, to see the HTML file you uploaded with the applied CSS style.

</Fragment>

<Fragment slot="panel.cli">
## Requirements 

- [Azion CLI installed](/en/documentation/products/azion-cli/overview/#installing-azion-cli). 
- [A personal token configured](/en/documentation/devtools/cli/globals/#token).

To create an applications with the necessary configurations to use a bucket as origin: 

<Code lang="bash" code={`azion create edge-application --name "object storage app" --delivery-protocol "http" --http3 false --origin-type "single_origin" --address "httpbin.org" --origin-protocol-policy "preserve" --host-header "\${host}" --browser-cache-settings "honor" --browser-cache-settings-maximum-ttl 0 --cdn-cache-settings "override" --cdn-cache-settings-maximum-ttl 0
`} />

</Fragment>


</Tabs>

:::tip
After creating your application with an Object Storage bucket as the origin, you can manage and configure settings, such as [cache settings](/en/documentation/products/guides/cache-settings/).
:::