Damselfly
Overview
Damselfly is a self-hosted, server-based photograph management and de-duplication application. It indexes an extremely large collection of images and makes them easy to search and retrieve by metadata such as IPTC keyword tags, folder names and file names. It serves a modern browser interface for browsing, tagging and downloading, with optional on-device object and face recognition. Your photos, the thumbnail cache and the search index live on a dedicated data disk mounted at /var/lib/damselfly. This guide covers deploying and configuring it on Ubuntu 24.04 on Azure with the SecureAnyCloud Azure Marketplace image.
Stock Damselfly ships with authentication turned off, which would leave every image open to anyone who can reach the server. When authentication is enabled, the first person to register becomes the administrator. This image turns authentication on, disables self-registration, and generates a unique administrator credential on each virtual machine's first boot.
Damselfly's database stores only a one-way (PBKDF2) hash of the password. The plain password is placed in a root-only file for the administrator to read. No shared or default credentials exist.
What you get:
- The official Damselfly container (built on .NET, hosted Blazor WebAssembly), with the exact image digest pinned and recorded in
/opt/damselfly/VERSION. It runs under Docker, managed by a systemd unit. - Damselfly published to loopback only (
127.0.0.1:6363), so it is never exposed to the network directly. - nginx as the sole network-facing surface. It terminates TLS on port 443 and reverse proxies to Damselfly on
127.0.0.1:6363, with HSTS and sensible security headers. Port80redirects to HTTPS. - Port
:80returns a301redirect to HTTPS for every path except an unauthenticated/healthzendpoint (HTTP 200) for load balancer probes. - Authentication on by default with a unique admin credential generated per VM on first boot. Self-registration is disabled, the database stores only the one-way hash, and the plain password lands in a root-only file.
- A dedicated data disk mounted at
/var/lib/damselfly, provisioned automatically with every VM. It holds your photos (pictures/), the search index and config (config/) and the thumbnail cache (thumbs/). - A small set of sample photos so the gallery is populated the moment you sign in. Replace them with your own.
- Optional object and face recognition, included in the image but off by default. Enable it from the Config page when you want it.
- A self-signed TLS certificate regenerated per VM on first boot. Its Subject Alternative Names include the VM IP, hostname and
127.0.0.1. Replace it with your own CA-signed certificate for production. - A built-in self-test at
/usr/local/bin/damselfly-selftestthat proves the authenticated login end to end over TLS. - An Ubuntu 24.04 LTS base with the latest security patches applied at build time.
- The Azure Linux Agent for cloud integration and SSH key injection.
- 24/7 SecureAnyCloud support with a guaranteed 24 hour response SLA.
Prerequisites
- An Azure subscription with permission to deploy virtual machines.
- An SSH key pair for administrative access to the VM as the
azureuseraccount. - A Network Security Group that allows inbound TCP
443(HTTPS) and80(redirect) from the networks that should reach the gallery, and22(SSH) from your management network only. - A recommended VM size of Standard_B2s or larger. Use a larger size such as Standard_D2s_v3 if you plan to enable object and face recognition.
Deploy from the Azure Portal
- Find the Damselfly on Ubuntu 24.04 LTS image in the Azure Marketplace and select Create.
- Choose your subscription, resource group and region.
- Select a VM size (Standard_B2s or larger) and provide your SSH public key for the
azureuseraccount. - On the Networking tab, allow inbound
443and80from your users, and restrict22to your management network. - Select Review + create. When the VM is running, browse to
https://<your-public-ip>/.
Deploy from the Azure CLI
Deploy the image from the command line and restrict SSH to your management network. Replace the example values with your own:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:damselfly-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name damselfly \
--image sac1647283583153:damselfly-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard
# Allow the gallery from your users and SSH from your management network only
az vm open-port --resource-group my-resource-group --name damselfly --port 443 --priority 1001
az network nsg rule create --resource-group my-resource-group --nsg-name damselflyNSG \
--name allow-ssh --priority 1002 --destination-port-ranges 22 \
--source-address-prefixes <your-mgmt-cidr> --access Allow --protocol TcpWhen the VM is running, browse to https://<public-ip>/.
Retrieve your per-instance admin credential
Authentication is on by default. Each VM generates its own admin credential on first boot and writes it to a root-only file. Read the file over SSH:
ssh azureuser@<vm-ip> 'sudo cat /root/damselfly-credentials.txt'The file contains the DAMSELFLY_USER, DAMSELFLY_EMAIL, DAMSELFLY_PASS and DAMSELFLY_URL for this VM. Keep it secret. Damselfly's database stores only a one-way hash of the password, never the plain text.
Sign in to Damselfly
Browse to https://<vm-ip>/. The certificate is self-signed per VM, so your browser shows a certificate warning the first time. Accept it to proceed, or install the per-VM certificate, or place a CA-signed certificate in front as described in Step 10. Damselfly then shows a login screen.
Sign in with the email address and password from Step 3. The login uses the email, not the username.
Damselfly opens on the gallery, which shows the photos in your library as a responsive grid. The included sample photos are visible immediately, with the search bar and the Basket, Keywords and Folders panels alongside them. The status bar shows the signed-in admin user.
View and browse your photos
Click a photo to open it in the full image view. The toolbar lets you move between images, download, rotate and zoom. The side panels show the image keywords and any map data.
Damselfly reads folder and file names, so subfolders of your library appear as browsable folders in the Folders panel.
Add your own photos
Your library reads from /var/lib/damselfly/pictures on the dedicated data disk. Copy your own photos and videos into that folder, keeping any subfolder structure that you want as folders. Then rescan from the UI to index them:
# Copy your photos into the library folder (use sudo; the folder is on the data disk)
sudo cp -r ~/my-photos/. /var/lib/damselfly/pictures/Damselfly indexes the library in the background and picks up new folders automatically. You can also trigger a rescan from the UI.
Thumbnails are written to /var/lib/damselfly/thumbs and the search index to /var/lib/damselfly/config, both on the same data disk. The data disk is captured with the image and re-attached to every VM, so your photos and index survive a redeploy of the OS disk.
Manage settings and enable recognition
The signed-in admin user can open the Config page to manage settings, users, image recognition and more.
Object and face detection are included in the image but off by default, so nothing runs until you turn it on. To search your library by its content, enable them under the Image Recognition tab. The User Management tab lets you add further users and roles.
Verify the deployment
SSH to the VM as azureuser and confirm that the services are running and Damselfly is published on loopback only:
systemctl is-active docker damselfly nginx
sudo ss -tlnp | grep 6363All three services report active, and Damselfly is published on 127.0.0.1:6363 only. nginx is the only component exposed on :80 and :443.
Run the built-in self-test. It reads this VM's credential and proves the full round trip over TLS. Authentication is enforced, a login with a wrong password is refused, and a login with the per-VM credential returns a signed token:
sudo /usr/local/bin/damselfly-selftestCheck TLS, authentication and the per-instance certificate
nginx terminates TLS on port 443 and redirects plain HTTP on port 80 to HTTPS. Confirm the redirect and the unauthenticated health probe from the VM:
curl -s -o /dev/null -w 'port 80 -> HTTP %{http_code}\n' http://127.0.0.1/
curl -sk -o /dev/null -w 'healthz over TLS -> HTTP %{http_code}\n' https://127.0.0.1/healthzPort 80 returns 301 and the health endpoint returns 200. A login with a wrong password is refused, while a login with this VM's credential returns a signed token. The ForceLogin setting confirms that authentication is enforced.
The self-signed certificate is regenerated per VM on first boot, with the VM IP and hostname in its Subject Alternative Names.
Replace the certificate for production
The per-VM certificate is self-signed, so browsers warn on first use. For a public deployment, put a real certificate in front. The simplest approach is to point a DNS name at the VM and obtain a free certificate with Certbot:
# Point https://<your-domain> at this VM first, then:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>Alternatively, terminate TLS at an Azure Application Gateway or a load balancer in front of the VM, and forward to port 443.
Check the version and credential summary
The pinned image digest is recorded in /opt/damselfly/VERSION, and this VM's credential summary is recorded on the VM. Read the full credential value from the root-only file in Step 3.
Security notes
- No default login. Authentication is on by default, self-registration is disabled and a unique admin credential is generated on each VM's first boot. Damselfly's database stores only a one-way hash. The plain password lives in the root-only file
/root/damselfly-credentials.txt. The stock no-login default and the first-to-register administrator are never shipped. - Loopback-only application. Damselfly is published on
127.0.0.1:6363and is reachable only through the nginx TLS reverse proxy on:443. Keep it that way, and let nginx (or a load balancer) be the sole network-facing surface. - Data on a dedicated disk. Your photos, thumbnail cache and index live on the data disk at
/var/lib/damselfly, separate from the OS disk. Back up this disk to protect your library. - Restrict access. Allow
443only from the networks that need it, keep22restricted to your management network, and replace the self-signed certificate with a CA-signed one for production. - Recognition is opt-in. Object and face detection run on the device and are off by default. Enable them from the Config page when you want them. They use additional CPU, so size the VM accordingly.
Support
This image is backed by 24/7 SecureAnyCloud support with a guaranteed 24 hour response SLA. Contact sales@secureanycloud.com for assistance.
Damselfly is open-source software distributed under the GNU General Public License v3.0 and is free. The SecureAnyCloud charge covers packaging, hardening, security patching, image maintenance and support.
Deploy on Azure
Launch Damselfly on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Damselfly 4.5.3 is an open-source, self-hosted, server-based photograph management and de-duplication application. This image delivers it fully installed and secured behind an nginx TLS reverse proxy. Damselfly indexes an extremely large collection of images and makes them fast to search and retrieve by IPTC keyword tags, folder names and file names. It has a modern browser interface for browsing, tagging, basket and download, with optional on-device object and face detection.
Damselfly runs as the official webreaper/damselfly container, pinned by digest, under systemd. It is published on the host loopback interface only. nginx sits in front on port 443 and terminates TLS with a per-instance self-signed certificate. It also proxies the SignalR WebSocket traffic that the UI relies on. Port 80 redirects to HTTPS.
Your photo library, the SQLite search index and the thumbnail cache all live on a dedicated, independently resizable EBS data volume mounted at /var/lib/damselfly, separate from the operating system disk. Damselfly is licensed under the GNU General Public License v3.0.
Secure by default
Stock Damselfly ships with authentication turned off, which leaves every image open to anyone who can reach the server. Once authentication is enabled, the first person to register becomes the administrator. This image works differently:
- Damselfly's own authentication is on by default (
ForceLogin), self-registration is disabled, and a singleadminuser is seeded. - An nginx HTTP Basic Auth gate sits in front of the whole application. Damselfly's
ForceLoginprotects only the Blazor UI. Its raw-image and REST endpoints (for example/rawimage/{id}) are not auth-checked on their own, so without this gate anyone who could reach port 443 could download the photo library. With the gate, the login page is the only surface reachable without a credential, apart from the/healthzload-balancer probe. - A unique administrator password is generated on each instance's first boot. It is used for both the nginx gate and the Damselfly login, and is written to a root-only file. The database stores only a one-way PBKDF2 hash, never the plaintext.
- The security group opens only SSH (22) and HTTPS (443). The application itself is bound to loopback and is never exposed over plain HTTP or left world-open.
There are no shared or default credentials, and nothing is baked into the image, so no two deployments are the same.
Connecting to your instance
Connect over SSH on port 22 using the default login user for your operating system variant and the EC2 key pair that you launched with.
For Ubuntu 24.04, the SSH login user is ubuntu. For example: ssh -i your-key.pem ubuntu@<instance-public-ip>
Replace <instance-public-ip> with your instance's public IPv4 address, or its private address if you reach it over a VPN or Direct Connect. Scope the security group's 22 and 443 rules to your own network.
Retrieve your admin password
Each instance generates its own admin credential on first boot and writes it to a root-only file. Read the file over SSH:
sudo cat /root/damselfly-credentials.txtThe file shows the admin username (admin), the login email (admin@damselfly.local), the per-instance password and the HTTPS URL for your instance. Keep this file secret.
Sign in
Open Damselfly in your browser over HTTPS:
https://<instance-public-ip>/Signing in is a two-step flow, and the same password is used for both steps:
- The certificate is self-signed per instance, so your browser shows a one-time certificate warning. Accept it to proceed. For production, replace the certificate with a CA-signed one (see the HTTPS section below).
- Your browser then shows an HTTP authentication prompt. This is the nginx security gate that keeps the photo library private. Enter username
adminand the password from the credentials file. - Damselfly's own Log In page then appears. Sign in with the email (
admin@damselfly.local) and the same password.
After you sign in, you land on the gallery. A small set of sample photos is included so the gallery is populated immediately, with a folder tree, keyword tagging, a basket for downloads, and a fast search bar across the top.
Adding your own photos
Your library lives on the dedicated data volume at /var/lib/damselfly/pictures. Copy your own photos there, then rescan from the UI. For example, upload from your workstation with rsync. Replace the example paths and address with your own:
rsync -av -e "ssh -i your-key.pem" /path/to/your/photos/ ubuntu@<instance-public-ip>:/tmp/df-upload/
sudo rsync -a /tmp/df-upload/ /var/lib/damselfly/pictures/ && rm -rf /tmp/df-uploadDamselfly watches the pictures folder and indexes new files automatically. You can also trigger a rescan from the folder view. The library is on its own EBS volume, so you can grow it independently of the operating system disk as your collection expands.
Optional object and face recognition
Damselfly can scan your images locally, on the device, to detect objects and faces so you can find photos by what is in them. This is off by default to keep CPU usage low. The bundled ONNX models run on the CPU only, with no GPU and no external service.
To enable it, open Config -> Image Recognition and complete these steps:
- Tick Scan images locally for objects/faces using AI.
- Untick Disable object detection scanner.
- Set a CPU usage limit that suits your instance.
- Save.
Configuration
The Config page, which you open from the admin link in the footer, groups every setting. It covers user settings and theme, image recognition, email notifications, WordPress publishing, user management and system settings.
Verifying the deployment
The checks below confirm that the appliance is healthy. Run them over SSH.
The appliance has three services: the Docker runtime, the Damselfly container and the nginx TLS proxy. All three should report active:
systemctl is-active docker.service damselfly.service nginx.serviceThe unauthenticated health probe on the HTTPS listener returns 200, and plain HTTP on port 80 returns a 301 redirect to HTTPS:
curl -ks -o /dev/null -w 'healthz -> %{http_code}\n' https://127.0.0.1/healthz
curl -s -o /dev/null -w 'port 80 -> %{http_code} %{redirect_url}\n' http://127.0.0.1/The Damselfly container is published on the host loopback interface only (127.0.0.1:6363), never on a public address. nginx is the sole network-facing surface:
ss -H -tln 'sport = :6363'Print the exact Damselfly version and pinned image digest shipped in this AMI:
cat /opt/damselfly/VERSIONList the sample photos that populate the gallery on first launch:
ls -1 /var/lib/damselfly/picturesFinally, run the built-in self-test. It proves the end-to-end security model over TLS in one command. Authentication is enabled, a wrong password is refused, and the per-instance credential authenticates and returns a JWT:
/usr/local/bin/damselfly-selftestA healthy instance prints OK damselfly self-test passed: auth enabled (ForceLogin), wrong pw refused, per-VM login returns a JWT (TLS).
Enabling HTTPS with your own certificate
The image ships a per-instance self-signed certificate at /etc/nginx/tls/damselfly.crt and /etc/nginx/tls/damselfly.key, which is why browsers show a warning. For production, point a DNS name at your instance, replace the certificate with a CA-signed one (for example from Let's Encrypt), and reload nginx. Keep the security group's 443 rule scoped to the networks that should reach your photo library.
Support
SecureAnyCloud provides 24/7 technical support for this product by email and live chat. Our engineers help with deployment, library configuration, TLS and certificate setup, object and face recognition tuning, data-volume sizing and runtime tuning.
- Email: sales@secureanycloud.com
- Live chat: available 24/7 through the SecureAnyCloud support portal
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com