Setup large file storage
Use external file storage when your Git repository should not act as file storage, or when you need larger uploads. For example, Cloudflare Workers only allows files up to 25 MB.
This guide explains how to configure Cloudflare R2 for Administration UI uploads in LightNet.
Set up Cloudflare R2
Section titled “Set up Cloudflare R2”- Add an R2 subscription: Open your Cloudflare account and enable R2 Object Storage if it is not already active.
- Create a bucket: Create a new R2 bucket for your uploaded files.
- Configure bucket settings: In the bucket settings, add a custom domain such as
files.your-site.org. Then add a CORS policy like this:Replace the sample origins with your real local development URL and your production site URL.[{"AllowedOrigins": ["http://localhost:4321","https://your-site.org"],"AllowedMethods": ["GET", "PUT", "HEAD"],"ExposeHeaders": ["ETag"],"AllowedHeaders": ["*"],"MaxAgeSeconds": 3000}] - Create an API token: In Cloudflare, go to
R2 Object Storage, clickAPI tokensand thenManage, then create an account API token. SetPermissionstoObject Read & Write, setSpecify bucketstoApply to specific buckets only, and select your bucket. Save the generated Access Key ID and Secret Access Key somewhere secure.
Configure astro.config.mjs
Section titled “Configure astro.config.mjs”Add the experimental R2 file storage configuration to lightnetSveltiaAdmin(...):
import lightnet from "lightnet"import lightnetSveltiaAdmin from "@lightnet/sveltia-admin"import { defineConfig } from "astro/config"
export default defineConfig({ integrations: [ lightnet({ // ... }), lightnetSveltiaAdmin({ experimental: { fileStorage: { name: "cloudflare-r2", accessKeyId: "<your-access-key-id>", bucket: "<your-bucket>", accountId: "<your-account-id>", publicUrl: "https://files.your-site.org", }, }, }), ],})Configuration fields
Section titled “Configuration fields”name: Must be"cloudflare-r2".accessKeyId: The R2 Access Key ID for uploads.bucket: The bucket name used to store uploaded files.accountId: Your Cloudflare account ID.publicUrl: Public base URL used for previews and downloads.prefix: Optional path prefix inside the bucket, for exampleuploads/.
Migrate to external file storage
Section titled “Migrate to external file storage”Follow these steps when an existing site stores uploaded media files in public/files and you want future uploads to go to Cloudflare R2.
Before you start, finish the R2 setup above and choose the public file URL you want to use, for example https://files.your-site.org.
- Install rclone: Install
rcloneon your computer. - Create an R2 remote: Run
rclone configand follow Cloudflare’s rclone setup guide. The examples below use<remote-name>for the rclone remote and<bucket-name>for the R2 bucket. - Upload the existing files: From your site repository, copy the current
public/filescontents (excluding OS-files) to the R2 bucket:If you configured aTerminal window cd public/filesrclone copy . <remote-name>:<bucket-name> \--progress \--exclude ".DS_Store" \--exclude "._*" \--exclude "Thumbs.db" \--exclude "desktop.ini"prefixinexperimental.fileStorage, include it in the destination:Terminal window rclone copy . <remote-name>:<bucket-name>/<prefix> \--progress \--exclude ".DS_Store" \--exclude "._*" \--exclude "Thumbs.db" \--exclude "desktop.ini" - Check the uploaded files: Open a few uploaded file URLs in the browser using your public file domain.
For example,
public/files/videos/intro.mp4should be available athttps://files.your-site.org/videos/intro.mp4. - Update media item URLs: In your site repository, replace file URLs in media content from the local
/files/path to the R2 public URL. For JSON content, this usually means replacing:with:"/files/Keep the trailing slash so existing nested paths stay intact."https://files.your-site.org/ - Allow the file domain in LightNet: In
astro.config.mjs, add the new file storage domain tointernalDomainsso LightNet treats the uploaded files as internal media:If your config already hasastro.config.mjs lightnet({internalDomains: ["files.your-site.org"],})internalDomains, add the new domain to the existing list. - Enable R2 uploads in the Administration UI: Add the
experimental.fileStorageconfiguration tolightnetSveltiaAdmin(...)as shown above. Future Administration UI uploads will now go to R2 instead of the Git repository. - Test the site locally: Build or run the site and confirm that existing media loads from the R2 domain:
Terminal window pnpm build - Archive the old repository history: If you need to preserve the old Git history, push the current repository to a separate archive repository before removing the file blobs from the active project. This is done to reduce the size of the active repository after moving uploads to R2, which helps future clone, fetch, and CI performance. Deleting the files from the working tree alone would not be enough, because Git would still keep the old file blobs in the commit history.
- Create a fresh Git history: When the R2 migration is verified and the archive is complete, merge or close any important open pull requests first, and ask contributors to stop opening new ones. Then remove the old
.gitdirectory and initialize a new repository:Terminal window rm -rf .gitgit initgit add .git commit -m "Migrate media files to external storage"git remote add origin git@github.com:Your-Org/Your-Repo.gitgit push -u origin main --force - Verify the site now uses R2: After the force push, run the site again and confirm media still loads from the R2 domain rather than from repository files. Upload a new file in the Administration UI and check that it appears in R2 and is served from your public file URL.