Sign inSign up

tedcharles/galleria

By tedcharles

•Updated 11 days ago

Galleria is a modern, self-hosted photography portfolio platform

Image
Web servers
Content management system
0

9.1K

tedcharles/galleria repository overview

⁠Galleria

A modern photography portfolio website built with React 19, TypeScript, Express 5, and SQLite. Features optimized image delivery, admin panel, analytics tracking, and responsive design.

🌐 Live Demo: tedcharles.net⁠


⁠🐳 Docker Hub

Pre-built Docker images are available on Docker Hub: hub.docker.com/r/tedcharles/galleria⁠

# Pull latest production image
docker pull tedcharles/galleria:latest

# Pull latest development image
docker pull tedcharles/galleria:dev

# Pull specific version
docker pull tedcharles/galleria:v1.2.0

Quick Start with Docker Hub image:

# Create data directory
mkdir -p ~/galleria-data

# Run with Docker
docker run -d \
  --name galleria \
  -p 3000:3000 \
  -v ~/galleria-data:/data \
  -e DATA_DIR=/data \
  tedcharles/galleria:latest

Open http://YOUR-SERVER-IP:3000 and create a username and password. No email address, DNS setup, or second exposed port is required. Email is requested only when you choose Google sign-in. Local accounts can use MFA and passkeys; email password recovery requires an email-based account.

For Nginx Proxy Manager, create one proxy host pointing to your server's WebUI port, using HTTP upstream, and enable SSL. No custom API location is needed. For plain nginx:

server {
    listen 443 ssl;
    server_name photos.example.com;
    # Configure your ssl_certificate and ssl_certificate_key here.
    client_max_body_size 0;
    location / {
        proxy_pass http://YOUR-SERVER-IP:3000;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}

DOMAIN=https://photos.example.com is optional. Leaving it blank uses your browser's origin. If your public hostname changes after setup, set DOMAIN to update generated links and Google/passkey origins.

Upgrading existing Unraid/Docker installations: keep your current volumes, port mappings, and environment variables. /app/data remains the default for existing Unraid templates; installations using DATA_DIR=/data remain supported. Existing email/password accounts keep their logins and data. FRONTEND_DOMAIN, BACKEND_DOMAIN, API_URL, ALLOWED_ORIGINS, and saved split-domain API URLs remain supported. To intentionally switch an existing split-domain installation to one domain, remove BACKEND_DOMAIN/API_URL, set DOMAIN to the public URL, and point the reverse proxy to port 3000. Update your Google OAuth redirect URI if you use Google sign-in.

VariableDefault / purpose
DOMAINOptional public URL; blank for automatic same-origin access
FRONTEND_DOMAINLegacy frontend URL override
BACKEND_DOMAIN / API_URLLegacy public API URL; explicit values preserve split-domain access
BACKEND_INTERNAL_URLInternal proxy target; defaults to http://127.0.0.1:3001
DATA_DIR/app/data in Docker unless explicitly set, e.g. /data
ALLOWED_ORIGINSOptional additional allowed browser origins

Available tags:

  • :latest - Latest production build
  • :dev - Latest development build
  • :vX.Y.Z - Specific version (e.g., :v1.2.3)

⁠Quick Start

⁠Prerequisites
  • Node.js 22+ (for development)
  • Docker & Docker Compose (for Docker deployment)
  • Google OAuth credentials (optional - password-based authentication works without it)

ā šŸš€ Getting Started

Single container deployment with PM2 process management.

  1. Clone the repository:
git clone https://github.com/theodorecharles/Galleria.git
cd Galleria
  1. Create a data directory:
mkdir -p ~/galleria-data
  1. Configure environment variables in docker-compose.yml:
environment:
  - DATA_DIR=/data
  - DOMAIN= # Optional, e.g. https://photos.yourdomain.com
volumes:
  - ~/galleria-data:/data
  1. Build and start:
docker-compose up -d --build
  1. Access the application:

⁠Option 2: Development Setup
  1. Clone and install dependencies:
git clone https://github.com/theodorecharles/Galleria.git
cd Galleria
npm install
cd backend && npm install
cd ../frontend && npm install
cd ..
  1. Start the development server:
npm run dev
  1. Open your browser: Navigate to http://localhost:3000 - the setup wizard will guide you through initial configuration.

ā šŸ“¦ Production Deployment

⁠Using PM2
# Build both frontend and backend
npm run build

# Install PM2 globally
npm install -g pm2

# Start services
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup
⁠Using Docker

See Docker Deployment⁠ section above.

⁠Automated Deployment

Via GitHub Actions:

Push to master (prod) or devel branch, and GitHub Actions automatically deploys.

Manual deployment:

git pull origin <branch>
./restart.sh

The restart.sh script handles:

  • Install all dependencies
  • Optimize all images
  • Build both frontend and backend
  • Restart services via PM2

ā šŸŽ¬ Hardware Video Encoding

Galleria supports hardware-accelerated video encoding for faster video processing using your GPU.

⁠Supported Hardware
  • NVIDIA GPUs (NVENC) - Docker and native
  • Intel Quick Sync Video (QSV) - Native only
  • AMD GPUs (AMF) - Native only
  • Apple VideoToolbox - macOS native only
  • VA-API - Linux native only
⁠Docker Setup (NVIDIA GPUs)

Prerequisites:

  1. NVIDIA GPU with driver installed on host
  2. NVIDIA Container Toolkit installed: Installation Guide⁠

Enable in docker-compose.yml:

services:
  app:
    runtime: nvidia  # Enable NVIDIA runtime
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=compute,video,utility
⁠Non-Docker Setup

Hardware encoding automatically detects and uses available GPU encoders on your system. No special configuration needed - just ensure GPU drivers are installed.

⁠Enable Hardware Encoding
  1. Navigate to Admin Panel → Settings → Video Quality
  2. Toggle Hardware Transcoding to enabled
  3. Video processing will now use GPU acceleration when available

Performance: Hardware encoding can be 5-10x faster than software encoding, especially for high-resolution videos.


ā āš™ļø Configuration

Configuration is managed through environment variables or the admin panel - you don't need to edit config files directly.

⁠Docker Deployment

Configure via environment variables in docker-compose.yml:

environment:
  - DATA_DIR=/data
  - DOMAIN= # Optional, e.g. https://photos.yourdomain.com
⁠Non-Docker Deployment
  1. Copy the example environment file:

    cp .env.example .env
    
  2. Edit .env with your settings:

    DOMAIN= # Optional public URL
    DATA_DIR=./data
    

After initial setup, all configuration is managed through the Admin Panel at /admin → Settings.

⁠Google OAuth Setup (Optional)

Google OAuth is completely optional. You can use password-based authentication without any OAuth setup.

To enable Google OAuth login:

  1. Go to Google Cloud Console⁠
  2. Create OAuth 2.0 credentials
  3. Add authorized redirect URIs:
    • Single-domain: https://photos.yourdomain.com/api/auth/google/callback
    • Local: http://localhost:3000/api/auth/google/callback
    • Existing split-domain: keep your backend URL, e.g. https://api.yourdomain.com/api/auth/google/callback
  4. Configure OAuth credentials in Admin Panel → Settings → Advanced Settings → Authentication

ā šŸ“ø Adding Photos

  1. Navigate to /admin
  2. Select album → Upload Photos
  3. Images auto-optimize in background

ā šŸ› ļø Common Tasks

View logs (PM2):

pm2 logs

View logs (Docker):

docker exec galleria pm2 logs

Restart services:

pm2 restart all
# or
docker-compose restart

Optimize images:

node scripts/optimize_all_images.js

ā šŸ“š Project Structure

galleria/
ā”œā”€ā”€ backend/              # Express API
│   ā”œā”€ā”€ src/
│   │   ā”œā”€ā”€ server.ts    # Main server
│   │   └── routes/      # API endpoints
│   └── package.json
ā”œā”€ā”€ frontend/            # React app
│   ā”œā”€ā”€ src/
│   └── package.json
ā”œā”€ā”€ data/                # Data directory (not in Git)
│   ā”œā”€ā”€ config.json      # Configuration (auto-generated, managed via admin panel)
│   ā”œā”€ā”€ photos/          # Original photos
│   ā”œā”€ā”€ optimized/       # Generated images
│   └── gallery.db       # SQLite database
ā”œā”€ā”€ .env.example         # Environment variables template (copy to .env)
ā”œā”€ā”€ scripts/             # Utility scripts
ā”œā”€ā”€ Dockerfile           # Docker container
ā”œā”€ā”€ docker-compose.yml   # Docker Compose config
└── package.json         # Root dependencies

ā šŸ”’ Security

  • āœ… CSRF protection on all mutations
  • āœ… Rate limiting (configurable)
  • āœ… Input validation and sanitization
  • āœ… Path traversal protection
  • āœ… Security headers (Helmet)
  • āœ… HTTPS enforcement in production
  • āœ… Multiple auth methods (OAuth, password, passkey)
  • āœ… Role-based access control (viewer, manager, admin)

ā šŸŒ Internationalization

Galleria supports 37 languages with full UI and SEO localization:

  • šŸ‡ŗšŸ‡ø English
  • šŸ‡ŖšŸ‡ø Spanish
  • šŸ‡«šŸ‡· French
  • šŸ‡µšŸ‡¹ Portuguese
  • šŸ‡·šŸ‡ŗ Russian
  • šŸ‡©šŸ‡Ŗ German
  • šŸ‡¹šŸ‡· Turkish
  • šŸ‡®šŸ‡¹ Italian
  • šŸ‡µšŸ‡± Polish
  • šŸ‡ŗšŸ‡¦ Ukrainian
  • šŸ‡·šŸ‡“ Romanian
  • šŸ‡³šŸ‡± Dutch
  • šŸ‡¬šŸ‡· Greek
  • šŸ‡­šŸ‡ŗ Hungarian
  • šŸ‡ØšŸ‡æ Czech
  • šŸ‡ŖšŸ‡ø Catalan
  • šŸ‡øšŸ‡Ŗ Swedish
  • šŸ‡§šŸ‡¬ Bulgarian
  • šŸ‡·šŸ‡ø Serbian
  • šŸ‡©šŸ‡° Danish
  • šŸ‡«šŸ‡® Finnish
  • šŸ‡³šŸ‡“ Norwegian
  • šŸ‡øšŸ‡° Slovak
  • šŸ‡­šŸ‡· Croatian
  • šŸ‡±šŸ‡¹ Lithuanian
  • šŸ‡øšŸ‡® Slovenian
  • šŸ‘ Basque
  • šŸ›ļø Latin
  • šŸ‡ØšŸ‡³ Chinese (Simplified)
  • šŸ‡®šŸ‡© Indonesian
  • šŸ‡ÆšŸ‡µ Japanese
  • šŸ‡»šŸ‡³ Vietnamese
  • šŸ‡°šŸ‡· Korean
  • šŸ‡µšŸ‡­ Filipino
  • šŸ‡¹šŸ‡­ Thai
  • šŸ‡²šŸ‡¾ Malay
  • šŸ‡²šŸ‡² Burmese
⁠Changing Language
  1. Navigate to Admin Panel → Settings → Branding
  2. Select your preferred language from the dropdown
  3. The entire site (including SEO meta tags) updates instantly

The selected language applies to:

  • All UI elements and buttons
  • Navigation and menus
  • Admin panel
  • SEO titles and descriptions
  • Error messages and notifications


Built by Ted Charles⁠ with React, TypeScript, and Express

Tag summary

Content type

Image

Digest

sha256:e1862d4ad…

Size

694.4 MB

Last updated

11 days ago

docker pull tedcharles/galleria