From b6a3f41b5dbf1886887f4a10bdb6b2f8016e27fc Mon Sep 17 00:00:00 2001 From: Isakdl Date: Mon, 31 Aug 2026 15:17:34 +0200 Subject: [PATCH 1/4] docs(cloud): Add a storage concept page Covers the two default storages, choosing private vs public, registering a storage on the server, adding one in the console, the file browser, deletion, and plan limits. The ServerpodCloudStorage class has not landed in the framework yet, so the two registration snippets carry TODO markers to be replaced with the real class, package, and import before this merges. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01N237K5XruApUeGphztg8nc --- cloud_docs/concepts/storage.md | 141 +++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 cloud_docs/concepts/storage.md diff --git a/cloud_docs/concepts/storage.md b/cloud_docs/concepts/storage.md new file mode 100644 index 00000000..19aaedd2 --- /dev/null +++ b/cloud_docs/concepts/storage.md @@ -0,0 +1,141 @@ +--- +sidebar_position: 9 +description: Every Serverpod Cloud project gets file storage for avatars, documents, and other user files, read and written through the standard Serverpod storage API. +--- + +# Storage + +Avatars, invoice PDFs, video attachments, and generated exports do not belong in your database. Serverpod Cloud keeps them as files instead. Your app uploads a file straight to storage rather than through an endpoint method, which keeps large files out of your API calls. Every new Serverpod Cloud project starts with two storages, `private` and `public`, matching the two the Serverpod framework configures by default. + +## Choose between private and public + +`private` is the default. Only your server can read the files in it. When your app needs a file, your server hands out a link that works for a short time. + +`public` serves its files to anyone who has the URL. Use it for content you would put on a website, such as profile pictures, product images, and downloadable assets. + +You choose access when you create a storage, and it cannot be changed afterwards. Pick `private` when you are unsure. You can add a public storage later and copy the files you want to expose into it. + +## Use a storage from your server + +Register each storage before you start the server. The storage id is the name you gave it. + + + +```dart title="server.dart" +void run(List args) async { + final pod = Serverpod(args, Protocol(), Endpoints()); + + pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'private')); + pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'public')); + + await pod.start(); +} +``` + +`ServerpodCloudStorage.create` is asynchronous, so call it before `pod.start()`. Projects created from the Serverpod template already contain these two lines. + +After that, reach the storage through `session.storage`, the same API every Serverpod storage uses. + +Write a file from your server: + +```dart +await session.storage.storeFile( + storageId: 'private', + path: 'invoices/2026/$invoiceId.pdf', + byteData: pdfBytes, +); +``` + +Read it back: + +```dart +final pdfBytes = await session.storage.retrieveFile( + storageId: 'private', + path: 'invoices/2026/$invoiceId.pdf', +); +``` + +Get the URL of a file in a public storage: + +```dart +final url = await session.storage.getPublicUrl( + storageId: 'public', + path: 'avatars/$userId.png', +); +``` + +To upload from your app, your server creates an upload description and your app sends the file with it. See [File uploads](https://docs.serverpod.dev/concepts/endpoints-and-apis/file-uploads) for the full flow, including the Flutter side. + +```dart +class ProfileEndpoint extends Endpoint { + Future getAvatarUploadDescription(Session session, String path) { + return session.storage.createDirectFileUploadDescription( + storageId: 'public', + path: path, + ); + } + + Future verifyAvatarUpload(Session session, String path) { + return session.storage.verifyDirectFileUpload( + storageId: 'public', + path: path, + ); + } +} +``` + +## Add a storage + +Add a storage when you want files kept apart from the two defaults, such as one per tenant or one for exports you purge on a schedule. + +1. Open your project in the Cloud console and select the **Storage** tab. +2. Select **Create storage**. +3. Enter a storage id. This is the name your code passes as `storageId`. Use lowercase letters, digits, and dashes. +4. Choose **Private** or **Public**. +5. Select **Create storage**. + +The storage shows as `Creating` for a few seconds, then as `Private` or `Public`. + +Deploy your project again so the new storage reaches your running server: + +```bash +scloud deploy +``` + +Then register it the same way as the default storages: + + + +```dart title="server.dart" +pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'user-uploads')); +``` + +## Browse files in the console + +Select a storage in the **Storage** tab to open its file browser. + +A storage holds a flat list of files, and the console reads `/` in a path as a folder separator. A file stored at `avatars/2026/user-42.png` appears under `avatars`, then `2026`. The path you write is the only structure you get, so decide on a path scheme before you store many files. Use **Filter by name** to narrow a long list. + +To add files, select **Upload files**, or drag them onto the browser. Select **Upload folder** to upload a whole folder and keep its structure. + +Each file row has **Download** and **Delete**. + +## Delete a storage + +Open the row menu for the storage and select **Delete storage**. Type the storage id to confirm. + +Deleting a storage deletes every file in it. The files cannot be recovered. Remove the storage from `server.dart` and deploy again, or calls to that storage id will fail. + +## Usage and limits + +A project's plan sets how many storages it can have and how much data it can store and transfer. Serverpod Cloud meters stored data and transfer, and bills them by usage. + +When a project reaches a usage limit, its files stop being readable until usage is back under the limit. Delete files you no longer need to restore access. + +See [Serverpod Cloud plans](https://serverpod.dev/cloud) for the figures on your plan. + +## Related + +- [File uploads](https://docs.serverpod.dev/concepts/endpoints-and-apis/file-uploads): the `session.storage` API and the Flutter upload flow. +- [Passwords, secrets, and environment variables](./passwords-secrets-env-vars): configuration your server reads at runtime. From 251cf8f48e1b355d890e2e025ad67fccd4fdab95 Mon Sep 17 00:00:00 2001 From: developerjamiu Date: Wed, 16 Sep 2026 23:36:42 +0100 Subject: [PATCH 2/4] docs: Update the Cloud storage concept page for 4.0.0 --- cloud_docs/concepts/storage.md | 128 +++++++++++++++------------------ 1 file changed, 57 insertions(+), 71 deletions(-) diff --git a/cloud_docs/concepts/storage.md b/cloud_docs/concepts/storage.md index 19aaedd2..74d2281e 100644 --- a/cloud_docs/concepts/storage.md +++ b/cloud_docs/concepts/storage.md @@ -1,43 +1,43 @@ --- +title: Storage sidebar_position: 9 -description: Every Serverpod Cloud project gets file storage for avatars, documents, and other user files, read and written through the standard Serverpod storage API. +description: Serverpod Cloud gives every project file storage. Use it from your server through session.storage, and manage storages and their files from the CLI or the console. --- # Storage -Avatars, invoice PDFs, video attachments, and generated exports do not belong in your database. Serverpod Cloud keeps them as files instead. Your app uploads a file straight to storage rather than through an endpoint method, which keeps large files out of your API calls. Every new Serverpod Cloud project starts with two storages, `private` and `public`, matching the two the Serverpod framework configures by default. +Avatars, invoice PDFs, and generated exports do not belong in your database. Serverpod Cloud keeps them as files instead. Every new project starts with two storages, `private` and `public`, matching the two the Serverpod framework configures by default, and you can add more. -## Choose between private and public +## Choose access for a storage -`private` is the default. Only your server can read the files in it. When your app needs a file, your server hands out a link that works for a short time. +A storage is either private or public, and the two you start with are named after their access. -`public` serves its files to anyone who has the URL. Use it for content you would put on a website, such as profile pictures, product images, and downloadable assets. +Files in a private storage are never served publicly. Your server reads and writes them, and you can reach them yourself from the CLI and the console. Use it for anything belonging to a single user or anything you would not publish. To let an app download one, your server hands out a link that works for a short time with `session.storage.temporaryDownloadUrl`. -You choose access when you create a storage, and it cannot be changed afterwards. Pick `private` when you are unsure. You can add a public storage later and copy the files you want to expose into it. +Files in a public storage are served to anyone who has the URL. Use it for content you would put on a website, such as profile images, product photos, and downloadable assets. -## Use a storage from your server +Access is fixed when a storage is created and cannot be changed afterwards. Choose private when you are unsure. You can create a public storage later and copy the files you want to expose into it. -Register each storage before you start the server. The storage id is the name you gave it. +## Use storage from your server - +New projects already connect both default storages in `server.dart`. The `serverpod_cloud_storage` package that `serverpod create` adds provides them: ```dart title="server.dart" -void run(List args) async { - final pod = Serverpod(args, Protocol(), Endpoints()); - - pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'private')); - pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'public')); - - await pod.start(); -} +pod.addCloudStorage( + await ServerpodCloudProvider.private( + fallback: () => DatabaseCloudStorage('private'), + ), +); +pod.addCloudStorage( + await ServerpodCloudProvider.public( + fallback: () => DatabaseCloudStorage('public'), + ), +); ``` -`ServerpodCloudStorage.create` is asynchronous, so call it before `pod.start()`. Projects created from the Serverpod template already contain these two lines. +Register storages before `pod.start()`, because the running server serves the storages registered on it. The `fallback` runs when your server is not running on Serverpod Cloud, for example on your own machine, and files are then stored in the database instead. -After that, reach the storage through `session.storage`, the same API every Serverpod storage uses. - -Write a file from your server: +Each call names the storage it works on with a storage id, the same name you see in the CLI and the console. Write a file: ```dart await session.storage.storeFile( @@ -59,83 +59,69 @@ final pdfBytes = await session.storage.retrieveFile( Get the URL of a file in a public storage: ```dart -final url = await session.storage.getPublicUrl( +final url = await session.storage.publicDownloadUrl( storageId: 'public', path: 'avatars/$userId.png', ); ``` -To upload from your app, your server creates an upload description and your app sends the file with it. See [File uploads](https://docs.serverpod.dev/concepts/endpoints-and-apis/file-uploads) for the full flow, including the Flutter side. - -```dart -class ProfileEndpoint extends Endpoint { - Future getAvatarUploadDescription(Session session, String path) { - return session.storage.createDirectFileUploadDescription( - storageId: 'public', - path: path, - ); - } - - Future verifyAvatarUpload(Session session, String path) { - return session.storage.verifyDirectFileUpload( - storageId: 'public', - path: path, - ); - } -} -``` +To upload from your app instead, your server creates an upload description and your app sends the file with it. See [File uploads](/concepts/endpoints-and-apis/file-uploads) for the full flow, including the Flutter side. -## Add a storage +Cloud connects `private` and `public` for you. A storage you add yourself has no ready-made helper, so you register it in `server.dart` the same way you would any other storage provider. See [Configure a storage provider](/concepts/endpoints-and-apis/file-uploads#configure-a-storage-provider) for how registration works. -Add a storage when you want files kept apart from the two defaults, such as one per tenant or one for exports you purge on a schedule. +## Manage your storages -1. Open your project in the Cloud console and select the **Storage** tab. -2. Select **Create storage**. -3. Enter a storage id. This is the name your code passes as `storageId`. Use lowercase letters, digits, and dashes. -4. Choose **Private** or **Public**. -5. Select **Create storage**. +List the storages in your project: -The storage shows as `Creating` for a few seconds, then as `Private` or `Public`. +```bash +serverpod cloud storage list +``` -Deploy your project again so the new storage reaches your running server: +Add one when you want files kept apart from the defaults, such as exports you purge on a schedule: ```bash -scloud deploy +serverpod cloud storage create exports ``` -Then register it the same way as the default storages: +A storage id uses lowercase letters, digits, and dashes, starts and ends with a letter or a digit, and is at most 63 characters. New storages are private unless you pass `--access public`. - +Delete a storage and everything in it: -```dart title="server.dart" -pod.addCloudStorage(await ServerpodCloudStorage.create(storageId: 'user-uploads')); +```bash +serverpod cloud storage delete exports ``` -## Browse files in the console +The command asks you to confirm. The files cannot be recovered, and code that still writes to that storage id fails afterwards. -Select a storage in the **Storage** tab to open its file browser. +You can do both in the Cloud console instead, from the **Storage** tab. A new storage shows as `Creating` briefly, then as `Private` or `Public`, and deleting one asks you to type its storage id to confirm. -A storage holds a flat list of files, and the console reads `/` in a path as a folder separator. A file stored at `avatars/2026/user-42.png` appears under `avatars`, then `2026`. The path you write is the only structure you get, so decide on a path scheme before you store many files. Use **Filter by name** to narrow a long list. +## Work with files -To add files, select **Upload files**, or drag them onto the browser. Select **Upload folder** to upload a whole folder and keep its structure. +Use these commands to check what your users uploaded, to put an asset in place before anyone needs it, or to clear out test data. The first argument is the storage id: -Each file row has **Download** and **Delete**. - -## Delete a storage +```bash +serverpod cloud storage file list public avatars +serverpod cloud storage file upload public ./avatar.png avatars/u1.png +serverpod cloud storage file download public avatars/u1.png +serverpod cloud storage file delete public avatars/u1.png +``` -Open the row menu for the storage and select **Delete storage**. Type the storage id to confirm. +See [CLI reference: `storage` command](/cloud/reference/cli/commands/storage) for every subcommand and flag. -Deleting a storage deletes every file in it. The files cannot be recovered. Remove the storage from `server.dart` and deploy again, or calls to that storage id will fail. +In the console, select a storage in the **Storage** tab to open its file browser. A storage holds a flat list of files, and the console reads `/` in a path as a folder separator. A file stored at `avatars/2026/user-42.png` appears under `avatars`, then `2026`. The path you write is the only structure you get, so decide on a path scheme before you store many files. Use **Filter by name** to narrow a long list. -## Usage and limits +To add files, select **Upload files**, or drag them onto the browser. Select **Upload folder** to upload a whole folder and keep its structure. Each file row has a menu with **Download** and **Delete**. -A project's plan sets how many storages it can have and how much data it can store and transfer. Serverpod Cloud meters stored data and transfer, and bills them by usage. +## Limits -When a project reaches a usage limit, its files stop being readable until usage is back under the limit. Delete files you no longer need to restore access. +- **Storages per project.** Your plan sets how many storages a project can have. +- **Metered usage.** Serverpod Cloud meters three things and bills them by usage: the data you store, the data read out of your storages, and the operations performed on them. +- **Caps on some plans.** Plans that set caps lock a project out when it goes over one. Every storage in the project becomes unreadable and unwritable, and public URLs stop working. +- **Getting access back.** Access returns on the next enforcement pass, once usage is back under the cap, once the month rolls over for a monthly cap, or once the project moves to a plan that covers the usage. Deleting files helps when the amount stored is what you went over. -See [Serverpod Cloud plans](https://serverpod.dev/cloud) for the figures on your plan. +See [Serverpod Cloud plans](https://serverpod.dev/cloud) for the caps and prices on your plan. ## Related -- [File uploads](https://docs.serverpod.dev/concepts/endpoints-and-apis/file-uploads): the `session.storage` API and the Flutter upload flow. -- [Passwords, secrets, and environment variables](./passwords-secrets-env-vars): configuration your server reads at runtime. +- [File uploads](/concepts/endpoints-and-apis/file-uploads): the `session.storage` API and the Flutter upload flow. +- [CLI reference: `storage` command](/cloud/reference/cli/commands/storage): every storage subcommand and flag. From 136c59b224928384468e161b0839bf28593dd5bb Mon Sep 17 00:00:00 2001 From: developerjamiu Date: Fri, 18 Sep 2026 12:51:29 +0100 Subject: [PATCH 3/4] docs: Address review on the Cloud storage concept page --- cloud_docs/concepts/storage.md | 76 ++++++++++++---------------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/cloud_docs/concepts/storage.md b/cloud_docs/concepts/storage.md index 74d2281e..92bf8f4e 100644 --- a/cloud_docs/concepts/storage.md +++ b/cloud_docs/concepts/storage.md @@ -1,7 +1,7 @@ --- title: Storage sidebar_position: 9 -description: Serverpod Cloud gives every project file storage. Use it from your server through session.storage, and manage storages and their files from the CLI or the console. +description: Serverpod Cloud gives every project file storage. Use it from your server through session.storage, and manage storages and files from the CLI or the console. --- # Storage @@ -10,13 +10,13 @@ Avatars, invoice PDFs, and generated exports do not belong in your database. Ser ## Choose access for a storage -A storage is either private or public, and the two you start with are named after their access. +A storage is either private or public. Any storage id can be either, and the two you start with happen to be named after their access. -Files in a private storage are never served publicly. Your server reads and writes them, and you can reach them yourself from the CLI and the console. Use it for anything belonging to a single user or anything you would not publish. To let an app download one, your server hands out a link that works for a short time with `session.storage.temporaryDownloadUrl`. +Files in a private storage are not reachable by URL by default. Your server reads and writes them, and you can reach them yourself from the CLI and the console. Use it for anything belonging to a single user or anything you would not publish. To let an app download one, your server creates a signed link with `session.storage.temporaryDownloadUrl` that works for a limited time. Check that the user is allowed to access that file before you return the link. Files in a public storage are served to anyone who has the URL. Use it for content you would put on a website, such as profile images, product photos, and downloadable assets. -Access is fixed when a storage is created and cannot be changed afterwards. Choose private when you are unsure. You can create a public storage later and copy the files you want to expose into it. +Access is fixed when a storage is created and cannot be changed afterwards. Choose private when you are unsure. You can create a public storage later and move the files you want to expose into it by downloading them and uploading them again. ## Use storage from your server @@ -35,41 +35,13 @@ pod.addCloudStorage( ); ``` -Register storages before `pod.start()`, because the running server serves the storages registered on it. The `fallback` runs when your server is not running on Serverpod Cloud, for example on your own machine, and files are then stored in the database instead. +The `fallback` runs when your server is not on Serverpod Cloud, for example on your own machine. Files are then stored in the database instead. -Each call names the storage it works on with a storage id, the same name you see in the CLI and the console. Write a file: +Your server reaches a storage through `session.storage`, naming it with a storage id. That id is the same name you see in the CLI and the console. A storage you create yourself is not connected automatically. To list, upload, download or delete its files, use the CLI or the console. -```dart -await session.storage.storeFile( - storageId: 'private', - path: 'invoices/2026/$invoiceId.pdf', - byteData: pdfBytes, -); -``` - -Read it back: - -```dart -final pdfBytes = await session.storage.retrieveFile( - storageId: 'private', - path: 'invoices/2026/$invoiceId.pdf', -); -``` - -Get the URL of a file in a public storage: - -```dart -final url = await session.storage.publicDownloadUrl( - storageId: 'public', - path: 'avatars/$userId.png', -); -``` +See [File uploads](/concepts/endpoints-and-apis/file-uploads) for the `session.storage` API and the Flutter upload flow. -To upload from your app instead, your server creates an upload description and your app sends the file with it. See [File uploads](/concepts/endpoints-and-apis/file-uploads) for the full flow, including the Flutter side. - -Cloud connects `private` and `public` for you. A storage you add yourself has no ready-made helper, so you register it in `server.dart` the same way you would any other storage provider. See [Configure a storage provider](/concepts/endpoints-and-apis/file-uploads#configure-a-storage-provider) for how registration works. - -## Manage your storages +## List your storages List the storages in your project: @@ -77,7 +49,13 @@ List the storages in your project: serverpod cloud storage list ``` -Add one when you want files kept apart from the defaults, such as exports you purge on a schedule: +The **Storage** tab in the Cloud console shows the same list, and you can add and delete storages there too. + +## Add a storage + +A storage you add yourself keeps files apart from the defaults, such as exports you purge on a schedule. The Starter plan includes two storages and your project already uses both, so adding more needs the **Growth** plan. + +Add one: ```bash serverpod cloud storage create exports @@ -85,15 +63,17 @@ serverpod cloud storage create exports A storage id uses lowercase letters, digits, and dashes, starts and ends with a letter or a digit, and is at most 63 characters. New storages are private unless you pass `--access public`. -Delete a storage and everything in it: +## Delete a storage + +Deleting a storage removes every file in it, and the files cannot be recovered. Anything still using that storage id fails afterwards. + +Delete one you no longer need: ```bash serverpod cloud storage delete exports ``` -The command asks you to confirm. The files cannot be recovered, and code that still writes to that storage id fails afterwards. - -You can do both in the Cloud console instead, from the **Storage** tab. A new storage shows as `Creating` briefly, then as `Private` or `Public`, and deleting one asks you to type its storage id to confirm. +The command asks you to confirm before it deletes anything. ## Work with files @@ -106,22 +86,20 @@ serverpod cloud storage file download public avatars/u1.png serverpod cloud storage file delete public avatars/u1.png ``` -See [CLI reference: `storage` command](/cloud/reference/cli/commands/storage) for every subcommand and flag. - -In the console, select a storage in the **Storage** tab to open its file browser. A storage holds a flat list of files, and the console reads `/` in a path as a folder separator. A file stored at `avatars/2026/user-42.png` appears under `avatars`, then `2026`. The path you write is the only structure you get, so decide on a path scheme before you store many files. Use **Filter by name** to narrow a long list. +See [CLI reference: `storage` command](/cloud/reference/cli/commands/storage) for the `storage` commands and their options. -To add files, select **Upload files**, or drag them onto the browser. Select **Upload folder** to upload a whole folder and keep its structure. Each file row has a menu with **Download** and **Delete**. +In the console, select a storage in the **Storage** tab to browse, upload, download and delete its files. A storage holds a flat list of files, and the console reads `/` in a path as a folder separator, so a file stored at `avatars/2026/user-42.png` appears under `avatars`, then `2026`. The path you write is the only structure you get, so decide on a path scheme before you store many files. ## Limits -- **Storages per project.** Your plan sets how many storages a project can have. +- **Storages per project.** The Starter plan includes two and Growth allows up to ten. - **Metered usage.** Serverpod Cloud meters three things and bills them by usage: the data you store, the data read out of your storages, and the operations performed on them. -- **Caps on some plans.** Plans that set caps lock a project out when it goes over one. Every storage in the project becomes unreadable and unwritable, and public URLs stop working. -- **Getting access back.** Access returns on the next enforcement pass, once usage is back under the cap, once the month rolls over for a monthly cap, or once the project moves to a plan that covers the usage. Deleting files helps when the amount stored is what you went over. +- **Going over a cap.** Caps come with the plan, and there is no setting that raises them. When a project goes over one, your server can no longer read or write any storage in the project, and public URLs stop serving. Listing, downloading and deleting keep working from the CLI and the console, so you can clear space. +- **Getting access back.** Access returns once usage is back under the cap, the month rolls over for a monthly cap, or the project moves to a plan that covers the usage. The check runs about once an hour, so it can take up to an hour. Deleting files helps when stored data is what you went over. See [Serverpod Cloud plans](https://serverpod.dev/cloud) for the caps and prices on your plan. ## Related - [File uploads](/concepts/endpoints-and-apis/file-uploads): the `session.storage` API and the Flutter upload flow. -- [CLI reference: `storage` command](/cloud/reference/cli/commands/storage): every storage subcommand and flag. +- [CLI reference: `storage` command](/cloud/reference/cli/commands/storage): the `storage` commands and their options. From c2a53c5b5cd9832c3763f1306dcc70e40ee850ec Mon Sep 17 00:00:00 2001 From: developerjamiu Date: Tue, 22 Sep 2026 09:26:42 +0100 Subject: [PATCH 4/4] docs: Show how to connect a custom Cloud storage from server code --- cloud_docs/concepts/storage.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/cloud_docs/concepts/storage.md b/cloud_docs/concepts/storage.md index 92bf8f4e..675f51d7 100644 --- a/cloud_docs/concepts/storage.md +++ b/cloud_docs/concepts/storage.md @@ -37,9 +37,20 @@ pod.addCloudStorage( The `fallback` runs when your server is not on Serverpod Cloud, for example on your own machine. Files are then stored in the database instead. -Your server reaches a storage through `session.storage`, naming it with a storage id. That id is the same name you see in the CLI and the console. A storage you create yourself is not connected automatically. To list, upload, download or delete its files, use the CLI or the console. +Your server reaches a storage through `session.storage`, naming it with a storage id. That id is the same name you see in the CLI and the console. -See [File uploads](/concepts/endpoints-and-apis/file-uploads) for the `session.storage` API and the Flutter upload flow. +To use a storage you created yourself, connect it in `server.dart` the same way, with `custom` and its storage id. This needs `serverpod_cloud_storage` 4.0.2 or later: + +```dart title="server.dart" +pod.addCloudStorage( + await ServerpodCloudProvider.custom( + storageId: 'exports', + fallback: () => DatabaseCloudStorage('exports'), + ), +); +``` + +See [File uploads](/concepts/endpoints-and-apis/file-uploads) for the `session.storage` API, the Flutter upload flow, and how storage providers are configured. ## List your storages @@ -63,6 +74,8 @@ serverpod cloud storage create exports A storage id uses lowercase letters, digits, and dashes, starts and ends with a letter or a digit, and is at most 63 characters. New storages are private unless you pass `--access public`. +To use it from your server, connect it with `ServerpodCloudProvider.custom`. See [Use storage from your server](#use-storage-from-your-server). + ## Delete a storage Deleting a storage removes every file in it, and the files cannot be recovered. Anything still using that storage id fails afterwards. @@ -101,5 +114,5 @@ See [Serverpod Cloud plans](https://serverpod.dev/cloud) for the caps and prices ## Related -- [File uploads](/concepts/endpoints-and-apis/file-uploads): the `session.storage` API and the Flutter upload flow. +- [File uploads](/concepts/endpoints-and-apis/file-uploads): the `session.storage` API, the Flutter upload flow, and storage provider setup. - [CLI reference: `storage` command](/cloud/reference/cli/commands/storage): the `storage` commands and their options.