Lychee: Self-Hosted Photo Management
Beautiful photo management with sharing. Albums, tags, and public galleries.
Introduction
Lychee is a lightweight, elegant photo management application designed for simplicity and aesthetics. Unlike heavier AI-powered solutions, Lychee focuses on providing a beautiful, fast interface for viewing and sharing your photos with minimal resource requirements.
What Makes Lychee Special?
Simplicity First
Lychee prioritizes ease of use over complex features. The clean, intuitive interface makes it perfect for personal photo galleries, family sharing, or professional portfolios without overwhelming users with options.
Beautiful Design
With its modern, minimalist interface inspired by macOS and iOS photo apps, Lychee presents your photos in an elegant grid layout that puts the focus on your images. The interface is responsive and works beautifully on desktop, tablet, and mobile devices.
Lightweight and Fast
Lychee runs smoothly on minimal hardware. Unlike AI-powered alternatives that require significant CPU and RAM, Lychee can run on a Raspberry Pi while still delivering a snappy user experience.
Key Features
- Clean, modern interface with grid and masonry layouts
- Album organization with nested albums
- Public and private photo sharing
- Password-protected albums
- Drag-and-drop photo uploads
- Bulk operations (move, delete, download)
- EXIF data display and editing
- Map view for geotagged photos
- Multi-user support with access controls
- Mobile-friendly responsive design
- RAW image support with automatic conversion
- Video support (display and streaming)
When to Choose Lychee
Perfect For:
- Personal photo galleries
- Photography portfolios
- Family photo sharing
- Event photo collections
- Small business showcases
- Wedding/event photographers
- Low-resource environments
Consider Alternatives If:
- You need AI-powered tagging and face recognition (use PhotoPrism or Immich)
- You want automatic mobile backup (use Immich)
- You need document management features (use Nextcloud)
Lychee vs. Alternatives
| Feature | Lychee | PhotoPrism | Piwigo |
|---|---|---|---|
| Resource Usage | Very Low | Medium-High | Low |
| Setup Difficulty | Easy | Moderate | Easy |
| UI/UX Design | Excellent | Good | Dated |
| AI Features | None | Extensive | None |
| Mobile Upload | Manual | Automatic | Via App |
| RAW Support | Good | Excellent | Limited |
| Performance | Excellent | Good | Good |
| Portfolio Use | Excellent | Good | Good |
Prerequisites
Hardware Requirements
Minimum Configuration:
- CPU: 1 core (dual-core recommended)
- RAM: 512MB (1GB recommended)
- Storage: 20GB + photo library size
- Network: 100Mbps connection
Recommended Configuration:
- CPU: 2 cores
- RAM: 2GB
- Storage: 100GB+ SSD
- Network: Gigabit ethernet
Resource Impact Examples:
- 10,000 photos: ~500MB RAM, minimal CPU
- 50,000 photos: ~1GB RAM, minimal CPU
- 100,000+ photos: 2GB RAM recommended
Software Requirements
- Docker Engine 20.10+
- Docker Compose v2.0+
- Linux, macOS, or Windows with WSL2
- Web browser (Chrome, Firefox, Safari, Edge)
Optional Components
- Reverse proxy (Nginx Proxy Manager, Traefik, Caddy)
- Domain name for public access
- SSL certificate (Let’s Encrypt recommended)
Installation
Step 1: Create Directory Structure
Create directories for Lychee’s data and configuration:
# Create main Lychee directory
mkdir -p ~/lychee
cd ~/lychee
# Create subdirectories
mkdir -p uploads
mkdir -p sym
mkdir -p logs
mkdir -p mysql
# Set permissions
chmod -R 755 uploads sym
chmod 700 mysql Directory Explanation:
uploads: Stores your original photos and generated thumbnailssym: Symbolic links for public/shared albumslogs: Application and web server logsmysql: Database files
Step 2: Docker Compose Configuration
Create a docker-compose.yml file:
version: '3.8'
services:
lychee-db:
image: mariadb:11
container_name: lychee-db
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: RootPassword123
MYSQL_DATABASE: lychee
MYSQL_USER: lychee
MYSQL_PASSWORD: LycheeDBPassword456
volumes:
- ./mysql:/var/lib/mysql
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
lychee:
image: lycheeorg/lychee:latest
container_name: lychee
restart: unless-stopped
depends_on:
- lychee-db
ports:
- "8080:80"
environment:
# Database Configuration
DB_CONNECTION: mysql
DB_HOST: lychee-db
DB_PORT: 3306
DB_DATABASE: lychee
DB_USERNAME: lychee
DB_PASSWORD: LycheeDBPassword456
# Application Settings
APP_NAME: "My Lychee Gallery"
APP_ENV: production
APP_DEBUG: false
APP_URL: http://YOUR-SERVER-IP:8080
# Security
APP_KEY: base64:CHANGE-THIS-TO-RANDOM-32-CHAR-STRING
# Timezone
TZ: America/New_York
# PHP Settings
PHP_TZ: America/New_York
UPLOAD_MAX_FILESIZE: 100M
POST_MAX_SIZE: 100M
# Optional: Enable additional features
TRUSTED_PROXIES: "*"
volumes:
- ./uploads:/uploads
- ./sym:/sym
- ./logs:/logs
networks:
default:
name: lychee-network Important Configuration Notes:
- Generate APP_KEY:
# Generate a random 32-character string
openssl rand -base64 32
# Replace CHANGE-THIS-TO-RANDOM-32-CHAR-STRING with output Change passwords:
MYSQL_ROOT_PASSWORD: Strong root passwordMYSQL_PASSWORDandDB_PASSWORD: Must match- Use unique passwords for security
Adjust upload limits:
UPLOAD_MAX_FILESIZE: Maximum single file sizePOST_MAX_SIZE: Maximum total upload size- Increase for RAW files or large batches
Set timezone:
- Replace
America/New_Yorkwith your timezone - Find your timezone:
timedatectl list-timezones
- Replace
Step 3: Deploy Lychee
Start the containers:
# Pull images and start services
docker compose up -d
# Monitor logs during startup
docker compose logs -f lychee
# Wait for: "Server started successfully" Check container status:
docker compose ps Both containers should show “Up” status.
Step 4: Initial Setup
Navigate to http://YOUR-SERVER-IP:8080 in your browser.
First-Time Setup Wizard:
Database connection is pre-configured (should show green checkmark)
Create admin account:
- Username:
admin(or your preferred username) - Password: Use a strong password (12+ characters)
- Email: Your email address
- Username:
Basic settings:
- Gallery title: Name your gallery
- Photo sorting: Choose default sort order
- Public access: Enable/disable public viewing
Complete setup and log in
Step 5: Configure Settings
Navigate to Settings (gear icon) to customize:
General Settings:
- Gallery title and subtitle
- Default sorting (newest first, oldest first, by name)
- Layout style (grid, justified, masonry)
- Image overlay display options
Security Settings:
- Enable/disable public access
- Require login for viewing
- Allow downloads
- Image protection settings
Upload Settings:
- Default album for uploads
- Skip duplicates automatically
- Delete imported files
- Medium/small thumbnail sizes
Advanced Settings:
- Full photo resolution display
- Map provider for location data
- New photos notification
- Photo compression quality
Photo Import and Organization
Method 1: Web Interface Upload
The simplest method for adding photos:
Single Photo Upload:
- Click “Upload” button (cloud with arrow icon)
- Select photos from your computer
- Choose destination album (or create new)
- Wait for upload and processing
Bulk Upload:
- Click “Upload” button
- Select multiple photos (Ctrl/Cmd + click)
- Or drag and drop entire folder onto Lychee window
- Progress bar shows upload status
Upload Tips:
- Lychee processes photos asynchronously
- Large RAW files may take time to generate thumbnails
- Close upload dialog only after “Complete” status
- Check browser console for any errors
Method 2: Server-Side Import
For large libraries already on the server:
Copy files to uploads directory:
# Copy photos to Lychee's import location
cp -r /path/to/photos/* ~/lychee/uploads/import/
# Or use rsync for large transfers with progress
rsync -av --progress /path/to/photos/ ~/lychee/uploads/import/ Import via web interface:
- Log in to Lychee
- Settings > More > Import from server
- Lychee scans
uploads/import/directory - Select photos to import
- Choose destination album
- Click “Import”
Automated import script:
#!/bin/bash
# File: ~/lychee/import-photos.sh
SOURCE_DIR="/media/camera/DCIM"
IMPORT_DIR="$HOME/lychee/uploads/import"
# Copy new photos
rsync -av --ignore-existing "$SOURCE_DIR/" "$IMPORT_DIR/"
# Set correct permissions
chown -R 33:33 "$IMPORT_DIR" # www-data user in container
echo "Photos copied to import directory"
echo "Log in to Lychee and use Settings > Import from server" Album Organization
Creating Albums:
- Click “Albums” in sidebar
- Click ”+” button (New Album)
- Enter album details:
- Title: Album name
- Description: Optional description
- Public: Enable for public access
- Password: Optional protection
- Click “Create”
Nested Albums:
Lychee supports nested album structure:
Family
├── 2023
│ ├── Summer Vacation
│ ├── Birthday Parties
│ └── Holiday Season
└── 2024
└── Winter Trip
Photography Portfolio
├── Landscapes
├── Portraits
└── Street Photography Create nested albums:
- Create parent album first
- Open parent album
- Click ”+” to create child album
- New album appears under parent
Moving Photos Between Albums:
- Select photos (click to select multiple)
- Click “Move” icon
- Choose destination album
- Confirm move
Album Settings:
Right-click album or click settings icon:
- Rename album
- Add/edit description
- Set cover photo
- Configure public access
- Set password protection
- Enable/disable downloads
- Delete album (photos remain in library)
Smart Organization Tips
By Date Structure:
2024
├── 01-January
├── 02-February
└── ... By Event Structure:
Events
├── Weddings
├── Corporate
└── Private Parties By Location Structure:
Travel
├── Europe
│ ├── France
│ └── Italy
└── Asia
└── Japan Sharing and Collaboration
Public Photo Sharing
Make Album Public:
- Open album
- Click settings icon
- Enable “Public”
- Copy shareable link
- Optional: Enable password protection
Public Album Options:
- Allow full photo download
- Allow original quality download
- Show photo information (EXIF)
- Display album description
- Enable social sharing buttons
Share Individual Photos:
- Open photo
- Click share icon
- Copy direct link
- Or use sharing buttons (Facebook, Twitter, etc.)
Password-Protected Albums
For semi-private sharing:
- Create or open album
- Album settings
- Enable “Public”
- Enable “Password”
- Set strong password
- Share link and password separately
Use Cases:
- Client preview galleries
- Family photo sharing
- Event photography delivery
- Selective photo sharing
Multi-User Access
Lychee supports multiple users with separate galleries:
Create New User:
- Settings > Users (admin only)
- Click “Add User”
- Enter details:
- Username
- Password
- Upload privileges
- Choose user role
User Roles:
| Role | View Photos | Upload | Create Albums | Settings Access | User Management |
|---|---|---|---|---|---|
| Admin | All | Yes | Yes | Yes | Yes |
| User | Own + Shared | Yes | Yes | Limited | No |
| Guest | Shared Only | No | No | No | No |
Sharing Albums Between Users:
- Open album as owner
- Album settings > Sharing
- Select users to share with
- Set permission level:
- View only
- Can add photos
- Can edit
Download Options
Single Photo Download:
- Click photo to view
- Click download icon
- Choose quality:
- Original (full resolution)
- Medium (resized)
- Small (thumbnail)
Album Download:
- Open album
- Click download icon (down arrow)
- Lychee creates ZIP archive
- Wait for preparation
- Download begins automatically
Bulk Download Script:
For server-side bulk downloads:
#!/bin/bash
# Download all photos from specific album
ALBUM_ID="12345" # Find in album URL
OUTPUT_DIR="~/downloads/lychee-album"
# Copy from container
docker cp lychee:/uploads/big/ "$OUTPUT_DIR/"
echo "Photos downloaded to $OUTPUT_DIR" Mobile Access and Apps
Mobile Web Interface
Lychee’s responsive design works excellently on mobile browsers:
Access:
- Open
http://YOUR-SERVER-IP:8080on mobile browser - Or use custom domain:
https://photos.yourdomain.com
Mobile Features:
- Touch-optimized interface
- Swipe gestures for navigation
- Mobile upload from camera or gallery
- Full album browsing
- Photo viewing with zoom
Add to Home Screen (PWA-style):
iOS:
- Open Lychee in Safari
- Tap Share button
- “Add to Home Screen”
- Icon appears like native app
Android:
- Open Lychee in Chrome
- Menu > “Add to Home Screen”
- App icon added to launcher
Mobile Photo Upload
From Mobile Browser:
- Open Lychee on mobile
- Log in
- Tap upload button
- Choose “Camera” or “Photo Library”
- Select photos
- Upload begins immediately
Tips for Mobile Upload:
- Use WiFi for large photos/RAW files
- Upload to specific album before starting
- Keep browser open until upload completes
- Check upload status in notifications
Third-Party Apps
While Lychee doesn’t have official mobile apps, compatible options exist:
iOS Options:
PhotoSync (Recommended)
- One-time purchase
- Auto-upload via WebDAV
- Background sync
- Selective folder sync
WebDAV Navigator
- Free with ads
- Manual upload to Lychee server
- Basic file management
Android Options:
FolderSync
- Free with premium option
- Scheduled auto-sync
- Multiple protocol support
- Tasker integration
PhotoSync (Android version)
- One-time purchase
- Same features as iOS version
- Auto-upload capability
WebDAV Setup for Third-Party Apps:
While Lychee doesn’t expose native WebDAV, you can set up a WebDAV server pointing to the uploads directory:
# Add to docker-compose.yml
webdav:
image: bytemark/webdav
container_name: lychee-webdav
restart: unless-stopped
ports:
- "8081:80"
environment:
AUTH_TYPE: Basic
USERNAME: webdav
PASSWORD: WebDAVPassword789
volumes:
- ./uploads:/var/lib/dav Mobile apps can then upload to the WebDAV endpoint, and you manually import via Lychee interface.
Backup Strategies
Database Backup
Automated Backup Script:
#!/bin/bash
# File: ~/lychee/backup-db.sh
BACKUP_DIR=~/lychee/backups/database
DATE=$(date +%Y%m%d_%H%M%S)
DB_PASSWORD="LycheeDBPassword456"
mkdir -p $BACKUP_DIR
# Backup Lychee database
docker compose exec -T lychee-db mysqldump -u lychee -p$DB_PASSWORD lychee | gzip > $BACKUP_DIR/lychee_db_$DATE.sql.gz
# Keep only last 30 days
find $BACKUP_DIR -name "lychee_db_*.sql.gz" -mtime +30 -delete
echo "Database backup completed: lychee_db_$DATE.sql.gz" Schedule with Cron:
chmod +x ~/lychee/backup-db.sh
# Add to crontab (daily at 3 AM)
crontab -e
# Add:
0 3 * * * ~/lychee/backup-db.sh >> ~/lychee/backup.log 2>&1 Photo Library Backup
Method 1: Rsync to External Drive
#!/bin/bash
# File: ~/lychee/backup-photos.sh
SOURCE=~/lychee/uploads
DEST=/mnt/backup/lychee/uploads
DATE=$(date +%Y%m%d)
# Create backup with rsync
rsync -av --delete --exclude="thumb" --exclude="import" --log-file=~/lychee/backup-$DATE.log $SOURCE/ $DEST/
echo "Photo backup completed: $DATE" Method 2: Restic for Encrypted Backups
# Initialize restic repository
restic init --repo /mnt/backup/lychee-restic
# Backup script
#!/bin/bash
restic backup ~/lychee/uploads --repo /mnt/backup/lychee-restic --exclude "thumb" --exclude "import" --tag daily
# Verify backup
restic snapshots --repo /mnt/backup/lychee-restic Method 3: Cloud Backup with Rclone
# Configure rclone (one-time)
rclone config
# Backup script
#!/bin/bash
rclone sync ~/lychee/uploads remote:lychee/uploads --exclude "thumb/**" --exclude "import/**" --progress
# Verify backup
rclone ls remote:lychee/uploads | wc -l Complete Backup Strategy
Full backup including configuration:
#!/bin/bash
# File: ~/lychee/full-backup.sh
BACKUP_ROOT=/mnt/backup/lychee
DATE=$(date +%Y%m%d_%H%M%S)
# Create dated backup directory
BACKUP_DIR=$BACKUP_ROOT/$DATE
mkdir -p $BACKUP_DIR
# Backup database
docker compose exec -T lychee-db mysqldump -u lychee -pLycheeDBPassword456 lychee | gzip > $BACKUP_DIR/database.sql.gz
# Backup photos
rsync -av ~/lychee/uploads $BACKUP_DIR/ --exclude="thumb" --exclude="import"
# Backup configuration
cp ~/lychee/docker-compose.yml $BACKUP_DIR/
cp -r ~/lychee/logs $BACKUP_DIR/
# Create completion marker
touch $BACKUP_DIR/.complete
# Keep only last 7 full backups
cd $BACKUP_ROOT
ls -t | tail -n +8 | xargs rm -rf
echo "Full backup completed: $DATE" Disaster Recovery
Restore from Backup:
#!/bin/bash
# File: ~/lychee/restore.sh
BACKUP_DATE="20250115_030000" # Specify backup to restore
BACKUP_DIR=/mnt/backup/lychee/$BACKUP_DATE
# Stop containers
cd ~/lychee
docker compose down
# Restore photos
rm -rf ~/lychee/uploads/*
rsync -av $BACKUP_DIR/uploads/ ~/lychee/uploads/
# Restore database
gunzip < $BACKUP_DIR/database.sql.gz | docker compose exec -T lychee-db mysql -u lychee -pLycheeDBPassword456 lychee
# Restore configuration
cp $BACKUP_DIR/docker-compose.yml ~/lychee/
# Restart containers
docker compose up -d
echo "Restoration completed from backup: $BACKUP_DATE" Test Restoration Quarterly:
- Create test environment
- Restore latest backup
- Verify all photos accessible
- Check album structure intact
- Test login functionality
- Verify EXIF data preserved
Troubleshooting
Upload Issues
Problem: Photos fail to upload or upload stalls.
Solutions:
- Check upload size limits:
# In docker-compose.yml, increase limits:
environment:
UPLOAD_MAX_FILESIZE: 200M
POST_MAX_SIZE: 200M - Verify disk space:
df -h ~/lychee/uploads - Check permissions:
sudo chown -R 33:33 ~/lychee/uploads - Review logs:
docker compose logs lychee | grep -i error Thumbnail Generation Problems
Problem: Thumbnails not generating or appearing as broken images.
Solutions:
- Check PHP memory:
environment:
MEMORY_LIMIT: 512M # Increase from default - Regenerate thumbnails:
# Access Lychee container
docker compose exec lychee bash
# Run diagnostic
php artisan lychee:diagnostics
# Clear and regenerate thumbs
php artisan lychee:sync - Verify image processing libraries:
docker compose exec lychee php -m | grep -i imagick
docker compose exec lychee php -m | grep -i gd Database Connection Errors
Problem: Cannot connect to database or frequent disconnections.
Solutions:
- Verify database is running:
docker compose ps lychee-db - Check database credentials match:
# Compare environment variables in docker-compose.yml
# MYSQL_PASSWORD must equal DB_PASSWORD - Test database connection:
docker compose exec lychee-db mysql -u lychee -pLycheeDBPassword456 -e "SELECT 1;" - Restart database:
docker compose restart lychee-db
docker compose restart lychee Slow Performance
Problem: Lychee interface is slow or unresponsive.
Solutions:
- Enable caching (add Redis):
services:
lychee-redis:
image: redis:7-alpine
container_name: lychee-redis
restart: unless-stopped
lychee:
environment:
CACHE_DRIVER: redis
REDIS_HOST: lychee-redis
REDIS_PORT: 6379
depends_on:
- lychee-redis - Optimize database:
docker compose exec lychee-db mysqlcheck -u root -p --optimize --all-databases - Reduce thumbnail quality for faster generation:
# Settings > Image Settings
# Reduce medium/small photo quality to 85% - Check resource usage:
docker stats lychee lychee-db Import from Server Not Working
Problem: Photos in import directory don’t appear in import dialog.
Solutions:
- Fix permissions:
sudo chown -R 33:33 ~/lychee/uploads/import
sudo chmod -R 755 ~/lychee/uploads/import - Move photos to correct location:
# Photos must be in uploads/import/ inside container
# Which maps to ~/lychee/uploads/import/ on host - Check file formats:
# Lychee supports: jpg, jpeg, png, gif, webp, mp4, mov
# Ensure files have proper extensions - Restart container:
docker compose restart lychee EXIF Data Not Displaying
Problem: Photo metadata doesn’t appear.
Solutions:
- Verify exiftool is available:
docker compose exec lychee which exiftool - Re-read metadata:
docker compose exec lychee php artisan lychee:sync - Enable EXIF in settings:
- Settings > Image Settings
- Enable “Read EXIF data”
- Enable “Display EXIF overlay”
Advanced Configuration
Reverse Proxy with SSL
Nginx Proxy Manager Example:
- Add proxy host in NPM
- Configure:
- Domain: photos.yourdomain.com
- Scheme: http
- Forward Hostname: lychee (or host IP)
- Forward Port: 8080
- Enable SSL with Let’s Encrypt
- Force SSL enabled
Traefik Labels Example:
services:
lychee:
labels:
- "traefik.enable=true"
- "traefik.http.routers.lychee.rule=Host(`photos.yourdomain.com`)"
- "traefik.http.routers.lychee.entrypoints=websecure"
- "traefik.http.routers.lychee.tls=true"
- "traefik.http.routers.lychee.tls.certresolver=letsencrypt"
- "traefik.http.services.lychee.loadbalancer.server.port=80" Update Lychee APP_URL:
environment:
APP_URL: https://photos.yourdomain.com
TRUSTED_PROXIES: "*" Custom Branding
Customize appearance:
- Settings > Design
- Configure:
- Custom CSS
- Logo upload
- Color scheme
- Layout preferences
Add custom CSS:
/* Example: Custom header color */
header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
/* Custom font */
body {
font-family: 'Inter', -apple-system, sans-serif;
}
/* Larger thumbnails */
.album img {
max-width: 350px;
} Integration with External Storage
Mount external NFS/SMB:
volumes:
- ./uploads:/uploads
- /mnt/nas/photos:/uploads/external:ro Lychee can index photos on external storage without copying.
Conclusion
Lychee provides an elegant, lightweight solution for self-hosted photo management that prioritizes simplicity and aesthetics. Its minimal resource requirements make it ideal for small homelab setups, while its beautiful interface rivals commercial solutions.
Key Advantages:
- Minimal resource usage (runs on Raspberry Pi)
- Beautiful, intuitive interface
- Fast deployment and configuration
- Excellent for portfolios and sharing
- Strong privacy and control
Best Use Cases:
- Personal photo galleries
- Photography portfolios
- Family photo sharing
- Event photography delivery
- Small business showcases
For homelabbers seeking a simple, elegant photo management solution without the overhead of AI processing, Lychee strikes an excellent balance between functionality and resource efficiency.
Next steps to enhance your Lychee installation:
- Configure reverse proxy with SSL for secure remote access
- Set up automated backups
- Integrate with external storage
- Customize branding for professional use
- Create user accounts for family members
Your photos deserve a beautiful home. Lychee provides exactly that with minimal complexity.