Photos beginner ⏱ 30 minutes

Lychee: Self-Hosted Photo Management

Beautiful photo management with sharing. Albums, tags, and public galleries.

By Homelab Team • 2025-01-15
#lychee#photos#gallery#sharing#docker

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

FeatureLycheePhotoPrismPiwigo
Resource UsageVery LowMedium-HighLow
Setup DifficultyEasyModerateEasy
UI/UX DesignExcellentGoodDated
AI FeaturesNoneExtensiveNone
Mobile UploadManualAutomaticVia App
RAW SupportGoodExcellentLimited
PerformanceExcellentGoodGood
Portfolio UseExcellentGoodGood

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 thumbnails
  • sym: Symbolic links for public/shared albums
  • logs: Application and web server logs
  • mysql: 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:

  1. Generate APP_KEY:
# Generate a random 32-character string
openssl rand -base64 32
# Replace CHANGE-THIS-TO-RANDOM-32-CHAR-STRING with output
  1. Change passwords:

    • MYSQL_ROOT_PASSWORD: Strong root password
    • MYSQL_PASSWORD and DB_PASSWORD: Must match
    • Use unique passwords for security
  2. Adjust upload limits:

    • UPLOAD_MAX_FILESIZE: Maximum single file size
    • POST_MAX_SIZE: Maximum total upload size
    • Increase for RAW files or large batches
  3. Set timezone:

    • Replace America/New_York with your timezone
    • Find your timezone: timedatectl list-timezones

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:

  1. Database connection is pre-configured (should show green checkmark)

  2. Create admin account:

    • Username: admin (or your preferred username)
    • Password: Use a strong password (12+ characters)
    • Email: Your email address
  3. Basic settings:

    • Gallery title: Name your gallery
    • Photo sorting: Choose default sort order
    • Public access: Enable/disable public viewing
  4. 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:

  1. Click “Upload” button (cloud with arrow icon)
  2. Select photos from your computer
  3. Choose destination album (or create new)
  4. Wait for upload and processing

Bulk Upload:

  1. Click “Upload” button
  2. Select multiple photos (Ctrl/Cmd + click)
  3. Or drag and drop entire folder onto Lychee window
  4. 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:

  1. Log in to Lychee
  2. Settings > More > Import from server
  3. Lychee scans uploads/import/ directory
  4. Select photos to import
  5. Choose destination album
  6. 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:

  1. Click “Albums” in sidebar
  2. Click ”+” button (New Album)
  3. Enter album details:
    • Title: Album name
    • Description: Optional description
    • Public: Enable for public access
    • Password: Optional protection
  4. 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:

  1. Create parent album first
  2. Open parent album
  3. Click ”+” to create child album
  4. New album appears under parent

Moving Photos Between Albums:

  1. Select photos (click to select multiple)
  2. Click “Move” icon
  3. Choose destination album
  4. 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:

  1. Open album
  2. Click settings icon
  3. Enable “Public”
  4. Copy shareable link
  5. 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:

  1. Open photo
  2. Click share icon
  3. Copy direct link
  4. Or use sharing buttons (Facebook, Twitter, etc.)

Password-Protected Albums

For semi-private sharing:

  1. Create or open album
  2. Album settings
  3. Enable “Public”
  4. Enable “Password”
  5. Set strong password
  6. 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:

  1. Settings > Users (admin only)
  2. Click “Add User”
  3. Enter details:
    • Username
    • Password
    • Email
    • Upload privileges
  4. Choose user role

User Roles:

RoleView PhotosUploadCreate AlbumsSettings AccessUser Management
AdminAllYesYesYesYes
UserOwn + SharedYesYesLimitedNo
GuestShared OnlyNoNoNoNo

Sharing Albums Between Users:

  1. Open album as owner
  2. Album settings > Sharing
  3. Select users to share with
  4. 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:8080 on 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:

  1. Open Lychee in Safari
  2. Tap Share button
  3. “Add to Home Screen”
  4. Icon appears like native app

Android:

  1. Open Lychee in Chrome
  2. Menu > “Add to Home Screen”
  3. App icon added to launcher

Mobile Photo Upload

From Mobile Browser:

  1. Open Lychee on mobile
  2. Log in
  3. Tap upload button
  4. Choose “Camera” or “Photo Library”
  5. Select photos
  6. 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:

  1. Create test environment
  2. Restore latest backup
  3. Verify all photos accessible
  4. Check album structure intact
  5. Test login functionality
  6. Verify EXIF data preserved

Troubleshooting

Upload Issues

Problem: Photos fail to upload or upload stalls.

Solutions:

  1. Check upload size limits:
# In docker-compose.yml, increase limits:
environment:
  UPLOAD_MAX_FILESIZE: 200M
  POST_MAX_SIZE: 200M
  1. Verify disk space:
df -h ~/lychee/uploads
  1. Check permissions:
sudo chown -R 33:33 ~/lychee/uploads
  1. Review logs:
docker compose logs lychee | grep -i error

Thumbnail Generation Problems

Problem: Thumbnails not generating or appearing as broken images.

Solutions:

  1. Check PHP memory:
environment:
  MEMORY_LIMIT: 512M  # Increase from default
  1. Regenerate thumbnails:
# Access Lychee container
docker compose exec lychee bash

# Run diagnostic
php artisan lychee:diagnostics

# Clear and regenerate thumbs
php artisan lychee:sync
  1. 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:

  1. Verify database is running:
docker compose ps lychee-db
  1. Check database credentials match:
# Compare environment variables in docker-compose.yml
# MYSQL_PASSWORD must equal DB_PASSWORD
  1. Test database connection:
docker compose exec lychee-db mysql   -u lychee   -pLycheeDBPassword456   -e "SELECT 1;"
  1. Restart database:
docker compose restart lychee-db
docker compose restart lychee

Slow Performance

Problem: Lychee interface is slow or unresponsive.

Solutions:

  1. 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
  1. Optimize database:
docker compose exec lychee-db mysqlcheck -u root -p --optimize --all-databases
  1. Reduce thumbnail quality for faster generation:
# Settings > Image Settings
# Reduce medium/small photo quality to 85%
  1. 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:

  1. Fix permissions:
sudo chown -R 33:33 ~/lychee/uploads/import
sudo chmod -R 755 ~/lychee/uploads/import
  1. Move photos to correct location:
# Photos must be in uploads/import/ inside container
# Which maps to ~/lychee/uploads/import/ on host
  1. Check file formats:
# Lychee supports: jpg, jpeg, png, gif, webp, mp4, mov
# Ensure files have proper extensions
  1. Restart container:
docker compose restart lychee

EXIF Data Not Displaying

Problem: Photo metadata doesn’t appear.

Solutions:

  1. Verify exiftool is available:
docker compose exec lychee which exiftool
  1. Re-read metadata:
docker compose exec lychee php artisan lychee:sync
  1. 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:

  1. Add proxy host in NPM
  2. 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:

  1. Settings > Design
  2. 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.