Storage, artwork, and capacity
Silo is in active development before 1.0. These guides are updated frequently.
Your media files stay on mounted filesystems. Artwork and other generated files have their own storage settings. An S3 bucket cannot be used as a library folder.
Choose artwork storage
Section titled “Choose artwork storage”Before the first library scan, open Admin > Server > Storage and set Backend in the Storage group:
- Local disk keeps files on the server at Local storage path. With the default Compose file,
/var/lib/silo/artworkisconfig/silo/artworkin your data directory. - S3 uses the public storage bucket. Choose it when several hosts need the same artwork.
- Automatic uses the public bucket when one is configured, and local disk otherwise.
Save and follow the restart notice. For a single host, local disk is enough.
Save provider artwork to storage, in the same group, is on by default. It copies posters and backdrops into artwork storage, on local disk or in S3, including images you keep beside your media files. When it’s off, clients load artwork straight from the providers and Silo ignores local images. Artwork saved earlier switches back to the providers’ images, except on titles whose artwork you chose in Edit Metadata. A title with only local artwork keeps it until a refresh finds a provider image.
Silo records the location the first time it stores a file. From then on, a change goes through a storage transition.
Public and private storage
Section titled “Public and private storage”Public storage holds files clients download directly: cached artwork, uploaded posters, and branding images. “Public” describes how the files are used; the bucket does not need to be readable by everyone.
Private storage holds files that are never public: profile avatars, diagnostic bundles, and catalog seed artifacts. Without a private bucket, a local-disk install keeps these on local disk. An install that stores artwork in S3 needs a private bucket for profile avatar uploads.
Admin > Server > Storage shows Public storage and Private storage when Backend is S3 or Automatic. With Local disk it hides them, and shows Private storage only if a private bucket is already saved. To add a private bucket to a local-disk install, set Backend to Automatic. Without a public bucket, Automatic keeps artwork on local disk and shows both sections.
Silo records the private bucket’s Endpoint, Bucket, and Folder inside the bucket when it starts, even if nothing is stored there yet. Changing them afterwards requires a storage transition.
Set up S3
Section titled “Set up S3”Silo works with any S3-compatible service, including AWS S3, Cloudflare R2, and Garage. Create a bucket, then an access key with these permissions on it:
s3:PutObject,s3:GetObject, ands3:DeleteObjectto store, read, and remove files.s3:ListBucketto check the bucket and list its files. Check Connection, the readiness check, storage transitions, and diagnostics cleanup all need it.s3:PutBucketCORSfor a bucket that uses Signed links (recommended). Silo sets the bucket’s CORS rules when it starts so the web app can load files from it. If the key can’t have this permission, add a CORS rule yourself that allowsGETfrom any origin.
Then connect the bucket:
- Open Admin > Server > Storage and set Backend to S3 or Automatic.
- Under Public storage or Private storage, enter the Endpoint, Bucket, Access Key, and Secret Key. Use your provider’s S3 API endpoint, not the address of its web console.
- Set Region if your provider checks it, as Garage does. When it’s blank, Silo signs requests for
us-east-1. Turn on Put the bucket name in the URL path if your provider needs it. Folder inside the bucket is optional. - For public storage, keep How asset links are authorized at Signed links (recommended) unless you have set up another option.
- Select Check Connection. It writes, reads, and deletes a test file, so a missing permission shows up here.
- Save and follow the restart notice.
- On a device that will use Silo, open some artwork in the app or web app, or a profile avatar for private storage. Apps load these files straight from the bucket, so Check Connection can pass while devices still can’t reach it, for example when the Endpoint is an address only the server can see.
Choose how clients download files
Section titled “Choose how clients download files”How asset links are authorized, in Public storage, decides how clients get files from the public bucket. Options other than Signed links (recommended) put their settings in an Advanced section below it:
- Signed links (recommended) lets clients fetch a file without making the bucket public. It needs no other setup.
- Anyone with the link needs the bucket, or a domain in front of it, to serve files without a signature. Enter that domain in Address clients download from, under Advanced, for example
https://cdn.example.com. Anyone who has a file’s address can download it. - Cloudflare signed token is for an R2 bucket behind a custom domain, with a Cloudflare rule that checks each link. Silo signs the links and Cloudflare checks them. See Cloudflare R2.
Cloudflare R2
Section titled “Cloudflare R2”Connect an R2 bucket the same way for every link option:
- Set Endpoint to
https://<account_id>.r2.cloudflarestorage.com. - Enter the Access Key and Secret Key of an R2 API token with read and write access to the bucket.
- Turn on Put the bucket name in the URL path.
Signed links (recommended) works with these settings alone. To serve files from your own domain instead, connect a custom domain under the bucket’s Settings > Custom Domains in the Cloudflare dashboard, then choose one of the options below.
Serve files from a public custom domain
Section titled “Serve files from a public custom domain”Set How asset links are authorized to Anyone with the link, and under Advanced set Address clients download from to your custom domain, for example https://cdn.example.com. Anyone who has a file’s address can download it.
Check links with a Cloudflare signed token
Section titled “Check links with a Cloudflare signed token”This needs a Cloudflare Pro plan or higher, for the is_timed_hmac_valid_v0() rule function.
-
Generate a secret, for example with
openssl rand -hex 32. -
In the Cloudflare dashboard, open your zone’s Security rules page and select Create rule > Custom rules. Name the rule, for example
Silo CDN Token Auth. -
Select Edit expression and enter:
(http.host eq "cdn.example.com" and not is_timed_hmac_valid_v0("YOUR_SECRET", http.request.uri, 10800, http.request.timestamp.sec, 8))Replace
cdn.example.comwith your custom domain andYOUR_SECRETwith the secret.10800must equal Link lifetime in Silo.8is the length of Token query parameter plus 2:?verify=is 8 characters. -
Set the action to Block and select Deploy.
-
In Silo, set How asset links are authorized to Cloudflare signed token. Under Advanced, set Address clients download from to
https://cdn.example.com, Token Secret to the same secret, Token query parameter toverify, and Link lifetime to10800. -
Save and follow the restart notice.
-
Open an image in a client. Its address should look like
https://cdn.example.com/<object key>?verify=<unix time>-<signature>.
If images don’t load, look for blocked requests in the zone’s security events. Check that the secret, the parameter length, and the lifetime are the same in the rule and in Silo.
Link lifetime is in seconds; the default, 10800, is three hours. Silo reuses each artwork link for a while so clients and Cloudflare keep their cached images, and every link it hands out works for at least three quarters of Link lifetime. A longer lifetime means links change less often, and a leaked link keeps working longer.
Garage
Section titled “Garage”Garage supports the S3 calls Silo uses but has no bucket policies or object ACLs (see its S3 compatibility list). Use signed links, or Garage’s website access for a public domain.
Garage serves plain HTTP on both its S3 and website ports. For an https:// address, put a reverse proxy in front of Garage and use the proxy’s address in Silo.
Use signed links
Section titled “Use signed links”- Create the bucket:
garage bucket create <bucket-name> - Create a key:
garage key create <key-name>. Note the key ID and secret key it prints. - Give the key access:
garage bucket allow --read --write --key <key-name> <bucket-name> - In Silo, enter Garage’s S3 API address as the Endpoint, the bucket name, and the key ID and secret key as Access Key and Secret Key.
- Turn on Put the bucket name in the URL path.
- Set Region to the
s3_regionvalue under[s3_api]ingarage.toml. Garage’s example configuration usesgarage. If they don’t match, Garage rejects Silo’s requests and clients can’t open signed links. - Keep How asset links are authorized at Signed links (recommended).
Set up a private bucket the same way.
Serve files from a public domain
Section titled “Serve files from a public domain”-
Name the bucket after the public domain:
garage bucket create assets.example.com -
Turn on website access:
garage bucket website --allow assets.example.com -
Add a website listener to
garage.tomland restart Garage:[s3_web]bind_addr = "[::]:3902"root_domain = ".web.example.com" -
Route
assets.example.comto port 3902 through a reverse proxy that keeps theHostheader. -
In Silo, set Endpoint to Garage’s S3 API address, for example
https://garage.example.com, and Bucket toassets.example.com. Set Region and the key as in Use signed links, and turn on Put the bucket name in the URL path. -
Set How asset links are authorized to Anyone with the link, and under Advanced set Address clients download from to
https://assets.example.com. -
Open an image in a client to check the route.
https://assets.example.com/on its own returns404, which is expected.
Change storage later
Section titled “Change storage later”Use a storage transition to move from local disk to S3 (for example, before adding a second host), switch buckets or providers, move to a new local path, go back from S3 to local disk, or add or remove a private bucket. Silo checks the new location, copies what you choose, switches the settings, and restarts.
- Make a backup first.
- For a new local path, mount it into the container before you start.
- Open Admin > Server > Storage. To move to S3, set Backend to S3 first so Public storage and Private storage appear. For a new bucket, enter its Endpoint, Bucket, and keys under Public storage or Private storage, and select Check Connection.
- Start the transition. Choosing Local disk, or Automatic with no public bucket, to leave S3 opens the transition dialog right away. After choosing S3 or editing a location (the Local storage path, or a bucket’s Endpoint, Bucket, or Folder inside the bucket), select Review transition in the save bar.
- In the Change artwork storage dialog, check the Target. The dialog is called Change private storage when only private storage moves.
- Under What should move?, choose a policy (see below), then select Queue transition.
- Wait for the transition to finish. The page shows each step, such as Copying storage objects and Verifying copied objects. Select Cancel transition to stop it before the switch.
- Silo restarts itself to use the new storage. If the page shows Manual restart required, restart it yourself, for example with
docker compose restart silo. After the restart, Storage recovery may appear while Silo updates artwork references in the background. - Check posters, an uploaded image, and a profile avatar in a client.
Going back from S3 to Local disk clears every S3 setting, for private storage too. Profile avatars, diagnostic bundles, and catalog files then live on local disk as well, and the policy decides which existing files are copied there.
Silo never deletes the old storage. Remove it yourself once you are happy with the new location.
What each policy copies
Section titled “What each policy copies”| Policy | Copies | Left behind |
|---|---|---|
| Preserve personal uploads (recommended) | Branding, collection and library posters, and downloaded subtitles. Profile avatars too, when private storage moves. | Provider artwork, which goes back to its saved source URLs. When private storage moves, also diagnostic bundles and catalog files. |
| Start fresh | Nothing. | Everything. Provider artwork goes back to its saved source URLs, and custom images must be uploaded again. Downloaded subtitles, and avatars when private storage moves, stay in the old storage and are unavailable. |
| Migrate everything | All artwork, including downloaded subtitles. When private storage moves, also avatars, diagnostic bundles, and catalog files. | Nothing. This can take a long time for a large collection. |
When only private storage moves, the choices are Preserve profile avatars, Start fresh, and Migrate all private data. Only the last one copies diagnostic bundles and catalog files.
Library records and metadata in PostgreSQL stay as they are. Artwork from NFO or sidecar files that wasn’t copied comes back after a metadata refresh.
Copying needs the current storage to be reachable. If Silo cannot reach the old S3 bucket, only Start fresh is available until you reconnect it.
Private storage mismatch at startup
Section titled “Private storage mismatch at startup”If Silo refuses to start with private storage identity mismatch, its private bucket settings no longer match the location it recorded. The error names both locations.
- Stop every Silo server and node that uses this database, including nodes on older releases.
- Set
s3.private_endpoint,s3.private_bucket, ands3.private_key_prefixinserver_settingsback to the recorded location. - Start Silo, then use a storage transition for the move you intended.
Keep both buckets until you have checked for files written while the settings disagreed. Do not clear or replace the recorded location (storage.operational_identity) to get Silo started.
Space and persistence
Section titled “Space and persistence”Keep the database, artwork, and plugin data on persistent storage. Leave room for transcodes and prepared downloads; they grow while people watch or download. To cap the space prepared downloads take, set a storage budget.
Watch free space on the host and its mounted volumes. A full disk can stop one task before the whole server fails. Before adding users, set up backups.