Skip to content
pokertourPublic

About

Self-hosted vault to upload, organize and share disk images (ISO, QCOW2, VMDK, IMG…) with groups, expiring share links and 2FA. Built with Laravel & Livewire.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

39 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Silo logo

Silo

A self-hosted vault for disk images — upload, organize and share ISOs, VM disks and large archives.

Tests Docker image PHP Laravel Livewire Tailwind CSS

Features · Screenshots · Quick start · Configuration · Security · Development

🌐 Website · 🇫🇷 Version française


Silo dashboard

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

✨ Features

📦 File management

  • 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.

🔗 Sharing

  • 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.

👥 Access control

  • 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.

🛠️ Administration

  • 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.

🎨 Interface

  • 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.

📸 Screenshots

Library Disk image details
Library — search, filters, tags and bulk actions Details — verified SHA-256, share links, history
Upload Public share page
Upload — resumable chunks or import from URL Share page — what your recipients see
Command palette Administration
Command palette — ⌘K / / to jump anywhere Administration — storage, OS distribution, activity
Dark theme Confirmation dialog
Dark theme — follows your system No browser popups — custom dialogs everywhere
Single sign-on Authentication settings
Single sign-on — OpenID Connect, OAuth 2 or LDAP Authentication — IdP and directory settings

Silo on mobile
A real mobile layout: tab bar, slide-in menu and bottom sheets.

🚀 Quick start (Docker)

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.yml
curl -o .env https://raw.githubusercontent.com/pokertour/Silo/main/.env.example

2. 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 -d

Migrations 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 --force

The 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.

⚙️ Configuration

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).

Single sign-on and LDAP

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, state and nonce. 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.

🔐 Security

  • Keep disk images in private storage. The default location is storage/app/private. Never point a storage location at storage/app/public: that folder is publicly served under /storage, which would bypass permissions and share links.

  • Serve Silo over HTTPS and set TRUSTED_PROXIES to 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.

💻 Development

Requirements: PHP 8.4+, Composer, Node.js 22+, and SQLite (or MariaDB/MySQL/PostgreSQL).

git clone https://github.com/pokertour/Silo.git
cd Silo
composer run setup

composer 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:seed
composer run dev

Tests and code style

php artisan test
./vendor/bin/pint

Note

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).

Tech stack

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

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.0
git push origin v1.0.0

🤝 Contributing

Issues and pull requests are welcome. Please run php artisan test and ./vendor/bin/pint before submitting — CI checks both.

About

Self-hosted vault to upload, organize and share disk images (ISO, QCOW2, VMDK, IMG…) with groups, expiring share links and 2FA. Built with Laravel & Livewire.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages