---
title: How to Mount NFS Shares on App Platform (private)
description: Mount Network File Storage shares to App Platform services, workers, and jobs for persistent file storage shared across components and instances.
product: App Platform
url: https://docs.digitalocean.com/products/app-platform/how-to/mount-nfs-shares/
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# How to Mount NFS Shares on App Platform (private)

App Platform is a fully managed Platform-as-a-Service (PaaS) that deploys applications from Git repositories or container images. It automatically builds, deploys, and scales components while handling all underlying infrastructure.

App Platform can mount DigitalOcean [Network File Storage (NFS)](https://docs.digitalocean.com/products/nfs/index.html.md) shares into your app’s services, workers, and jobs. Unlike an App Platform instance’s local filesystem, which resets on every deployment and is separate for each instance, files written to an NFS share persist across deployments and restarts, and are visible to every instance and component that mounts the share.

This feature is in [private preview](https://docs.digitalocean.com/platform/product-lifecycle/index.html.md#private-preview). To request access, contact Support, your account team, or your Customer Success team. If your account doesn’t have access, App Platform rejects app specs that include volumes with the error `NFS volume support is not enabled for your account`.

During the private preview, you mount shares by adding a `volumes` section to your [app spec](https://docs.digitalocean.com/products/app-platform/reference/app-spec/index.html.md) and submitting it with the API or the Control Panel’s app spec editor.

## Pricing

Mounting a share to an app doesn’t incur additional App Platform charges. The [access point](https://docs.digitalocean.com/products/nfs/how-to/manage-access-points/index.html.md) that App Platform creates for the app isn’t billed. Your app’s App Platform pricing doesn’t change. Shares and their snapshots are billed at standard [Network File Storage pricing](https://docs.digitalocean.com/products/nfs/details/pricing/index.html.md), the same as when you use them outside App Platform.

## Feedback and Support

To give us feedback during the private preview, contact your Customer Success Manager or Solutions Architect.

[Private preview releases](https://docs.digitalocean.com/platform/product-lifecycle/index.html.md#private-preview) may not be suitable for production workloads. We recommend avoiding sensitive workloads in preview features.

Your use of DigitalOcean services is governed by our [terms of service](https://www.digitalocean.com/legal/terms-of-service-agreement), which cover eligibility, content, use, payments and billing, and warranties. This document is not a contract and all use of DigitalOcean’s services is subject to the terms of service.

## Prerequisites

To mount a share, you need:

- An App Platform app with at least one service, worker, or job. See [How to Create Apps in App Platform](https://docs.digitalocean.com/products/app-platform/how-to/create-apps/index.html.md).
- A Network File Storage share on the same team as your app, with `ACTIVE` status in the Network File Storage datacenter that corresponds to your app’s region. See [How to Create a Network File Storage Share](https://docs.digitalocean.com/products/nfs/how-to/create/index.html.md).
- The share’s ID. A share can only be mounted by one app at a time.

App Platform identifies regions with region slugs, such as `atl`, and Network File Storage identifies them with datacenter slugs, such as `atl1`. Create the share in the datacenter that matches your app’s region:

| App Platform region | Network File Storage datacenter |
|---|---|
| `ams` | `ams3` |
| `atl` | `atl1` |
| `mkc` | `mkc1` |
| `ric` | `ric1` |

Apps in other regions can’t mount shares. This includes the `nyc` region: apps in `nyc` run in the `nyc1` and `nyc3` datacenters, while Network File Storage shares in New York are in `nyc2`, so App Platform rejects the spec. For the datacenters where you can create shares, see [Network File Storage availability](https://docs.digitalocean.com/products/nfs/details/availability/index.html.md).

To look up your share’s ID with the API, send a `GET` request to the `/v2/nfs` endpoint with the share’s region. You need a [DigitalOcean API token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) saved as an environment variable named `DIGITALOCEAN_TOKEN`:

```shell
curl -X GET \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  "https://api.digitalocean.com/v2/nfs?region=<your_share_region>"
```

Replace `<your_share_region>` with the datacenter where the share runs, such as `atl1`. The `id` field of each share in the response is the value to use as the share ID.

## Define NFS Volumes in the App Spec

Each entry in the app spec’s top-level `volumes` array references one share and lists the components that mount it. The following example mounts an `/uploads` directory from a share into two components: an `api` service with read and write access, and a `thumbnailer` worker with read-only access:

```yaml
volumes:
- name: uploads
  type: NFS
  source:
    volume_id: <your_share_id>
    remote_path: /uploads
  mounts:
  - component: api
    mount_path: /data/uploads
  - component: thumbnailer
    mount_path: /data/uploads
    read_only: true
```

Replace `<your_share_id>` with your share’s ID, and the component names with the names of services, workers, or jobs in your app.

A volume entry supports the following fields:

- `name`: A name for the volume, unique within the app. Must be 2-32 characters, contain only lowercase letters, numbers, and hyphens, start with a letter, and end with a letter or number.
- `type`: Must be `NFS`.
- `source.volume_id`: The ID of the NFS share.
- `source.remote_path`: Optional. The directory to mount within the app-specific `do-app-<app_id>` directory on the share. Must start with `/`. If omitted, App Platform mounts the root of the app-specific directory. App Platform creates the directory if it doesn’t exist.
- `mounts`: One or more components that mount the share. Each mount supports the following fields:

  - `component`: The name of a service, worker, or job in the app. You can mount a volume to each component only once.
  - `mount_path`: The absolute path inside the component’s container where the share appears. Must start with `/`, can’t be a reserved system path, and can’t duplicate or overlap another mount path on the same component.
  - `read_only`: Optional. Set to `true` to mount the share without write access. Defaults to `false`.

To give components access to more than one share, add a separate entry to `volumes` for each share. To mount different directories of the same share, add separate entries that use the same `volume_id` with different `remote_path` values. The one-app-per-share limit applies to apps, not volume entries, so the same app can reference the same share in multiple volume entries.

## How App Platform Accesses NFS Shares

App Platform doesn’t mount the share’s root directory. It stores the app’s files in a directory dedicated to the app, named `do-app-<app_id>`, under the share’s export, and mounts that directory or the `remote_path` inside it. A `remote_path` of `/uploads` refers to `do-app-<app_id>/uploads` on the share, not `/uploads` at the share’s root. Files that other clients write elsewhere on the share aren’t visible to the app.

App Platform doesn’t delete files in the `do-app-<app_id>` directory when you unmount the share or destroy the app.

App Platform also manages the share’s access settings. When you mount a share, App Platform creates an access point for the app, so you don’t set an access policy, UID, or GID on the share yourself. Components that mount a share run as user ID and group ID `65534`, and files they create on the share are owned by that ID. If your application or container image expects to run as a specific user, such as `root`, check that it can run as `65534` before you mount a share.

Files that other clients write into the `do-app-<app_id>` directory keep their original owner. If a file isn’t owned by `65534` and its permissions don’t allow access by `65534`, the app gets permission errors when it reads or writes the file. For paths the app shares with other clients, set the owner to `65534:65534` with `chown`, or use `chmod` to grant the access the app needs.

## Mount an NFS Share Using the Control Panel

To mount a share from the Control Panel, go to the [**Apps** page](https://cloud.digitalocean.com/apps), select your app, and then click the **Settings** tab. In the **App Spec** section, click **Edit** to open the app spec editor.

Add a `volumes` section to the spec as described in [Define NFS Volumes in the App Spec](#define-nfs-volumes-in-the-app-spec), and then click **Save**. App Platform validates the spec and redeploys the app with the share mounted. The first deployment after you mount a share can take longer than usual while App Platform sets up network access to the share.

For more ways to edit an app spec, see [How to Update an App’s Spec](https://docs.digitalocean.com/products/app-platform/how-to/update-app-spec/index.html.md).

## Mount an NFS Share Using the API

To mount a share with the API, retrieve your app’s current spec, add a `volumes` section, and submit the full updated spec. The update endpoint replaces the app’s entire spec, so always start from the current version.

To use the commands in these instructions, you need a [DigitalOcean API token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md) with App Platform `read` and `write` scopes, saved as an environment variable named `DIGITALOCEAN_TOKEN`, and [`jq`](https://jqlang.org/) installed.

Retrieve your app’s current spec and save it to a file named `app-spec.json`:

```shell
curl -X GET \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  "https://api.digitalocean.com/v2/apps/<your_app_id>" \
  | jq '{spec: .app.spec}' > app-spec.json
```

Replace `<your_app_id>` with your app’s ID.

Open `app-spec.json`:

```shell
nano app-spec.json
```

Add the following `volumes` field to the existing `spec` object, keeping the object’s other fields. The following example is the JSON equivalent of the YAML example in [Define NFS Volumes in the App Spec](#define-nfs-volumes-in-the-app-spec):

```json
"volumes": [
  {
    "name": "uploads",
    "type": "NFS",
    "source": {
      "volume_id": "<your_share_id>",
      "remote_path": "/uploads"
    },
    "mounts": [
      {
        "component": "api",
        "mount_path": "/data/uploads"
      },
      {
        "component": "thumbnailer",
        "mount_path": "/data/uploads",
        "read_only": true
      }
    ]
  }
]
```

Save and close the file. Then submit the updated spec with a `PUT` request to the `/v2/apps/{id}` endpoint:

```shell
curl -X PUT \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
  -d @app-spec.json \
  "https://api.digitalocean.com/v2/apps/<your_app_id>"
```

If the spec is valid, App Platform starts a new deployment with the share mounted. If the spec is invalid, the response describes which field to fix. For the rules each field must follow, see [Define NFS Volumes in the App Spec](#define-nfs-volumes-in-the-app-spec).

## View, Update, and Unmount NFS Shares

You manage an app’s shares by editing the `volumes` section of its app spec, using either the Control Panel’s app spec editor or the API steps in [Mount an NFS Share Using the API](#mount-an-nfs-share-using-the-api). Each change redeploys the app.

- **View mounted shares**: Open the app spec editor, or retrieve the app with the API, and review the `volumes` section.
- **Update a mount**: Change a volume’s `remote_path`, or a mount’s `mount_path` or `read_only` value, or add and remove entries in `mounts`.
- **Unmount a share**: Remove the share’s entry from `volumes`.

When a share is mounted to an app, the share’s access points list in the Network File Storage section of the Control Panel includes an access point that App Platform manages. You can’t delete this access point from the Network File Storage section of the Control Panel. App Platform removes the access point when you unmount the share from the app or destroy the app. Unmounting a share or destroying the app doesn’t delete the share or the files in the app’s directory. For more about access points, see [How to Create and Delete Network File Storage Access Points](https://docs.digitalocean.com/products/nfs/how-to/manage-access-points/index.html.md).

## Limitations and Known Issues

- A share can only be mounted by one app at a time. Deployments fail with the reason `NFSShareInUseByOtherApp` if another app already uses the share. Multiple components in the same app can mount the same share.
- The share must have `ACTIVE` status and be in the Network File Storage datacenter that corresponds to your app’s region. See [Prerequisites](#prerequisites) for the region mapping. Apps in the `nyc` region can’t mount shares.
- Apps can only mount shares on the same team. If the share belongs to another team, App Platform rejects the spec because it can’t find the share.
- Components that mount a share run as user ID and group ID `65534`.
- Only services, workers, and jobs can mount shares. Static sites, functions, and build containers can’t.
- Mount paths can’t be `/workspace`, `/cnb`, `/layers`, `/platform`, `/tmp`, `/proc`, `/sys`, `/dev`, `/etc`, `/var`, `/usr`, or `/boot`, or any directory inside them. Applications that write to these locations by default, such as session files in `/tmp` or logs in `/var/log`, need to be configured to use the share’s mount path instead.
- The first deployment after you mount a new share can take longer than usual.
- The Control Panel doesn’t have a dedicated interface for mounting shares during the private preview. Use the app spec editor or the API.