Skip to main content

Photo Gallery Part 3: PiGallery 2

Today, I am trying out PiGallery 2. The “Pi” in the name refers to Raspberry Pi. While Raspberry Pi computers have more RAM than my target of 1GB, I am hopeful that this project can run with modest resources.

Impressions

Installation

The recommended way to install and run PiGallery 2 is to use Docker. I immediately notice that the official images use Debian buster, which is old. I wonder if there is a reason for this, or if the developer has just not had time to update it. The software is implemented using Node 14. I checked the currency of this version since the OS used is old, and I found that the current version is 17 while the LTS version is 16. Version 14 sounds old, but I see that it was first released in April 2020, so it is not too old. I wonder if PiGallery 2 works with more recent versions of Node, but it does not really matter for my use case. I see that there is a current Node image for Node 14 on Debian bullseye, so perhaps one can at least use stable Debian. I will use an official image for this test, but I will create my own image if I decide to proceed further with this software.

I created a docker-compose.yaml file along with some empty directories in a test directory.

$ ls -d *
config  db  docker-compose.yml  images  tmp

The docker-compose.yaml file is configured as follows. I exposed the service on port 8080 on my host network. Note that I am not using a Docker volume for the database, opting for a filesystem mount instead.

version: "3.9"
services:
  pigallery2:
    image: "bpatrik/pigallery2:latest-debian-buster"
    container_name: pigallery2
    environment:
      - NODE_ENV=production
    volumes:
      - "./config:/app/data/config"
      - "./db:/app/data/db"
      - "./images:/app/data/images"
      - "./tmp:/app/data/tmp"
    ports:
      - "8080:80"

Upon starting the service using docker-compose up, I see that it initializes a configuration file as well as an SQLite database. JSON is not a terribly editor-friendly configuration format, but I am happy that it is at least plain text. Inspecting the database, I see that it has seven tables and is pretty straightforward.

$ find . -type f
./config/config.json
./db/sqlite.db
./docker-compose.yml

Accessing the login page, 11 requests are made, transferring a total of 1.5MB. I consider that to be pretty heavy, but not a deal breaker. On a connection with 31.75KB/s download throughput, the overhead of loading the site requires just over 48 seconds of download time. Even within my LAN, the login page took 1.31 seconds to load, which is not very fast. Three cookies are set: two related to the session and one specifying the current language.

One request is for a stylesheet on a CDN. I would much prefer to host such stuff locally, and I can probably fix this easily myself.

Upon logging in (username: admin, password: admin), the (empty) gallery page loads in only 141ms. There is little network latency since the service is being run on a computer within my LAN, but I am hopeful that only the first page load is slow and subsequent page loads are fast because various resources are already retrieved.

Configuration

There are a variety of languages available, but Japanese is unfortunately not an option. This is not a big problem if the user interface is intuitive enough for common usage. Adding support for a language looks straightforward, so adding a Japanese translation is possible if I decide to use this software.

Upon logging into a service, the first thing to do (perhaps after switching to your desired language) is to change the password. I am very surprised that I am not able to find a way to do so! The only settings I can find are on the settings page, and the “password protection” section does not provide a way to change the password for a user. While you can add and remove other users, the delete icon is disabled for the admin user! If the admin user cannot be deleted and the default password cannot be changed, then anybody can login to a PiGallery 2 site with administrative privileges! Surely this is not the case…

I added a new user, hoping that I would be able to remove the admin user if a different administrative user exists, but the admin user still could not be removed. You can work around the issue by editing the database directly. First, create a new user with the desired password. To use this user as the administrative user (recommended, so that there is no admin user for people to try to hack into), configure the user as an administrator and then delete the admin user from the database. (If you really want to use the admin user, you could alternatively change the password hash for admin to that of the new user.) Note that my hash below is censored. After logging in as the new user, I confirmed that the settings work fine with no admin user. Interestingly, the delete icon for the new user is now disabled.

$ sudo sqlite3 db/sqlite.db
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> SELECT * FROM user_entity;
1|admin|$2b$09$ql3S0uGwc7dpd3SKQxnKWep8EbUgdAi2oyHAzNB91oHk4XTa1lYbS|4|
2|tcard|$2b$09$88888888888888888888888888888888888888888888888888888|4|
sqlite> DELETE FROM user_entity WHERE name = 'admin';
sqlite> SELECT * FROM user_entity;
2|tcard|$2b$09$88888888888888888888888888888888888888888888888888888|4|

Password protection can be disabled altogether. I tried it out, and there is indeed no more login. A warning is displayed indicated that the “sharing” feature is incompatible with the current settings. That feature is disabled automatically, but the warning persists until you update the configuration. From what I can tell, this needs to be done by editing the JSON file since the relevant settings are disabled on the settings screen, which is annoying. Note that this warning is displayed for all visitors, as there is no login when password protection is disabled.

The settings page is still available with password protection disabled, so the settings can be edited by anybody! I have a difficult time thinking of a valid use case for this, as anybody could break or take over the site. Perhaps this is why there is no way to change passwords? It would make much more sense if the software just viewed galleries when password protection is disabled, not allowing any changes. It could be useful for public galleries as well as private galleries that are behind basic authentication.

I turned password protection back on, and it recommended restarting the server. After restarting the server, I reloaded the page and found that I was logged in as an Admin user without providing a password! Perhaps this is an artifact of the session cookies. I logged out and was able to login using my new user.

When password protection was disabled, I experimented with disabling the “search” feature. Now I get a warning that the “faces” feature is not supported without the “search” feature. I do not want to use the “faces” feature anyway, so I tried disabling it, but the warning does not go away! I logged out and logged in again, but the warning persisted. I then logged out, stopped the service, confirmed the settings in the JSON file, restarted the service, and logged in again, and the warning is finally gone. It seems that the service needs to be restarted after configuration, which is pretty annoying but thankfully not something that needs to be done often.

A streak of blue moves across the top of the settings page every 10 seconds, unless at the top of the page. I see that XHR requests are made at the same frequency, and the URL path indicates that they are used to check on job status. The UI artifact is quite annoying, but it is thankfully limited to the settings page!

There are three types of users to select from: admin, user, and guest. I was unable to determine the difference between a user and a guest. Perhaps a user has additional capabilities related to options that I have disabled. I confirmed that neither users nor guests have access to the settings. Attempting to view the settings by changing the URL logs the user out and redirects to the login screen.

The settings allow you to set a URL base! I tried setting it to /photos and adjusted the URL setting accordingly. I restarted the service, and it was completely broken. Trying to access the /photos path resulted in a “404 Not Found” error, and trying to access the root resulted in a screen with a broken image and a “Loading…” message. I confirmed the settings in the JSON file, so I guess this feature just does not work. This is a shame because I would like to serve the photo galleries from a subdirectory. (I can probably make it do what I want on the proxy server using rewrite rules, but working support in the application would be cleaner.)

At one point during my testing, the software broke in an interesting way. Various galleries were created, and I could not figure out why. On the filesystem, I confirmed that the images directory was as expected. The tmp directory was not, so I tried clearing that directory so that the thumbnails could be regenerated. After starting the service and logging in, there were no galleries at all. I tried resetting the database via the settings, as well as simply removing the database from the filesystem, but the problem persisted. That left the JSON configuration as the possible cause, and I found that the images directory had been changed to use the tmp directory instead! I definitely did not do this, so it is an odd issue!

I was able to recreate this strange issue. The images directory setting is changed when I customize the page title! Oddly, attempts to fix the setting within the settings screen do not work, even after restarting the service. This does not inspire confidence in the quality of this software! If I decide to use it, I will save backups of both the JSON configuration and the database after configuring the software in users, before adding any media. That should allow me to quickly revert to a good state if/when the configuration or database gets in a bad state.

If I decide to use this software, I will likely fork it so that I can make some modifications. For example, I would like to get rid of the “Gallery” link in the navigation bar. It is not necessary since it links to the same location as the title. I would also remove the language selection (unless I add Japanese support).

Quite a large part of the settings are included in some JavaScript on the login page (before logging in). This seems a bit suspect, but I guess it does not really matter if attackers can see such configuration settings. If I decide to use this software, perhaps I should make time to do penetration tests.

For the rest of my tests, I stopped the service and removed both the JSON configuration and database, so that I can start from scratch. After re-configuring and preparing users, I created backups of the JSON configuration and database and restarted the service.

PiGallery 2 does not include gallery administration functionality in the user interface. Galleries are created by saving images and videos in the images directory, using directories for organization. In production, I would need to figure out a way to make that work for my wife, using a network mount or perhaps an SFTP client.

I copied a month of photos and videos to a subdirectory under images and then reloaded the gallery page. The new gallery showed up, and clicking on the gallery thumbnail loaded the full gallery without issue. The performance of the first load was faster than I expected, and I confirmed that the thumbnail images are saved in the tmp directory. It even automatically transcodes the .mov videos!

The gallery user interface is very intuitive! We organize photos and videos into monthly galleries, and the gallery page shows a thumbnail image with the name of the directory. It looks like the first image in the directory (when sorted by name) is used as the thumbnail image for the gallery. My wife would very likely want to select the thumbnail image, and I could teach her how to do so by using a filename that sorts first. The galleries are sorted by ascending date by default, which is good for my use case, as it allows family members to quickly see new galleries.

Clicking on a gallery thumbnail image loads that gallery. It loads quickly on my laptop. The layout shows thumbnail images in rows, maintaining the aspect ratio of each image yet fully justifying each row by adjusting the height of the images in each row. It looks quite similar to the layout of Google Photos, but I like it better because the thumbnail images are a bit smaller, allowing you to see more photos at the same time.

When you put the mouse cursor over a thumbnail image, the filename is displayed. The length of videos is displayed next to a video icon at the top right of thumbnail images, making it very easy to distinguish videos. The Google Photos interface is similar, but the font used by PiGallery 2 is much easier to read, which is quite useful for family members with poor vision.

Clicking on a thumbnail image opens the image in a full-page “lightbox” with a near-black background. Controls on the page are dimmed unless the mouse is active. Arrows on the left and right allow you to go to the previous or next image/video. Icons at the top right of the page allow the user to download the file, view information about the file, switch to full screen mode, and close the lightbox. Icons at the bottom right of the page allow the user to start or pause slideshow functionality, available at two speeds. All of these controls are very intuitive, and I do not think that Japanese translations are even necessary!

There are a few issues with the user interface. The most significant is that control icons are displayed using a gray color (that brightens to while on hover) regardless of the background color. Images that have near-white backgrounds can make it impossible to see the control icons. This could be particularly frustrating to family members who want to download an image but are unable to find the download icon. A quick fix for this would be to a near-black outline around the vector shapes that comprise the icons. The outline would not be visible over the lightbox background, and it would make the icons visible when over a light background.

Another issue is that there is a very noticeable flicker when images/videos are displayed. I see it both when transitioning manually or using the slideshow functionality. The flicker would be especially annoying when showing photos to others, perhaps on a big screen or projector.

Aside from these issues, I think that the gallery interface looks great! I really like it! It would be quite a bit better than the Google Photos interface if it were not for the issues.

Next, I tried out the user interface on a tablet. It looks great, but it took many attempts before I was able to open a gallery via touch. Further testing worked fine, so I am not sure what went wrong during that first time. The gallery UI looks great in both portrait and landscape orientations, and I did not have any problems with viewing a photo or using controls using touch. Pinching works fine to zoom in and out on photos, and full screen mode works fine as well. Unfortunately, the flicker issue is even worse on the tablet.

Next, I tried out the user interface on a phone. I did not have any issues with opening the gallery via touch. The user interface looks great even on the especially small screen, and I had no problems using the control icons. Pinching works fine to zoom in and out on photos, and full screen mode works fine as well. Interestingly, I do not have the flicker issue on the phone!

I showed my wife the UI on my phone since it was working perfectly, and of course there was a problem when demoing… When viewing an image, I was no longer able to see any of the control icons! It took me a second to figure out what caused this issue. My wife or I accidentally pinched and zoomed in when viewing the gallery thumbnail images. This caused the browser to zoom in, and the browser remained zoomed in when an image was selected, causing the control icons to be off-screen. Once an image is selected, gestures are controlled by the application, so it is not possible to pan over to the controls. With some images, it is not clear that the browser is zoomed in, so there is no clear indication of what is going wrong. I recreated this issue on the tablet. It is likely that family members would run into this issue and not be able to understand what is wrong even with explanation.

One other thing that I noticed is that each image view creates a new entry in the browser history, making the browser back button pretty useless. Some users may try to use the back arrow at the bottom of Android UIs to go from the gallery view to the gallery list, but this takes them back to the last image viewed, which could be a bit frustrating.

Evaluation

How does PiGallery 2 measure up to my requirements?

Configuration of the software is a mess, but this is not an issue because I would handle that myself (and only need to do it once). Users not being able to change passwords is both bad and good. The bad aspect is that some users may not be happy with the passwords that I assign to them. The good aspect is that such users will not be able to change their password to an insecure one or a password that they use for other purposes.

Gallery administration is done via the filesystem, so it is mostly outside of the scope of the software. The software creates gallery thumbnail images automatically, so my wife would even be able to simply reload the screen as she adds media to a gallery.

Viewing galleries is quite good. The user interface is intuitive, so Japanese translations are not even necessary. Downloading photos and videos is very easy. The most significant issue is control icon contrast, but I can easily fix that. The flicker issue is a significant annoyance. The gallery zoom issue could be a significant frustration for some family members. The user interface works well on tables and phones, aside from the zoom issue.

The software is pretty heavy, but not so much that I would not consider it. I can probably get it to run with a prefix using rewrite rules in the proxy server, and I should be able to run the container without internet access, for improved security. Users must use a username and password for authentication, and the interface does not allow them to change the password.

Image and video format support is excellent. There is no comment functionality. Resource usage is low, so I suspect that it would run fine even on a server with modest specs.

Overall, I am still not sure if I will consider using this software. I would probably overlook the problems if the user interface did not have the flicker issue, because I quite like the user interface otherwise. Given the flicker issue, however, I really hope that I will find better options.