> ## Documentation Index
> Fetch the complete documentation index at: https://developer.upsun.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Network Storage

The Network Storage service enables a new kind of [mount](https://developer.upsun.com/docs/configure-apps/image-properties/mounts.md)
that refers to a shared service rather than to a local directory.
This service allows you to store data and share it between different apps.

> [!NOTE]
>
> Writing to network mounts is slightly slower than to local mounts, most noticeably during high-volume sequential
> file creation — in that case, a local mount is more effective. Applications polling network mounts for a new file
> may not immediately detect it even though it exists.
>
> Detection can be delayed by approximately 30 seconds, so polling logic should account for this delay and not treat
> a missing file as an error until that window has passed.

## Supported versions

You can select the major and minor version.

Patch versions are applied periodically for bug fixes and other maintenance updates. By default, you get the latest available patches each time you deploy. If your project has a [maintenance window](https://developer.upsun.com/docs/core-concepts/build-deploy.md#maintenance-window) configured, Upsun Cloud applies patches only during that window. Upsun Cloud may still apply urgent or critical fixes outside of the maintenance window.

* 1.0

This service is the Upsun Cloud network storage implementation, not the version of a third-party application.

> [!WARNING]
>
> It isn't possible to upgrade or downgrade the network storage service version while keeping existing data in place.
> Changing the service version requires that the service be reinitialized.
> Any change to the service version results in existing data becoming inaccessible.

## Deprecated versions

The following versions are still available in your projects,
but they're at their end of life and are no longer receiving security updates from upstream.

* 2.0

To ensure your project remains stable in the future,switch to a [supported version](#supported-versions).

## Retired versions

The following versions have been retired and are no longer available.
If your project uses a retired version, you must update to a [supported version](#supported-versions).

*No retired versions.*

## Usage example

### 1. Configure the service

To define the service, use the `network-storage` type:


&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     \<SERVICE\_NAME>:
&#x20;       type: network-storage:\<VERSION>
&#x20;&#x20;

`SERVICE_NAME` must be [RFC 1123](https://tools.ietf.org/html/rfc1123) compliant, since it's used as the network storage's hostname:

* At most 63 characters
* Lowercase alphanumeric characters or `-` only (no underscores)
* Starts and ends with an alphanumeric character

Name the service for what it stores, for example, `shared-uploads`.

> [!WARNING]
>
> Changing the name of an existing service replaces it with a brand new service and all existing data is lost.
> Back up your data before changing the service.

### 2. Add the mount

To define the mount accessible by your application, use the following configuration:


&#x20;   applications:
&#x20;     \# The name of the app container. Must be unique within a project.
&#x20;     \<APP\_NAME>:
&#x20;       mounts:
&#x20;         \<TARGET\_PATH>:
&#x20;           source: service
&#x20;           service: \<SERVICE\_NAME>
&#x20;           source\_path: \<SOURCE\_PATH>

&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     \<SERVICE\_NAME>:
&#x20;       type: network-storage:\<VERSION>
&#x20;&#x20;

* `<TARGET_PATH>` is the path to your mount within the app container (relative to the app’s root).
* `SERVICE_NAME` is the name you [defined in step 1](#1-configure-the-service).
* `<SOURCE_PATH>` specifies where the mount points inside the service.\

  If the `source_path` is an empty string (`""`), your mount points to the entire service.\

  If you don’t define a `source_path`, Upsun Cloud uses the `MOUNT_PATH` as default value, without leading or trailing slashes.
  For example, if your mount lives in the `/my/files/` directory within your app container, it will point to a `my/files` directory within the service.

### Example configuration


&#x20;   applications:
&#x20;     \# The name of the app container. Must be unique within a project.
&#x20;     myapp:
&#x20;       mounts:
&#x20;         'my/uploads':
&#x20;           source: service
&#x20;           service: shared-uploads
&#x20;           source\_path: uploads

&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     shared-uploads:
&#x20;       type: network-storage:\{\{version:network-storage:latest}}

## Multi-application usage

If your project contains [multiple apps](https://developer.upsun.com/docs/configure-apps/multi-app),
they may [share `storage` mounts](https://developer.upsun.com/docs/configure-apps/image-properties/mounts#share-a-mount-between-several-apps).

Alternatively, they may use shared `service` mounts.
If the `source_path` is the same for both apps,
the files are shared between the two applications even if the mount location is different.

It's also possible to have one app mount a `source_path` that's a subdirectory of another application's mount.
For example:

```yaml .upsun/config.yaml theme={null}
applications:
  # The name of the app container. Must be unique within a project.
  app1:
    # The location of the application's code.
    source:
      root: "app1"

    [...]

    mounts:
      # The path to your mount within the app container (relative to the app's root).
      'web/uploads':
        # Specifies that the mount points to a network storage service that can be shared between apps.
        source: service
        # The name of the network storage service the mount points to.
        service: shared-uploads
        # Specifies where your mount points inside the external directory that is mounted to your app container.
        source_path: uploads

  # The name of the app container. Must be unique within a project.
  app2:
    # The location of the application's code.
    source:
      root: "app2"

    [...]

    mounts:
      # The path to your mount within the app container (relative to the app's root).
      'process':
        # Specifies that the mount points to a network storage service that can be shared between apps.
        source: service
        # The name of the network storage service the mount points to.
        service: shared-uploads
        # Specifies where your mount points inside the external directory that is mounted to your app container.
        # Since the target is the uploads directory app1's mount already points to,
        # the network storage service is effectively shared between app1 and app2.
        source_path: uploads/incoming
      # The path to your mount within the app container (relative to the app's root).
      'done':
        # Specifies that the mount points to a network storage service that can be shared between apps.
        source: service
        # The name of the network storage service the mount points to.
        service: shared-uploads
        # Specifies where your mount points inside the external directory that is mounted to your app container.
        # Since the target is the uploads directory app1's mount already points to,
        # the network storage service is effectively shared between app1 and app2.
        source_path: uploads/done
```

In this example, `app1` has access to the entire `uploads` directory by writing to `web/uploads`.
`app2` has two mounts that it can write to: `process` and `done`.
The `process` mount refers to the same directory as the `web/uploads/incoming` directory does on `app1`,
and the `done` mount refers to the same directory as the `web/uploads/done` directory on `app1`.

## How do I give my workers access to my main application’s files?

If you need to use a worker with access to the same file mount as your web-serving app,
define all the necessary mounts as `service` mounts.

The following example assumes a Network Storage service named `files` has been defined in `.upsun/config.yaml`.
Drupal files directories are shared between the `web` and `worker` instances,
while the Drush backup directory is unique to the `web` instance.


&#x20;   applications:
&#x20;     myapp:
&#x20;       source:
&#x20;         root: "/"

&#x20;       type: "php:\{\{version:php:latest}}"

&#x20;       \[...]

&#x20;       mounts:
&#x20;         \# The public and private files directories are
&#x20;         \# network mounts shared by web and workers.
&#x20;         'web/sites/default/files':
&#x20;           source: service
&#x20;           service: files
&#x20;           source\_path: files
&#x20;         'private':
&#x20;           source: service
&#x20;           service: files
&#x20;           source\_path: private
&#x20;         \# The backup, temp, and cache directories for
&#x20;         \# Drupal's CLI tools don't need to be shared between web and workers.
&#x20;         \# It wouldn't hurt anything to make them network
&#x20;         \# shares, however.
&#x20;         '/.drush':
&#x20;           source: storage
&#x20;           source\_path: drush
&#x20;         'tmp':
&#x20;           source: tmp
&#x20;           source\_path: tmp
&#x20;         'drush-backups':
&#x20;           source: storage
&#x20;           source\_path: drush-backups
&#x20;         '/.console':
&#x20;           source: storage
&#x20;           source\_path: console

&#x20;       \# Crons run on the web container, so they have the
&#x20;       \# same mounts as the web container.
&#x20;       crons:
&#x20;         drupal:
&#x20;           spec: '\*/20 \* \* \* \*'
&#x20;           commands:
&#x20;             start: 'cd web ; drush core-cron'

&#x20;       \# The worker defined here also has the same 6 mounts;
&#x20;       \# 2 of them are shared with the web container,
&#x20;       \# the other 4 are local to the worker.
&#x20;       workers:
&#x20;         queue:
&#x20;           commands:
&#x20;             start: |
&#x20;               cd web && drush queue-run myqueue

## How can I migrate data from a `storage` mount to a `service` mount?

Network Storage `service` mounts can be shared between different apps,
while `storage` mounts can only be shared between different *instances* of the same app.
To move data from a `storage` mount to a `service` one, follow these instructions.

Assuming you have the following `storage` mount:

```yaml .upsun/config.yaml theme={null}
applications:
  myapp:

    [...]

    mounts:
      web/uploads:
        source: storage
        source_path: uploads
```

1. Add a new `network-storage` service to your configuration, naming it `shared-uploads`:


&#x20;   applications:
&#x20;     myapp:

&#x20;       \[...]

&#x20;       mounts:
&#x20;         web/uploads:
&#x20;           source: storage
&#x20;           source\_path: uploads

&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     shared-uploads:
&#x20;       type: network-storage:\{\{version:network-storage:latest}}

> [!NOTE]
>
> Make sure you [allocate enough disk space](https://developer.upsun.com/docs/manage-resources/adjust-resources.md#vertical-scaling) to your `shared-uploads` service
> for your existing files with some buffer.

2. Add a new `service` mount, named `new-uploads`:


&#x20;   applications:
&#x20;     myapp:

&#x20;       \[...]

&#x20;       mounts:
&#x20;         web/uploads:
&#x20;           source: storage
&#x20;           source\_path: uploads
&#x20;         new-uploads:
&#x20;           source: service
&#x20;           service: shared-uploads
&#x20;           source\_path: uploads

&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     shared-uploads:
&#x20;       type: network-storage:\{\{version:network-storage:latest}}

Note that each mount is on a different storage service, which is why they can have the same `source_path`.

3. Deploy your changes.

4. Copy all your files from the `storage` (`web/uploads`) mount to the `service` (`new-uploads`) mount using `rsync`:

   ```bash theme={null}
   rsync -avz web/uploads/* new-uploads/
   ```

5. Reverse the mounts.
   To do so, rename the `storage` mount to `old-uploads`, and point the `web/uploads` directory to the `service` mount:


&#x20;   applications:
&#x20;     myapp:

&#x20;       \[...]

&#x20;       mounts:
&#x20;         old-uploads:
&#x20;           source: storage
&#x20;           source\_path: uploads
&#x20;         web/uploads:
&#x20;           source: service
&#x20;           service: shared-uploads
&#x20;           source\_path: uploads

&#x20;   services:
&#x20;     \# The name of the service container. Must be unique within a project.
&#x20;     shared-uploads:
&#x20;       type: network-storage:\{\{version:network-storage:latest}}

6. Push your changes and check that the files are now accessible from the `service` mount (now named `web/uploads`).
   To check that no files were lost during the transfer, run the following command:

   ```bash theme={null}
   rsync -avz old-uploads/* web/uploads/
   ```

7. Delete the contents of the `old-uploads` `storage` mount before removing it.

8. Push your changes again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.