Skip to content

Repository files navigation

GalleryWeb

A self-hostable photo & video gallery with a built-in editing studio — crop, rotate, flip, color/light adjustments, filter presets, and video trimming. Runs entirely on your own machine with no login and no cloud account required.

Fotoğraf ve video galeriniz + düzenleme stüdyosu. Kendi bilgisayarınızda, giriş yapmadan çalışır.

License: AGPL v3


How it runs

GalleryWeb
Who Anyone, on their own PC
Login ❌ None — open the app and go
Data Stays on your disk. No account, no telemetry, no outbound calls by default¹
Setup Double-click run.sh / run.bat (or docker compose up)
Database None to install — the thumbnail cache uses SQLite (stdlib)
Cost Free forever

There is one mode: local. No external service is required.

¹ The one exception, and it is opt-in. The map view can draw an OpenStreetMap basemap. That basemap is off by default: the app shows a consent panel explaining that requesting tiles reveals where your photos were taken to openstreetmap.org (the photos themselves are never uploaded), and the map works without it — markers on a blank canvas. Turn it on and it is remembered per device; you can reset the choice from the footer. Fonts and Leaflet are vendored locally, so nothing else leaves the machine. Verified against the code, 2026-08-07 (frontend/js/gallery.js, the img-src allow-list in backend/main.py).

Note (2026-08-07): earlier versions of this README also advertised a multi-tenant "hosted/cloud mode" (Supabase + PostgreSQL). That layer never shipped — it was an unfinished scaffold, and the setup guide pointed at it. Both have been removed so the documentation matches what the software actually does.


Features

  • Editing studio — rotate, flip (H/V), aspect-locked crop, live-preview adjustments (brightness, contrast, saturation, sharpness, temperature, gamma), and one-click filter presets (B&W, sepia, vintage, cool, warm, vivid).
  • Video trimming — cut start/end with a two-handle timeline (ffmpeg). Non-destructive: originals are backed up and revertible.
  • Fast browsing — thumbnails (SQLite cache), EXIF display, duplicate finder, favorites, tags, albums, ratings, map view (GPS EXIF).
  • PWA — installable, works offline², optional phone access on your local network (GALLERYWEB_LAN=1).

² Measured, not assumed (2026-08-07): with the network fully cut, a reload still renders the full UI from the service-worker cache — 43 KB of DOM, 506 CSS rules, gallery.js live, zero console errors. Scope, from frontend/sw.js: the app shell (HTML/CSS/JS/fonts/Leaflet) and previously viewed thumbnails are served from cache; live API calls fall back to cache and otherwise return 503 offline. So an offline reload gives you the interface and what you already looked at — not a fresh read of your folders.


Quick start — Self-host (no login)

Option A · Desktop app (Windows · Linux)

Grab an installer from Releases — no Python, no terminal, no browser tab:

Platform File Notes
Windows 10 / 11 GalleryWeb_x.y.z_x64-setup.exe Includes the WebView2 runtime — installs without internet
Linux (Debian 12+ / Ubuntu 22.04+) GalleryWeb_x.y.z_amd64.deb · _amd64.AppImage Requires glibc ≥ 2.35 — see the note below

Linux packages are built in CI, not on a developer's machine — and that is the whole point. A Linux package inherits the glibc of the machine that built it. Up to and including v1.1.0 they were built on Arch (glibc 2.44), which made them undistributable: the published .deb needs GLIBC_2.39 (won't start on Debian 12 / Ubuntu 22.04, and apt installs it anyway because the package declared no libc6 lower bound), and the v1.0.0 AppImage bundled Arch's system libraries and opened on no LTS at all. As of v1.1.1, both are built by GitHub Actions on Ubuntu 22.04 (glibc 2.35), the .deb declares libc6 (>= 2.35) so apt refuses rather than installing something broken, and every build is installed and started inside a debian:12 container before it may be published. If you're on something older, use Option B below (runs from source, no glibc constraint).

🇹🇷 Linux paketleri artık CI'da derleniyor. Bir Linux paketi, derlendiği makinenin glibc'sini taban alır. v1.1.0 dahil paketler Arch'ta (glibc 2.44) derlendiği için dağıtılamazdı: yayındaki .deb GLIBC_2.39 istiyor (Debian 12 / Ubuntu 22.04'te açılmaz, üstelik libc6 alt sınırı beyan edilmediği için apt sessizce kuruyordu), v1.0.0 AppImage'ı ise hiçbir LTS'te açılmıyordu. v1.1.1'den itibaren ikisi de GitHub Actions'ta Ubuntu 22.04 (glibc 2.35) üzerinde üretiliyor, .deb artık libc6 (>= 2.35) beyan ediyor ve her paket yayınlanmadan önce debian:12 kabında kurulup çalıştırılarak sınanıyor. Daha eski bir dağıtımdaysanız aşağıdaki Option B kaynaktan çalışır, bu kısıt yoktur.

Windows: “Windows protected your PC” — the installer is unsigned (a code-signing certificate costs $200–400/year and this is a free, open-source project). Click More info → Run anyway. You can verify what you're running: the package is built in public by GitHub Actions from this repository, not on a developer's machine.

🇹🇷 Windows'ta “Windows bilgisayarınızı korudu” uyarısı normaldir — paket imzasızdır (sertifika yıllık $200-400, bu ücretsiz açık kaynak bir proje). Ek bilgi → Yine de çalıştır deyin. Paket GitHub Actions'ta herkesin görebileceği şekilde derleniyor.

Video trimming additionally needs ffmpeg on your system; everything else works without it.

Option B · One click, from source (no terminal knowledge needed)

Download the project, then double-click the launcher for your system:

  • Linux / macOSrun.sh
  • Windowsrun.bat

It sets everything up on first run (creates an isolated environment, installs dependencies) and opens the gallery in your browser at http://localhost:5000. You only need Python 3.10+ installed first (on Windows, tick "Add Python to PATH" in the installer).

Kolay yol: run.sh (Linux/macOS) veya run.bat (Windows) dosyasına çift tıklayın — gerisini kendisi halleder, tarayıcıda galeri açılır.

Güncelleme / Updating: en son sürümü almak için güncelleyiciyi çalıştırın — Windows: guncelle.bat · Linux/macOS: ./guncelle.sh. GitHub'dan son sürümü indirir; fotoğraflarınız, ayarlarınız ve sanal ortamınız korunur. Sonraki run.bat / run.sh çalıştırmasında değişen bağımlılıklar otomatik kurulur — yani güncelleme için hiçbir şeyi silmenize gerek yok. (git ile klonladıysanız run zaten açılışta otomatik git pull yapar.)

Option C · Python by hand (zero extra services)

git clone https://github.com/ihsandeniz/galleryweb.git
cd galleryweb/backend
pip install -r requirements-selfhost.txt   # lightweight — no heavy ML deps
python main.py                              # → http://localhost:5000

Then open http://localhost:5000, click Klasör Aç / Open Folder, and pick a photo directory. That's it — no account, no database setup.

Video editing needs ffmpeg on your system (apt install ffmpeg / brew install ffmpeg / pacman -S ffmpeg).

Option D · Docker (no Python needed)

git clone https://github.com/ihsandeniz/galleryweb.git
cd galleryweb
mkdir photos                # put your photos/videos here
docker compose up --build   # → http://localhost:5000

Inside the app, open the /photos folder. ffmpeg is already included in the image.


Troubleshooting

Problem Fix
Port 5000 already in use Start on another port: PORT=5001 python main.py (or set PORT in docker-compose.yml).
Video trimming does nothing ffmpeg isn't installed. apt install ffmpeg / brew install ffmpeg / pacman -S ffmpeg. Photos work without it.
HEIC / iPhone photos don't open The pillow-heif dependency covers this — reinstall with pip install -r backend/requirements-selfhost.txt.
python: command not found Install Python 3.10+. On Windows, tick "Add Python to PATH" during install.
Phone can't reach the gallery Network access is off by default. Start with GALLERYWEB_LAN=1, then use the 📱 Telefon erişimi: URL it prints, and make sure the phone is on the same Wi-Fi.
Phone says “connection timed out” That's a firewall, not a bug — the server is listening correctly but packets are dropped. The app shows the exact command to fix it. Windows (run as Administrator): netsh advfirewall firewall add rule name="GalleryWeb" dir=in action=allow protocol=TCP localport=5000. Linux: see the 🧱 box in the app.
Windows: editing a photo does nothing Check Defender's Controlled folder access (Ransomware protection). It blocks writes to Pictures/Documents for unrecognised apps — usually silently. Either allow GalleryWeb or keep photos in an unprotected folder.
Windows: “file is used by another program” Windows won't move an open file. Stop video playback (or close the other program) and retry — the app deliberately refuses rather than pretending it deleted the file.
Want developer auto-reload GALLERYWEB_DEV=1 python main.py (off by default for faster startup).

Tech

  • Backend: FastAPI (Python), Pillow, ffmpeg. A single self-contained app (backend/main.py) with an SQLite thumbnail cache — no server database.
  • Frontend: Vanilla JS (no framework), PWA.
  • External services: none. The app makes no outbound calls (map tiles are opt-in and off until you enable them).

Security & privacy

  • Local mode stores everything on your machine and makes no outbound calls for auth.

  • ⚠️ Local mode has no authentication — this is by design (single-user desktop use). Because of that the server now binds to 127.0.0.1 only: nothing leaves your machine unless you ask for it. Network access is opt-in:

    GALLERYWEB_LAN=1 python main.py     # phone / same-Wi-Fi access

    When you enable it, anyone on that network can read, tag, and delete your photos via the API — the server prints a warning to remind you. Only do it on a network you trust, and never expose GalleryWeb directly to the internet — it has no authentication layer, so there is no safe public deployment mode.

    🇹🇷 Yerel modda giriş/parola yoktur — bu bilinçli bir tasarım (tek kişilik masaüstü kullanımı). Bu yüzden sunucu artık yalnızca 127.0.0.1 dinler; hiçbir şey makinenizden dışarı çıkmaz. Ağa açmak isteğe bağlıdır: GALLERYWEB_LAN=1 python main.py. Açtığınızda aynı ağdaki herkes fotoğraflarınızı görebilir, etiketleyebilir ve silebilir — sunucu bunu açılışta uyarı olarak yazar. Yalnızca güvendiğiniz bir ağda açın, yerel modu doğrudan internete açmayın.

  • If you put it behind a reverse proxy, set ALLOWED_ORIGINS to your exact domains (never * — the server rejects * and falls back to localhost).

  • Never commit your .env (it's git-ignored). Copy .env.example if you want to change the port or data directory.

  • See SECURITY_AUDIT.md.


License

GNU AGPL-3.0 — see LICENSE.

You are free to use, modify, and self-host GalleryWeb. If you run a modified version as a network service, the AGPL requires you to make your source code available to its users. This keeps the project open for everyone who builds on it.


Contributing

Issues and pull requests welcome. Please keep the frontend framework-free (Vanilla JS) to match the existing codebase.

About

Self-hostable photo & video gallery with a built-in editing studio (crop, filters, color/light adjustments, video trimming). No login, no cloud account — runs on your own machine. FastAPI + Vanilla JS.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages