# How to Enable the Spaces CDN Spaces Object Storage is an S3-compatible service for storing and serving large amounts of data. The built-in Spaces CDN minimizes page load times, improves performance, and reduces bandwidth and infrastructure costs. Spaces provides a built-in content delivery network (CDN), which is a network of edge servers that deliver content to users. Each point of presence (PoP), the location of a group of edge servers, sends content to users that are physically closest to it. CDNs help deliver static and dynamic online content faster and more reliably and provide a layer of redundancy for websites. The Spaces CDN is subject to the same [transfer charges](https://docs.digitalocean.com/products/spaces/details/pricing/index.html.md) as Spaces. **Note**: Spaces Cold Storage buckets do not support CDN integration or custom CDN endpoints. To use CDN caching or custom subdomains, create a Spaces Standard Storage bucket instead. For more information, see [Spaces Limits](https://docs.digitalocean.com/products/spaces/details/limits/index.html.md). You can enable the Spaces CDN either when [creating a new Space](https://docs.digitalocean.com/products/spaces/how-to/create/index.html.md#cdn) or on an existing Spaces bucket’s **Settings** tab, under the **CDN (Content Delivery Network)** section. Once you enable the Spaces CDN for a bucket, you can access the contents of that bucket using the edge URL `..cdn.digitaloceanspaces.com` in addition to the existing origin URL. You can also [customize the CDN endpoint](#setup-subdomain) with a secure subdomain you own. You can also [use presigned URLs with the Spaces CDN](https://docs.digitalocean.com/products/spaces/how-to/use-aws-sdks/index.html.md) by configuring your SDK or S3-compatible tool to use the non-CDN endpoint, generating a presigned URL for a `GetObject` request, and then modifying the hostname in the URL to use the CDN hostname (`..cdn.digitaloceanspaces.com`, unless the bucket uses a custom hostname). **Important**: Presigned URLs only work with the Spaces CDN when they use virtual-hosted–style URLs (for example, `https://..digitaloceanspaces.com/`). Presigned URLs generated using path-style URLs (for example, when `forcePathStyle: true` is enabled in an S3-compatible SDK) cannot be used with the CDN hostname. Requests made using presigned URLs aren’t cached by the Spaces CDN. Each request is forwarded to the Spaces origin, even when the request uses a CDN endpoint or custom domain. As a result, presigned URLs don’t benefit from reduced latency or cache hits. Using presigned URLs with the CDN is primarily useful for maintaining a consistent hostname or custom domain, not for improving performance. ## Enable CDN for a Bucket Using the Control Panel To enable CDN for a bucket, go to the [control panel](https://cloud.digitalocean.com/), in the left menu, click **Spaces Object Storage**, and then under the **Buckets** tab, click the bucket you want to enable CDN for. From the bucket’s overview page, click the **Settings** tab, and then under the **CDN (Content Delivery Network)** section, click **Edit**, and then click **Enable CDN**. Afterwards, click **Save** if the default edge cache TTL works for you and you do not need a custom subdomain, or [set up a custom subdomain](#setup-subdomain). The [**Edge Cache TTL**](https://docs.digitalocean.com/products/spaces/how-to/manage-cdn-cache/index.html.md#ttl) determines how long content is cached by the CDN’s edge servers before the current version is retrieved from the origin. You can keep the default of **1 hour** or choose another value. The default edge cache TTL provides a balance between performance and freshness. It allows frequently accessed content to benefit from CDN caching while ensuring updates propagate reasonably without requiring manual cache purges. A longer TTL improves performance but delays the visibility of updates until the cache expires. Use longer TTLs for static or infrequently changing content and shorter TTLs for dynamic content. You may also increase the TTL to handle anticipated traffic spikes. You can modify the edge cache TTL setting and custom subdomain at any time. ### Set Up a Custom Subdomain The CDN’s edge servers begin caching and serving the contents of the Spaces bucket from the default CDN endpoint, `..cdn.digitaloceanspaces.com`. Optionally, you can configure a secure subdomain you own as an alternative endpoint, such as `images.example.com`. For security, any subdomain you use with the Spaces CDN must have an SSL certificate. When you configure a custom endpoint, you can either create a new certificate during setup, upload an existing certificate during setup, or choose a certificate that is already uploaded to your DigitalOcean account. To add a custom subdomain, click **Add a New Subdomain** to open the **Add a custom subdomain** window. You can either create an SSL certificate with Let’s Encrypt or use your own certificate. - **Use Let’s Encrypt**. If you [manage your domain’s DNS with DigitalOcean](https://docs.digitalocean.com/products/networking/dns/index.html.md), you can create a free, fully managed SSL certificate with the Let’s Encrypt integration. - **Bring your own certificate**. If you host your domain’s DNS with another provider, you can manually create and upload a certificate. If you already have a certificate for the subdomain you want to use, select it from the menu and click **Save**. We automatically create a CNAME record if required and begin serving content from the custom subdomain. ## Use Let's Encrypt Under the **Use Let’s Encrypt** tab, enter the domain and subdomain you want to secure. Choose whether to secure all subdomains (wildcard), create a new subdomain, or use an existing one. DigitalOcean automatically configures the required DNS records and provisions the certificate. ## Bring Your Own Certificate Under the **Bring your own certificate** tab, enter a certificate name, then paste your certificate, private key, and certificate chain. After submitting the information, we generate the certificate and enable the custom subdomain. ### Edit or Remove a Custom Subdomain To edit or remove a custom subdomain, go to the [control panel](https://cloud.digitalocean.com/), click **Spaces Object Storage**, select the bucket, click the **Settings** tab, and then under **CDN (Content Delivery Network)** section, click **Edit**. To remove the subdomain and serve content only from the default CDN endpoint, click **Remove Custom Subdomain**, and then click **Confirm**. ## Enable CDN Using Automation You can enable the Spaces CDN for a bucket by creating a CDN endpoint whose origin points to the bucket’s Spaces origin URL via CLI (`doctl`) or the DigitalOcean API. Once enabled, the bucket is accessible from an edge URL such as `..cdn.digitaloceanspaces.com`, and you can optionally configure a custom domain secured with a DigitalOcean-managed TLS certificate. ### Enable CDN via the CLI To enable the CDN via the CLI, create a CDN endpoint with `doctl compute cdn create` and pass your bucket’s Spaces origin URL. ## How to Create a CDN Using the DigitalOcean CLI 1. [Install `doctl`](https://docs.digitalocean.com/reference/doctl/how-to/install/index.html.md), the official DigitalOcean CLI. 2. [Create a personal access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) and save it for use with `doctl`. 3. Use the token to grant `doctl` access to your DigitalOcean account. ```shell doctl auth init ``` 4. Finally, run `doctl compute cdn create`. Basic usage looks like this, but you can [read the usage docs](https://docs.digitalocean.com/reference/doctl/reference/compute/cdn/create/index.html.md) for more details: ```shell doctl compute cdn create [flags] ``` The following example creates a CDN for the custom domain `cdn.example.com` using a DigitalOcean Spaces origin endpoint and SSL certificate ID for the custom domain: ```shell doctl compute cdn create https://tester-two.blr1.digitaloceanspaces.com --domain cdn.example.com --certificate-id f81d4fae-7dec-11d0-a765-00a0c91e6bf6 ``` ### Enable CDN via the API To enable the CDN via the API, use the CDN endpoint with a Spaces origin by specifying your bucket’s Spaces origin URL (for example, `https://..digitaloceanspaces.com`) as the origin, and then send a `POST` request to `/v2/cdn/endpoints` with the `origin` field set to that URL. ## How to Create a New CDN Endpoint Using the DigitalOcean API 1. [Create a personal access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) and save it for use with the API. 2. Send a POST request to [`https://api.digitalocean.com/v2/cdn/endpoints`](https://docs.digitalocean.com/reference/api/digitalocean//index.html.md#operation/cdn_create_endpoint). ### cURL Using cURL: ```shell curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ -d '{"origin": "static-images.nyc3.digitaloceanspaces.com","certificate_id": "892071a0-bb95-49bc-8021-3afd67a210bf","custom_domain": "static.example.com","ttl": 3600}' \ "https://api.digitalocean.com/v2/cdn/endpoints" ``` ### Go Using [Godo](https://github.com/digitalocean/godo), the official DigitalOcean API client for Go: ```go import ( "context" "os" "github.com/digitalocean/godo" ) func main() { token := os.Getenv("DIGITALOCEAN_TOKEN") client := godo.NewFromToken(token) ctx := context.TODO() createRequest := &godo.CDNCreateRequest{ Origin: "static-images.nyc3.digitaloceanspaces.com", TTL: 3600, CustomDomain: "static.example.com", CertificateID: "892071a0-bb95-49bc-8021-3afd67a210b", } cdn, _, err := client.CDNs.Create(ctx, createRequest) } ``` ### Ruby Using [DropletKit](https://github.com/digitalocean/droplet_kit), the official DigitalOcean API client for Ruby: ```ruby require 'droplet_kit' token = ENV['DIGITALOCEAN_TOKEN'] client = DropletKit::Client.new(access_token: token) cdn = DropletKit::CDN.new( origin: 'static-images.nyc3.digitaloceanspaces.com', custom_domain: 'static.example.com', certificate_id: '892071a0-bb95-49bc-8021-3afd67a210bf', ttl: 3600 ) client.cdns.create(cdn) ``` ### Python Using [PyDo](https://github.com/digitalocean/pydo), the official DigitalOcean API client for Python: ```python import os from pydo import Client client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN")) create_req = {"origin": "static-images.nyc3.digitaloceanspaces.com", "ttl": 3600} create_resp = client.cdn.create_endpoint(create_req) ``` ## Disable CDN Using the Control Panel Disabling CDN removes cached files and certificates from edge servers but does not delete the bucket or its contents. To disable CDN, go to the bucket’s **Settings** tab, click **Edit**, under **CDN (Content Delivery Network)** sub-section, toggle off **Enable CDN**, and then click **Save**. ## Disable CDN Using Automation You can disable the Spaces CDN by deleting the CDN endpoint associated with the bucket via the CLI (`doctl`) or the DigitalOcean API. Disabling the CDN stops edge caching and removes the CDN URL. ### Disable CDN via the CLI To disable CDN via the CLI, first list CDN endpoints with `doctl compute cdn list` to find the CDN endpoint ID associated with the bucket. Then, delete the appropriate endpoint with the CDN endpoint ID. ## How to Delete a CDN Using the DigitalOcean CLI 1. [Install `doctl`](https://docs.digitalocean.com/reference/doctl/how-to/install/index.html.md), the official DigitalOcean CLI. 2. [Create a personal access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) and save it for use with `doctl`. 3. Use the token to grant `doctl` access to your DigitalOcean account. ```shell doctl auth init ``` 4. Finally, run `doctl compute cdn delete`. Basic usage looks like this, but you can [read the usage docs](https://docs.digitalocean.com/reference/doctl/reference/compute/cdn/delete/index.html.md) for more details: ```shell doctl compute cdn delete [flags] ``` The following example deletes a CDN with the ID `418b7972-fc67-41ea-ab4b-6f9477c4f7d8`: ```shell doctl compute cdn delete 418b7972-fc67-41ea-ab4b-6f9477c4f7d8 ``` ### Disable CDN via the API To disable CDN via the API, send a `DELETE` request to `/v2/cdn/endpoints/{cdn_id}`. ## How to Delete a CDN Endpoint Using the DigitalOcean API 1. [Create a personal access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) and save it for use with the API. 2. Send a DELETE request to [`https://api.digitalocean.com/v2/cdn/endpoints/{cdn_id}`](https://docs.digitalocean.com/reference/api/digitalocean//index.html.md#operation/cdn_delete_endpoint). ### cURL Using cURL: ```shell curl -X DELETE \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ "https://api.digitalocean.com/v2/cdn/endpoints/19f06b6a-3ace-4315-b086-499a0e521b76" ``` ### Go Using [Godo](https://github.com/digitalocean/godo), the official DigitalOcean API client for Go: ```go import ( "context" "os" "github.com/digitalocean/godo" ) func main() { token := os.Getenv("DIGITALOCEAN_TOKEN") client := godo.NewFromToken(token) ctx := context.TODO() _, err := client.CDNs.Delete(ctx, "19f06b6a-3ace-4315-b086-499a0e521b76") } ``` ### Ruby Using [DropletKit](https://github.com/digitalocean/droplet_kit), the official DigitalOcean API client for Ruby: ```ruby require 'droplet_kit' token = ENV['DIGITALOCEAN_TOKEN'] client = DropletKit::Client.new(access_token: token) client.cdns.delete(id: '19f06b6a-3ace-4315-b086-499a0e521b76') ``` ### Python Using [PyDo](https://github.com/digitalocean/pydo), the official DigitalOcean API client for Python: ```python import os from pydo import Client client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN")) delete_resp = client.cdn.delete_endpoint(cdn_id="bba23af") ```