Fussel
Fussel is a static photo gallery generator. It can build a simple static photo gallery site with nothing but a directory full of photos.
Features and Properties: - No server-side code to worry about once generated - Builds special "Person" gallery for people found in XMP face tags. - Adds watermarks - Mobile friendly - Automatic dark-mode - Uses EXIF hints to rotate photos - Predictable slug-basted urls
Common Use-cases: - Image Portfolios - Family Photos - Sharing Photo Archives - etc
| |
|
|---|---|
| |
|
./setup.sh
sample_config.yml
to config.yml
config.yml
to your needs (minimal change is to set INPUT_PATH)The folder you point gallery.input_path
at must have subfolders inside it with the folder names as the name of the albums you want in the gallery.
If you have your .env setup with:
gallery:
input_path: "/home/user/Photos/gallery"
Then that path should look like this:
/home/user/Photos/gallery:
- Album 1
- Album 2
- Sub Album 1
- Album 3
- Sub Album 2
- ...
Run the following script to generate your site into the path you set in gallery.output_path
folder.
- ./generate_site.sh
Point your web server at gallery.output_path
folder or copy/upload the gallery.output_path
folder to your web host HTTP root.
After running generate_site.sh
python -m http.server --directory <output_path>
(go to localhost:8000 in browser)cd fussel/web
yarn start
If you don't want to fuss with anything and would like to use docker instead to generate your site...
Required:
* <input_dir>
is the absolute path to top-level photo folder
* <output_dir>
is the absolute path to where you want the generated site written to
Note:
* The two -e env variables PGID and PUID tells the container what to set the output folder permissions to
once done. Otherwise it is set to root permissions
* For the label-based config to work you must mount /var/run/docker.sock
into the container, eg: -v /var/run/docker.sock:/var/run/docker.sock fussel
Optional:
You can provide any value found in the config.yml file in a docker label variable using --label item=value
docker run \
-e PGID=$(id -g) \
-e PUID=$(id -u) \
-v /var/run/docker.sock:/var/run/docker.sock \
-v <input_path>:/input:ro \
-v <output_path>:/output \
--label gallery.input_path="/input" \
--label gallery.output_path="/output" \
--label gallery.overwrite=False \
--label gallery.parallel_tasks=4 \
--label gallery.albums.recursive=True \
--label gallery.albums.recursive_name_pattern="{parent_album} > {album}" \
--label gallery.people.enable=True \
--label gallery.watermark.enable=True \
--label gallery.watermark.path="web/src/images/fussel-watermark.png" \
--label gallery.watermark.size_ratio=0.3 \
--label site.http_root="/" \
--label site.title="Fussel Gallery" \
ghcr.io/cbenning/fussel:latest
Once complete you can upload the output folder to your webserver, or see what it looks like with
python -m http.server --directory <output_path>
Try increasing your Node memory allocation: NODE_OPTIONS="--max-old-space-size=2048" yarn build
Reference: https://github.com/cbenning/fussel/issues/25
When running the following docker command, the "False"
and "True"
parameters appear to not be parsed correctly - I would guess because jq
reads that as a truthy string.
For example, see people.enable
and watermark.enable
below.
bash
docker run \
-e PGID=$(id -g) \
-e PUID=$(id -u) \
-v /home/dan/Backups/Exports:/input:ro \
-v $(pwd):/output \
--label gallery.input_path="/input" \
--label gallery.output_path="/output" \
--label gallery.overwrite=False \
--label albums.recursive=True \
--label albums.recursive_name_pattern="{parent_album} > {album}" \
--label people.enable=False \ # <---- 🚩
--label watermark.enable=False \ # <---- 🚩
--label watermark.path="web/src/images/fussel-watermark.png" \
--label watermark.size_ratio=0.3 \
--label site.http_root="/" \
--label site.title="Dan Hughes" \
-v /var/run/docker.sock:/var/run/docker.sock fussel
This create the following yaml config, where the booleans are strings:
yaml
Generating yaml config...
albums:
recursive: "True"
recursive_name_pattern: '{parent_album} > {album}'
gallery:
input_path: /input
output_path: /output
overwrite: "False"
org:
opencontainers:
image:
description: 'A static photo gallery generator '
licenses: MIT
source: https://github.com/cbenning/fussel
people:
enable: "False" # <---- 🚩
site:
http_root: /
title: Dan Hughes
watermark:
enable: "False" # <---- 🚩
path: web/src/images/fussel-watermark.png
size_ratio: "0.3"
Then, in the logs of the output, watermarks are generated:
Importing /input/2023-01-21 Katie's as 2023-01-21 Katie's (2023-01-21-katie-s)
--> Processing /input/2023-01-21 Katie's/DSCF5615.jpeg...
--> Processing /input/2023-01-21 Katie's/DSCF5603.jpeg...
--> Processing /input/2023-01-21 Katie's/DSCF5572.jpeg...
--> Processing /input/2023-01-21 Katie's/DSCF5641.jpeg...
----> Copying to
/fussel/fussel/web/public/static/_gallery/albums/2023-01-21-katie-s/original_dsc
f5603-jpeg.jpeg
----> Copying to
/fussel/fussel/web/public/static/_gallery/albums/2023-01-21-katie-s/original_dsc
f5572-jpeg.jpeg
----> Copying to
/fussel/fussel/web/public/static/_gallery/albums/2023-01-21-katie-s/original_dsc
f5615-jpeg.jpeg
----> Copying to
/fussel/fussel/web/public/static/_gallery/albums/2023-01-21-katie-s/original_dsc
f5641-jpeg.jpeg
------> Generating photo sizes: 500x400 800x640 1024x819 1600x1280
------> Adding watermark # <---- 🚩
--> Processing /input/2023-01-21 Katie's/DSCF5581.jpeg...
------> Generating photo sizes: 500x625 800x1000 1024x1280 1600x2000
------> Adding watermark # <---- 🚩
--> Processing /input/2023-01-21 Katie's/DSCF5613.jpeg...
----> Copying to
It appears that the boolean inputs are ignored and default values used instead.
Love the project! 🕊️
documentation says "albums.recursive" https://github.com/cbenning/fussel/blob/20c853f03b2a9a0db3e78b29bd6ad93cbd6477f8/README.md?plain=1#L122
but config is read from "gallery.albums.recursive" https://github.com/cbenning/fussel/blob/20c853f03b2a9a0db3e78b29bd6ad93cbd6477f8/fussel/generator/config.py#L39
same with most other label parameters.
V2 needs a new docker image.
Update README, everything is mostly still v1 specific
Have you thought about adding a view that can be filtered by year? Cheers
Update some dependencies with CVE's
Full Changelog: https://github.com/cbenning/fussel/compare/2.0.0-rc1...2.0.0-rc2
Total re-write using much simpler routing mechanism and most of libs replaced (as previous ones became abandonware)
Contributors to this release * @kcirtapw * @Radtoo * @chrisx8 * @cbenning
gallery photos docker static-site-generator