Livewire's temporary upload rule was hard-coded to max:4194304 (4 GB), so /livewire/upload-file rejected any larger file no matter how high PHP_UPLOAD_MAX_FILESIZE or the admin's max file size were set. _uploadErrored() then replaced Livewire's actual message with "file exceeds the maximum size of N MB", quoting the admin limit the file was under. The cap is removed: PHP's upload_max_filesize is the hard limit and the admin setting is still enforced in updatedFiles() and createShare(). A rejected upload now logs the real validation errors and tells the user the server could not accept the file. max_upload_time is configurable via LIVEWIRE_MAX_UPLOAD_TIME, and the README documents every limit large uploads depend on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017XYnWFt9pJEwvAmNFN38XD
142 lines
4.9 KiB
Markdown
142 lines
4.9 KiB
Markdown
# SealShare
|
|
|
|
A simple, self-hosted file sharing solution built with Laravel. Upload files, get a shareable link, done. All files are encrypted at rest with AES-256-GCM.
|
|
|
|
## Features
|
|
|
|
- **File Uploading** — Drag & drop or browse to upload single/multiple files and folders with real-time progress
|
|
- **Shareable Links** — Each upload generates a unique link for recipients
|
|
- **End-to-End Encryption** — All files encrypted at rest using AES-256-GCM (chunked, streaming)
|
|
- **Password Protection** — Optionally protect shares with a password
|
|
- **Expiration** — Shares auto-expire after a configurable duration (1 hour to 30 days)
|
|
- **Download Limits** — Set a maximum number of downloads per share
|
|
- **ZIP Downloads** — Download all files in a share as a single ZIP archive
|
|
- **Auto-Cleanup** — Expired shares and files are automatically deleted (hourly)
|
|
- **Admin Dashboard** — View, manage, and delete all shares
|
|
- **Admin Settings** — Configure upload limits, storage quotas, branding, and more
|
|
- **Site Branding** — Custom logo, title, and description
|
|
- **System Password** — Optional global password gate to restrict upload access
|
|
- **User Authentication** — Login, registration, password reset, email verification
|
|
- **Two-Factor Authentication** — TOTP-based 2FA via Laravel Fortify
|
|
- **Dark Mode** — Dark themed UI with DaisyUI components
|
|
- **Setup Wizard** — First-run wizard to create the initial admin account
|
|
|
|
## Tech Stack
|
|
|
|
| Layer | Technology |
|
|
|-------|-----------|
|
|
| **Framework** | Laravel 13 |
|
|
| **Application Server** | FrankenPHP (via Laravel Octane) |
|
|
| **Frontend** | Livewire 4, Alpine.js, Tailwind CSS 4, DaisyUI 5, Mary UI |
|
|
| **Authentication** | Laravel Fortify |
|
|
| **Encryption** | Chunked AES-256-GCM with PBKDF2-SHA256 key derivation |
|
|
| **ZIP Downloads** | Native PHP ZipArchive |
|
|
| **Testing** | Pest 4 |
|
|
| **Code Style** | Laravel Pint |
|
|
| **Build Tool** | Vite |
|
|
|
|
## Installation — Development
|
|
|
|
### Docker (recommended)
|
|
|
|
```bash
|
|
# Build and start the dev container
|
|
docker compose -f docker-compose.dev.yml up -d --build
|
|
|
|
# View logs (including Vite output)
|
|
docker compose -f docker-compose.dev.yml logs -f
|
|
```
|
|
|
|
The app is available at `http://localhost:8000` with Vite HMR on port `5173`.
|
|
|
|
|
|
## Installation — Production
|
|
|
|
### Docker (recommended)
|
|
|
|
```bash
|
|
mkdir sealshare && cd sealshare
|
|
curl -O https://raw.githubusercontent.com/surtic86/SealShare/main/docker-compose.example.yml
|
|
cp docker-compose.example.yml docker-compose.yml
|
|
|
|
# Generate an app key and paste it into docker-compose.yml
|
|
docker run --rm ghcr.io/surtic86/sealshare:latest php artisan key:generate --show
|
|
|
|
# Edit docker-compose.yml — set APP_KEY, APP_URL, and SERVER_NAME
|
|
# Then start:
|
|
docker compose up -d
|
|
```
|
|
|
|
Migrations run automatically on startup. Open your configured domain — the Setup Wizard will create the first admin account.
|
|
|
|
**Key environment variables:**
|
|
|
|
| Variable | Required | Description |
|
|
|----------|----------|-------------|
|
|
| `APP_KEY` | Yes | Laravel encryption key |
|
|
| `APP_URL` | Yes | Full URL (e.g. `https://share.example.com`) |
|
|
| `SERVER_NAME` | Yes | Domain for auto-TLS (e.g. `share.example.com`) |
|
|
|
|
**Volumes:**
|
|
|
|
| Volume | Path | Purpose |
|
|
|--------|------|---------|
|
|
| `sealshare_storage` | `/app/storage/app` | Encrypted uploaded files |
|
|
| `sealshare_database` | `/app/database` | SQLite database |
|
|
| `caddy_data` | `/data` | TLS certificates |
|
|
| `caddy_config` | `/config` | Caddy configuration |
|
|
|
|
**Large files:**
|
|
|
|
Uploads beyond the defaults need these limits raised together:
|
|
|
|
| Limit | Where | Default |
|
|
|-------|-------|---------|
|
|
| `PHP_UPLOAD_MAX_FILESIZE` / `PHP_POST_MAX_SIZE` | Environment | `4G` — hard cap per file / per upload batch |
|
|
| Max file size / Max size per share | Admin → Settings | 100 MB / 2 GB |
|
|
| `LIVEWIRE_MAX_UPLOAD_TIME` | Environment | 30 minutes per upload |
|
|
| `OCTANE_MAX_EXECUTION_TIME` / `PHP_MAX_EXECUTION_TIME` | Environment | 300 seconds — encrypting a large file takes a while |
|
|
|
|
Behind a reverse proxy, raise its request body limit and read timeout as well (nginx: `client_max_body_size`, `proxy_read_timeout`).
|
|
|
|
### Manual (without Docker)
|
|
|
|
```bash
|
|
git clone https://github.com/surtic86/SealShare.git
|
|
cd SealShare
|
|
|
|
composer install --no-dev --optimize-autoloader
|
|
npm install && npm run build
|
|
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
|
|
# Edit .env — set APP_ENV=production, APP_DEBUG=false, APP_URL=https://your-domain.com
|
|
|
|
touch database/database.sqlite
|
|
php artisan migrate --force
|
|
php artisan storage:link
|
|
|
|
php artisan config:cache
|
|
php artisan route:cache
|
|
php artisan view:cache
|
|
```
|
|
|
|
Start with Octane:
|
|
|
|
```bash
|
|
php artisan octane:frankenphp --host=0.0.0.0 --port=80
|
|
```
|
|
|
|
Or point your web server (Nginx/Apache) to the `public/` directory for a traditional PHP-FPM setup.
|
|
|
|
Add the scheduler to your crontab:
|
|
|
|
```bash
|
|
* * * * * cd /path-to-sealshare && php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
## License
|
|
|
|
This project is open-source software licensed under the [MIT License](LICENSE).
|