A self-hosted vault for disk images — upload, organize and share ISOs, VM disks and large archives.
Features · Screenshots · Quick start · Configuration · Security · Development
🌐 Website · 🇫🇷 Version française
Silo is a web application for teams that need one place to store and distribute their disk images: OS installers, VM templates, firmware, recovery media… It handles multi-gigabyte files gracefully (resumable chunked uploads, resumable downloads, background checksums), keeps access under control with groups and roles, and lets you share a file with anyone through expiring, password-protected links.
Supported formats: iso img bin raw qcow2 vhd vhdx vmdk wim esd zip 7z tar gz xz
- Resumable chunked uploads — drag & drop files of any size; interrupted uploads pick up where they left off.
- Import from URL — let the server download an image in the background, follow its progress live (speed, ETA), cancel or retry it.
- SHA-256 integrity — checksums are computed in the background, compared with the expected value you provide, and searchable (paste a hash to find the file).
- Duplicate detection — identical files are flagged automatically.
- Rich metadata — version, architecture, OS type, description and colored tags, with search, filters, sorting and bulk actions.
- Resumable downloads — HTTP Range support, plus an in-browser download manager with progress tracking.
- Public share links with optional password, expiration date and download limit.
- Brute-force protection on link passwords and a notification to the owner on every download.
- A central page to review and revoke every link.
- Invitation-only registration (single-use, expiring invitations sent by email).
- Groups: files are either visible to every user or restricted to a group's members.
- Roles: administrators manage everything; users manage their own files.
- Single sign-on with OpenID Connect / OAuth 2 (Keycloak, Authentik, Entra ID, Google, Okta, GitLab, GitHub…) and LDAP / Active Directory sign-in, with optional account provisioning and admin-group mapping.
- Two-factor authentication (TOTP) with recovery codes.
- Multi-storage: local disk, NFS, Amazon S3 (or any S3-compatible service), FTP and SFTP — credentials are encrypted at rest.
- Dashboard with usage statistics, storage capacity and OS distribution.
- Audit log of every change, user and group management, branding (name, logo, accent color).
- 4 languages: English, French, Spanish, German — detected from the browser.
- Light & dark themes that follow your system, an accent color you choose and your own logo.
- Command palette (⌘K, Ctrl K or /) to search the library and jump to any page.
- Mobile-first layout with a tab bar, a slide-in menu and bottom-sheet dialogs.
- Clean, Apple-inspired design: every image is presented like a product, with its own silver disc.

A real mobile layout: tab bar, slide-in menu and bottom sheets.
The image bundles FrankenPHP, Redis, the queue worker and the scheduler. You only need Docker and Docker Compose.
1. Get the compose file and the environment template
curl -O https://raw.githubusercontent.com/pokertour/Silo/main/docker-compose.ymlcurl -o .env https://raw.githubusercontent.com/pokertour/Silo/main/.env.example2. Fill in the secrets in .env:
| Variable | Value |
|---|---|
APP_KEY |
output of echo "base64:$(openssl rand -base64 32)" |
APP_URL |
public URL of your instance, e.g. https://silo.example.com |
DB_PASSWORD / DB_ROOT_PASSWORD |
strong random passwords (openssl rand -base64 32) |
3. Start the stack
docker compose up -dMigrations run automatically on startup. Silo listens on http://localhost:8080 — put it behind your reverse proxy with HTTPS.
4. Create the administrator account
docker compose exec app php artisan db:seed --forceThe seeder prints a randomly generated password (or uses ADMIN_EMAIL / ADMIN_PASSWORD if you set them). Log in, change it, and enable 2FA. Then invite your users from Admin → Invitations.
Tip
Pin a version instead of latest in docker-compose.yml (e.g. ghcr.io/pokertour/silo:v1.0.0) to control upgrades.
The Docker image ships with production defaults (APP_NAME=Silo, APP_ENV=production, LOG_CHANNEL=daily, Redis cache/sessions/queue, MariaDB host db…), so your .env only needs the secrets above. Any variable can still be overridden. The most useful ones:
| Variable | Default | Description |
|---|---|---|
APP_URL |
— | Public URL, used in share links and emails. |
APP_LOCALE |
en |
Default language when the browser preference is not supported. |
TRUSTED_PROXIES |
private networks | Reverse proxies allowed to send X-Forwarded-* headers. Use * only if Silo is reachable exclusively through your proxy. |
SESSION_SECURE_COOKIE |
true |
Keep enabled when served over HTTPS. |
MAIL_MAILER, MAIL_HOST, … |
log |
Fallback SMTP settings. Easier: configure SMTP from Admin → Settings → Email (password encrypted, test button). |
UPLOAD_CHUNK_SIZE_MB |
5 |
Size of upload chunks. Larger chunks mean fewer requests; your reverse proxy must accept request bodies that large (nginx: client_max_body_size). |
ADMIN_EMAIL / ADMIN_PASSWORD |
random password | Initial administrator created by the seeder. |
Storage locations (local, NFS, S3, FTP, SFTP) are managed from Admin → Settings → Storage, not from the environment. Upload limits are set in custom.ini (50 GB by default).
Both are configured from Admin → Settings → Authentication; local accounts keep working.
- OpenID Connect / OAuth 2 — enter the issuer URL (endpoints are discovered from
/.well-known/openid-configuration), the client ID and secret, and register the redirect URL shown on the page (https://<your-host>/auth/sso/callback) with your provider. The flow uses PKCE,stateandnonce. For plain OAuth 2 providers such as GitHub, fill in the authorization, token and userinfo URLs instead. - LDAP / Active Directory — server, encryption (STARTTLS or LDAPS), base DN, an optional service account and a user filter where
{login}is replaced by the username typed on the sign-in page. - Accounts — by default only existing users (matched by email address) can sign in; enable Create accounts automatically to provision them on first sign-in. Map an IdP group claim or an LDAP group (
memberOf) to the admin role if you wish. Silo's own 2FA is still required for users who enabled it.
Secrets (client secret, bind password) are encrypted with APP_KEY.
-
Keep disk images in private storage. The default location is
storage/app/private. Never point a storage location atstorage/app/public: that folder is publicly served under/storage, which would bypass permissions and share links. -
Serve Silo over HTTPS and set
TRUSTED_PROXIESto your reverse proxy's address so rate limiting sees real client IPs. -
Database: the compose file does not expose MariaDB on the host and refuses to start without
DB_PASSWORD/DB_ROOT_PASSWORD. -
Back up
APP_KEY: it encrypts storage credentials and 2FA secrets. Changing it makes them unreadable. -
CrowdSec / fail2ban: uploads are split into many requests to
/upload-chunk. If your IDS still flags them, whitelist that path (it requires a signed-in user), e.g. a CrowdSec parser whitelist in/etc/crowdsec/parsers/s02-enrich/silo-whitelist.yaml:name: silo/upload-whitelist description: "Silo resumable uploads" whitelist: reason: "Silo chunked uploads" expression: - evt.Meta.http_path startsWith '/upload-chunk'
Found a vulnerability? Please report it privately through GitHub Security Advisories rather than opening a public issue.
Requirements: PHP 8.4+, Composer, Node.js 22+, and SQLite (or MariaDB/MySQL/PostgreSQL).
git clone https://github.com/pokertour/Silo.gitcd Silocomposer run setupcomposer run setup installs dependencies, creates .env, generates the key, runs the migrations and builds the assets. Then seed the admin account and start everything (web server, queue worker, Vite):
php artisan db:seedcomposer run devTests and code style
php artisan test./vendor/bin/pintNote
The screenshots and the website are generated automatically by .github/workflows/pages.yml: it boots a demo instance seeded by DemoSeeder and captures every screen with Playwright (scripts/screenshots.mjs).
| Layer | Technology |
|---|---|
| Backend | Laravel 13, Fortify (2FA) |
| Frontend | Livewire 4 & Volt, Alpine.js, Tailwind CSS 4, Vite |
| Uploads | Resumable.js |
| Permissions & audit | spatie/laravel-permission, spatie/laravel-activitylog |
| Runtime | FrankenPHP, Redis, Supervisor |
| Tests | Pest 4 |
Releases are published to GitHub Container Registry as ghcr.io/pokertour/silo:<version> (and :latest for stable versions). Two ways to publish:
From GitHub (recommended): go to Actions → Build and Push Docker Image → Run workflow, enter the version (e.g. v1.2.0) and run. The workflow builds and pushes the image, then creates the matching git tag and GitHub release with auto-generated notes. Pre-releases such as v1.3.0-beta.1 are never tagged latest.
From the command line: push a v* tag.
git tag v1.0.0git push origin v1.0.0Issues and pull requests are welcome. Please run php artisan test and ./vendor/bin/pint before submitting — CI checks both.










