A simple web server setup for my personal photography.
Find a file
2024-12-07 01:39:10 +00:00
assets refactor: Add assets and templates to the Git repository. 2020-01-03 01:24:24 +01:00
docker Add debugging output. 2024-12-07 01:39:10 +00:00
src/gallery feature: Add XMP tags for Google-style licensing. 2020-05-21 17:42:46 +02:00
templates feature: Add an imprint and link to it from the base template. 2020-05-21 17:53:38 +02:00
.gitignore chore: Add dist/ and *.egg-info/ to .gitignore. 2020-02-26 15:40:31 +01:00
.gitlab-ci.yml chore: Add .gitlab-ci.yml file. 2020-01-05 13:22:16 +01:00
docker-stack.yml chore: Add docker-stack.yml file, for completeness. 2020-01-03 01:29:20 +01:00
LICENSE Add LICENSE grants. 2020-02-26 02:24:07 +00:00
MANIFEST.in chore: Add packaging files. 2020-02-26 15:40:15 +01:00
README.md doc: Add first draft of a README file. 2020-02-26 03:00:38 +01:00
requirements.in refactor: Replace piexif module with py3exiv2. 2020-05-21 15:11:51 +02:00
requirements.txt refactor: Replace piexif module with py3exiv2. 2020-05-21 15:11:51 +02:00
setup.py refactor: Split gallery.py into modules in the gallery package. 2020-02-26 15:40:31 +01:00

Anselm's Gallery

Overview

This is a fancy framework around Sebastian Tschan's blueimp Gallery (with a few tweaks). Features include:

  • Supports multiple galleries with multiple albums each
  • Export selections of photographs from Digikam albums to gallery albums
  • Display captions (from Digikam) and/or image info (from Exif tags)
  • Pure picture albums or “travelogue” albums with photos and explanatory text, grouped by date
  • “Private” albums which are only accessible with a user name and password
  • Clickable world map for albums
  • RSS feed for new albums

The general idea is that the gallery.py script writes a local directory structure containing your albums, which you can look at locally before you copy it to a web server using rsync.

Server setup

The Gallery requires a web server to serve pictures and support files. No server-side code is used; all of the Gallery's content is in static files.

The recommended directory structure on the server is:

/opt/gallery                     # root directory of Gallery's tree
    .ssh/authorized_keys         # for album upload using rsync
    alice                        # Alice's gallery
        .htsitename              # “alices-gallery.example.com”
        .htpasswd                # User names and passwords
        alicesalbum1             # Alice's first album
            .htaccess            # Allowed users (optional)
            thumb                # Thumbnail-sized photographs
            screen               # Screen-sized photographs
        alicesalbum2             # Alice's second album
            …
    bob                          # Bob's gallery
        .htsitename              # “pics-by-bob.example.net”
        bobsalbum1               # Bob's first album
            …
        bobsalbum2               # Bob's second album
            …
    …

This is mostly maintained by the gallery.py script. It's your responsibility as a web server operator to associate the host name given in the /opt/gallery/NAME/.htsitename file with the /opt/gallery/NAME, by defining a “virtual host” which uses the directory as its “document root”, as in

<VirtualHost *:80>
  ServerName alices-gallery.example.com
  DocumentRoot /opt/gallery/alice
</VirtualHost>

(for Apache 2.4; the equivalent for Nginx is left to the reader as an exercise).

In the docker subdirectory of the distribution there is a Dockerfile which generates a suitable image. This includes a script to create any needed VirtualHost definitions from the directory hierarchy when the container starts up.

You still need to add the site names to the DNS and obtain suitable TLS certificates for the sites. On his own server Anselm is using Traefik with a configuration that looks roughly like

version: '3.2'

services:
  gallery:
    image: registry.anselms.net/misc/gallery/gallery:latest
    volumes:
      - /v/1/gallery:/opt/gallery
    networks:
      - web
    deploy:
      mode: replicated
      replicas: 1
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=web"
        - "traefik.port=80"
        - "traefik.backend=gallery"
        - "traefik.frontend.rule=Host:alices-gallery.example.com,pics-by-bob.example.net"

networks:
  web:
    external: true

Traefik then takes care of retrieving and keeping up-to-date a TLS certificate for the sites listed in the traefik.frontend.rule from Let's Encrypt. (Configuring Traefik to interact with Let's Encrypt is beyond the scope of this document.)

On the server, create a user called gallery with /opt/gallery as its home directory. gallery should own that directory and all the directories and files within it. Also install the OpenSSH sshd and the rsync program.

The rsync program comes with a “restricted rsync shell” script which lets us confine specific remote users to their own gallery (a subdirectory of /opt/gallery). You want to put that into /usr/local/bin/rrsync and make it executable:

# gzcat /usr/share/doc/rsync/scripts/rrsync.gz >/usr/local/bin/rrsync
# chmod +x /usr/local/bin/rrsync

You can then add the public SSH keys of prospective remote users to the /opt/gallery/.ssh/authorized_keys file, and prepend a set of use restrictions as in

command="/usr/local/bin/rrsync /v/1/gallery/alice",no-agent-forwarding,
no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding
ssh-rsa AAA…mfZE= alice@wonderland

(all on one line, with no space between the comma at the end of the first line shown here and the n at the stat of the second). This means that rsync operations authenticated by alice's public key can only access files and directories below the /v/1/gallery/alice directory. In other words, on Alice's computer the target of the rsync command should look like gallery@server.example.com: (no relative path) to access the /v/1/gallery/alice directory.

Local Setup

The first thing to do is to generate a directory which will hold the local directory hierarchy, e.g., /opt/gallery. This directory should belong to you. If you use a different directory, assign its name to the GALLERY_ROOT environment variable so the gallery.py script will be able to find it.

Add a site_meta.yml file to this directory, which should look more or less like this:

server: https://alices-gallery.example.com
site_title: Alice's Pictures
photographer_name: Alice
photographer_email: alice@example.com
remote_dir: "gallery@server.example.com:"
ssh_key: /home/alice/.ssh/id_gallery
digikam_db: /home/alice/pictures/digikam4.db
digikam_root: Pictures (local)
users:
  - alice:wonderland
always_allowed:
  - alice
rss:
  albums: 5
  description: Pictures by Alice

The server setting gives the base URL where the gallery will be accessible. The site_title will be displayed in the browser's title bar and at the top of the gallery's HTML pages. The photographer_name and photographer_email are self-explanatory. The remote_dir is the location on the web server where the gallery will be published (the value here presupposes a setup similar to the one discussed in the previous chapter, with restricted public keys for the gallery users). ssh_key is the SSH key that is used to authenticate rsync operations to copy material to the remote_dir. digikam_db gives the path name of the Digikam database (check the database preference page within Digikam if you're not quite sure where that is – note that right now we're only supporting SQLite databases). digikam_root is the name of the Digikam picture collection that the gallery.py script should consider.

It is possible to restrict access to an album to a user identified by a user name and password (using HTTP “basic” authentication). The users available for the gallery are defined under the users key, where you can list user name and passwords (separated by colons). The passwords will be encrypted and stored where the web server can find them. Individual albums can specify which users should have access to them, and the always_allowed setting lets us give a list of users who should always have access to any restricted album.

The rss key and its subkeys govern the generation of an RSS file for the gallery. The RSS files contains the last albums albums and will by default be called gallery.rss (in the root directory).

Creating an Album

Once the local directory hierarchy has been set up, we can try creating an album. In Digikam, pick an album that you like (e.g., “Seaside”, within the “Holiday” folder) and select a few photographs by putting a red frame around them (use Ctrl+Alt+1). Then execute the command

$ gallery create -a testalbum "/Holiday/Seaside 2019"

This will put together an album in the /opt/gallery/testalbum directory which contains the pictures you selected in the Digikam album. You can view this album by pointing your web browser at

file:///opt/gallery/index.html

where the test album should show up in the overview list.

There are a few things you can do on the Digikam side to improve the generated album:

  1. If you select a picture as the “album preview” in Digikam (using the right-button context menu on the picture), this will show up as the picture in the overview list of your gallery.

  2. You can set the title for the overview list by starting the album description within Digikam (accessible via “Properties” in the right-button context menu on an album in the album list, or “Album » Properties” in the main menu) with something like

    Title: My Holiday on the Seaside, 2020
    

    (followed by a blank line).

  3. Similarly, by including a line like

    Location: 59.4372155, 24.7453688
    

    where the first number is a decimal geographic latitude in degrees, with positive numbers being north of the equator, and the second number is a decimal geographic longitude in degrees, with positive numbers being east of Greenwich, you can make a marker appear in the designated spot on the gallery “map”, with a pop-up window containing a link that points to this album.

    If several albums give the same location, the pop-up window will contain links to all of them.

  4. Any image titles specified in the Digikam album will be made available in the light-box view of the album within the gallery.

The Album Overview List

The album overview list displays all albums, ordered in descending order by the album's date as set in the album properties within Digikam (i.e., “newest album first”).

If the --hidden option is given on the gallery create command, the album will be omitted from the album overview. To access it, you must type its full URL into the browser's URL bar. This is useful for draft albums or ones that you want to share with an unspecific number of people while not bothering with the hassle of a user name and password.