Directory Lister
Overview
Directory Lister is a lightweight web application that turns a directory of files into a clean, styled listing in the browser. It is published at github.com/DirectoryLister/DirectoryLister. It needs no database. It reads files straight from the filesystem and renders a browsable listing with breadcrumb navigation, file search, inline README rendering, single-file downloads and on-the-fly zip downloads of whole folders.
This guide covers deploying Directory Lister on Ubuntu 24.04 on Azure from SecureAnyCloud Azure Marketplace images. The image installs Directory Lister 5.6.1 served by nginx and PHP 8.3 FPM, with the application running under a dedicated non-root service account. Unattended security upgrades keep the server patched on your running VM.
What you get:
- Directory Lister 5.6.1 served by nginx and PHP 8.3 FPM under a dedicated non-root service account. A strict nginx allowlist serves only the compiled front-end assets and the application's rendered listing.
- A safe, self-contained demo directory as the served root. The served root is the
open_basedirceiling, so traversal above it is refused. - A first-boot service that prepares each instance, and a bootstrap gate that holds the web services until preparation is complete.
One appliance, one web application. nginx and php8.3-fpm serve the whole site on port 80. There is no database and no mail engine, and port 80 is the only network-reachable service.
A safe served root, hardened for a file browser. The appliance serves a dedicated, self-contained demo directory (/var/www/dirlister/files). It never serves the server filesystem, the application's own source or any sensitive path.
Directory Lister protects file access through PHP open_basedir. This image makes the served directory the open_basedir ceiling, and the application code lives in a hidden subdirectory inside the served root. As a result:
- Path traversal above the served root is refused. Relative paths (
../), URL-encoded sequences and symlinks that point outside the served directory all return404. No file outside the served directory can be read. - The application's own configuration, environment file and source are never listed or served. They are excluded from the listing, from search and from zip archives, and they return
404over HTTP. - nginx never renders a raw directory index. Only Directory Lister's own rendered listing of the served files is shown.
Public and read-only by design, with no credential in the image. The demo listing is public and read-only. There is no login and no secret anywhere in the image. For a private listing, you can enable Directory Lister's built-in password protection yourself (see Step 13).
On first boot, a one-shot service prepares each instance: it resolves the VM's address and writes an information file. A bootstrap marker then lets nginx and php8.3-fpm start. Until that marker exists, systemd skips those units, so the site never serves a half-prepared instance. The units are enabled, so the appliance comes straight back after a reboot.
Prerequisites
- An Azure subscription, and either the Azure Portal or the Azure CLI (
az) signed in. - An SSH key pair so you can administer the VM.
- Inbound TCP port 80 open to the browsers that will reach the listing, and port 22 open for administration.
Deploy from the Azure Portal
- Open the SecureAnyCloud Directory Lister on Ubuntu 24.04 LTS offer in Azure Marketplace and choose Create.
- Pick a resource group and region. Keep the recommended Standard_B2s size, because Directory Lister is small and runs comfortably on 2 vCPU / 4 GB. Provide your SSH public key for the
azureuseraccount. - On the Networking step, allow inbound 80 (the web application) and 22 (SSH). Directory Lister serves over port 80. For TLS, put it behind an Azure Application Gateway or a reverse proxy.
- Create the VM, then browse to its public IP address to see the demo directory listing.
Deploy from the Azure CLI
# Replace <sub-id> and <version> with your subscription and the image version. IMAGE_URN="sac1647283583153:directory-lister-ubuntu-24-04:default:latest" az group create --name directory-lister-rg --location eastus
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:directory-lister-ubuntu-24-04:default:latest
az vm create \
--resource-group directory-lister-rg \
--name directory-lister \
--image "$IMAGE_URN" \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group directory-lister-rg --name directory-lister --port 80First boot and the appliance information
On first boot, a one-shot service resolves the VM's address and writes an information file. There is no credential, because the listing is public and read-only by design. Read the information file over SSH.
sudo cat /root/directory-lister-info.txtThe file records the listing URL and the served directory.
DIRECTORY_LISTER_URL=http://<your-service-ip>/ DIRECTORY_LISTER_SERVED_ROOT=/var/www/dirlister/filesConfirm the appliance is running
This check confirms that both web services are active, that PHP 8.3 and nginx report their versions, that the application runs as the dedicated non-root dirlister account, and that port 80 is the only listener.
sudo systemctl is-active php8.3-fpm nginx php -v | head -1 nginx -v id dirlister
sudo ss -tulnp | grep ':80 'Browse the demo directory
Browse to the VM's address. The demo directory appears as a clean, styled listing with the data, documents and images folders and the README.md file, rendered inline. Each entry shows its size and modified date. The page also has a search box and a download control.
Open a folder and download files
Click a folder to browse into it. Each file shows its size and modified date. Click a file to download it. To download the whole folder as a zip archive, use the download control in the breadcrumb bar.
Search the listing
Type in the search box to filter the listing by file name. Directory Lister searches the served directory and shows the matching files with their paths.
Light and dark themes
Directory Lister ships light and dark themes. Use the theme toggle in the top bar to switch. The listing shows the same content in either theme.
Serve your own directory
To publish your own files, set FILES_PATH in the application environment file to your directory, then restart the web services.
# Point Directory Lister at your own directory of files:
# 1. Edit the environment file and set FILES_PATH to your directory:
sudo nano /var/www/dirlister/files/.dirlister-app/.env
# set FILES_PATH=/path/to/your/files
# 2. Restart the web services:
sudo systemctl restart php8.3-fpm nginxKeep your served directory self-contained and free of sensitive files, as the shipped demo directory is. The traversal and configuration protections shown in the next two steps apply to whatever directory you serve.
Path traversal above the served root is refused
The served root is a dedicated directory. Any attempt to read a file above it, with relative paths, URL-encoded sequences or symlinks, returns 404. Nothing outside the served directory can be read.
# relative-path traversal curl -s -o /dev/null -w '?dir=../../../../etc -> HTTP %{http_code}\n' 'http://127.0.0.1/?dir=../../../../etc' curl -s -o /dev/null -w '?file=../../../../etc/passwd -> HTTP %{http_code}\n' 'http://127.0.0.1/?file=../../../../etc/passwd'
# URL-encoded traversal curl -s -o /dev/null -w 'url-encoded traversal -> HTTP %{http_code}\n' 'http://127.0.0.1/?file=..%2f..%2f..%2f..%2fetc%2fpasswd'
# and nothing from /etc/passwd is ever returned:
echo "leaked /etc/passwd lines: $(curl -s 'http://127.0.0.1/?file=../../../../etc/passwd' | grep -c 'root:.*:0:0' || true)"The application's own config and source are never served
The application's environment file, configuration and source live in a hidden subdirectory inside the served root. They are excluded from the listing and return 404 over HTTP. The compiled front-end assets are served normally.
curl -s -o /dev/null -w 'GET /.env -> HTTP %{http_code}\n' 'http://127.0.0.1/.env'
curl -s -o /dev/null -w 'GET /app/config/app.php -> HTTP %{http_code}\n' 'http://127.0.0.1/app/config/app.php'
curl -s -o /dev/null -w '?file=.dirlister-app/.env -> HTTP %{http_code}\n' 'http://127.0.0.1/?file=.dirlister-app/.env'
# the app directory never appears in the rendered listing:
echo "app dir in listing: $(curl -s 'http://127.0.0.1/' | grep -c 'dirlister-app' || true) (0 = hidden)"How the first-boot gate works
nginx and php8.3-fpm each wait for a bootstrap marker. The first-boot service writes the marker only after it has prepared the instance. Until the marker exists, systemd skips those units. The units are enabled, so they survive a reboot.
grep -h ConditionPathExists /etc/systemd/system/nginx.service.d/*.conf /etc/systemd/system/php8.3-fpm.service.d/*.conf
sudo ls -l /var/lib/sac/data/
sudo systemctl is-enabled php8.3-fpm nginx directory-lister-firstbootSecurity recommendations
- Keep the served directory self-contained. Serve a dedicated directory that holds only the files you want to publish. Do not point
FILES_PATHat a home directory, a system path or anywhere that holds secrets. The traversal protection stops reads above the served root, but everything inside the served directory is browsable by design. - Enable password protection for a private listing. Directory Lister supports built-in password and hash directory protection. Enable it if the listing should not be public. See the Directory Lister configuration documentation.
- Put TLS in front. Serve over HTTPS with an Azure Application Gateway, a load balancer, or a reverse proxy such as Caddy or nginx with a certificate.
- Restrict inbound access. Use an Azure Network Security Group to limit who can reach ports 80 and 22.
- Keep the OS patched. Unattended security upgrades are enabled. Reboot periodically to apply kernel updates.
Support and licensing
Directory Lister is open-source software distributed under the MIT License. The license text ships in the image at /var/www/dirlister/files/.dirlister-app/LICENSE. This SecureAnyCloud image bundles Directory Lister with nginx and PHP on Ubuntu 24.04 and adds the security hardening, first-boot preparation and deployment tooling described above.
SecureAnyCloud provides 24/7 support for this image by email (sales@secureanycloud.com) and live chat. Support covers:
- Deployment.
- Pointing the listing at your own directory.
- Sort and hidden-file rules.
- Themes and titles.
- Enabling password protection.
- Zip and download behavior.
- Serving over HTTPS.
- Directory Lister version upgrades.
All product and company names are trademarks or registered trademarks of their respective holders.
Deploy on Azure
Launch Directory Lister 5.6.1 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