ZFile
Overview
ZFile is an open-source file listing and sharing server for individuals and small teams. It mounts many storage backends side by side, from the local disk of the VM to S3-compatible object storage, OneDrive, SharePoint, Google Drive, WebDAV, FTP and SFTP. It presents them all as one browsable website with share links, direct links, short links and rich in-browser previews, including images with a gallery mode, audio, video, text and code, PDF, Office documents and more.
The SecureAnyCloud image builds ZFile 4.5.0 entirely from the upstream MIT source, backend and web interface both, so the image contains only the open edition. The MIT licence text ships at /opt/zfile/LICENSE. ZFile runs as a systemd service bound to the loopback interface, and nginx on port 80 is the only public surface. First boot configures a ready-to-use "Local Storage" source on a dedicated data disk. 24/7 SecureAnyCloud support backs the image.
What you get:
- ZFile 4.5.0 built from the upstream MIT source (Spring Boot backend under OpenJDK 21 + the Vue 3 web interface), running as the
zfilesystemd service - The ZFile web UI and REST API on port
80, fronted by nginx with ZFile bound to loopback only, and tuned for large uploads (no request size cap) - No default credential of any kind: the image ships uninitialised, and first boot generates a unique per-VM admin password to create the admin account
- A preconfigured "Local Storage" source rooted at
/var/lib/zfile/fileson a dedicated 32 GiB Azure data disk, which also holds the embedded SQLite database - Share links, direct links and short links per file or folder, with optional passwords and expiry
- An unauthenticated
/healthzendpoint on:80for Azure Load Balancer health probes zfile.service+nginx.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
Good to know: The ZFile web interface is presented in Chinese, the language of the upstream project. The layout is a conventional file manager, you can reproduce every workflow in this guide from the screenshots alone, and browser page translation works well with it. A fresh VM is also private by default: anonymous visitors see an empty site until you either sign in or explicitly grant anonymous view permissions on a storage source (Step 9).
Prerequisites
- An active Azure subscription, an SSH key pair, and a VNet and subnet in the target region
- Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point for a personal or small-team file server. Size up for heavy concurrent transfer workloads
- NSG inbound rules that allow
22/tcpfrom your management network,80/tcpfor the web UI, and443/tcpif you add TLS - ZFile serves plain HTTP out of the box. For production use, front it with TLS on your own domain
Step 1 - Deploy from the Azure Marketplace
- Sign in to the Azure Portal.
- Choose Create a resource, search the Marketplace for ZFile by SecureAnyCloud, and select Create.
- On the Basics tab, pick your subscription, resource group, region and size.
- Under Administrator account, choose SSH public key and paste your key.
- Under Inbound port rules, allow SSH (22) and HTTP (80).
- On the Disks tab, review the dedicated data disk.
- Select Review + create, then Create.
Step 2 - Deploy from the Azure CLI
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:zfile:default:latest
az vm create \
--resource-group <your-rg> \
--name zfile \
--image sac1647283583153:zfile:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name zfile --port 80 --priority 1010Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>Step 4 - Confirm the services are running
systemctl is-active zfile.service nginx.serviceBoth services report active. ZFile itself listens only on the loopback address 127.0.0.1:8080, and nginx fronts port 80 as the only public surface. The embedded SQLite database (db/) and the Local Storage file root (files/) live on the dedicated data disk mounted at /var/lib/zfile:
findmnt -no SOURCE,SIZE,FSTYPE /var/lib/zfile ls -l /var/lib/zfileStep 5 - Retrieve your admin password
The image ships with no account at all. On the first boot of your VM, a unique admin password is generated, the admin account is created with it, and the password is written to a root-only file. Read the file with:
sudo cat /root/zfile-credentials.txtThe file contains ZFILE_URL, ZFILE_USERNAME (admin) and ZFILE_ADMIN_PASSWORD. Store the password somewhere safe. The MIT licence and the full source provenance for the build also ship in the image:
head -2 /opt/zfile/NOTICE.txtStep 6 - Confirm the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/healthzThe endpoint returns ok. It never requires authentication, so it is safe for an Azure Load Balancer health probe.
Step 7 - Confirm the authentication gate
The following commands read the per-VM password from the credentials file and prove the round trip. A wrong password is rejected, and the correct password authenticates:
PW=$(sudo grep '^ZFILE_ADMIN_PASSWORD=' /root/zfile-credentials.txt | cut -d= -f2-)
curl -s -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"wrong-pw"}' http://127.0.0.1/user/login | jq -r '.code'
curl -s -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$PW\"}" http://127.0.0.1/user/login | jq '{code, admin: .data.admin}'The wrong password returns error code 42001. The per-VM password returns code "0" with admin: true. Anonymous visitors cannot list files, because a fresh VM is private until you sign in or grant anonymous permissions (Step 9).
Step 8 - Sign in and browse your files
In a browser, go to http://<vm-public-ip>/ and click through to the sign-in page. You can also open http://<vm-public-ip>/login directly. Enter admin and the password from Step 5.
After you sign in, the home page lists your storage sources. The preconfigured Local Storage source is already there.
Click Local Storage to enter the file browser. The welcome README.txt that the image seeds is listed with its timestamp and size. Use the toolbar icons to upload files, create folders and switch to gallery view. Right-click a file for the rename, copy, move, delete, direct link and share link actions.
Double-click README.txt to preview it. Text and code files open in an in-browser editor, and images, audio, video, PDF and Office documents each get their own preview.
Step 9 - Manage storage sources and permissions
Click the settings icon, or browse to http://<vm-public-ip>/admin, to reach the admin area. Under the storage source settings, you can edit the preconfigured Local Storage source or add more sources: S3-compatible object storage, OneDrive, SharePoint, Google Drive, WebDAV, FTP, SFTP and others. Each source appears alongside Local Storage on the home page.
A fresh VM is private by default: anonymous visitors see an empty storage list. To publish a source as a public file library, open the permission settings of the source in the admin area and grant the anonymous role the view permission, and optionally the download permission. The multi-user system under user management lets you create additional accounts scoped to specific sources or directories.
Step 10 - Upload a file and share it by link
Everything in the UI is also scriptable through the same REST API, which is how the image proves itself on every boot. The following commands upload a file through the API, generate a share link for it, and download it back through the share link:
PW=$(sudo grep '^ZFILE_ADMIN_PASSWORD=' /root/zfile-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -s -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$PW\"}" http://127.0.0.1/user/login | jq -r '.data.token')
echo 'hello from zfile on azure' > hello.txt curl -s -X PUT -H "zfile-token: $TOKEN" -F 'file=@hello.txt' \
http://127.0.0.1/file/upload/local/hello.txt | jq -r '.code + " " + .msg'
SHARE=$(curl -s -H 'Content-Type: application/json' -H "zfile-token: $TOKEN" \
-d '{"storageKey":"local","sharePath":"/","shareEntries":[{"name":"hello.txt","type":"FILE"}],"shareType":"FILE"}' \
http://127.0.0.1/api/share/create | jq -r '.data.shareKey')
curl -s -L "http://127.0.0.1/api/share/download/$SHARE?path=/hello.txt"The upload returns 0 ok, and the share link download prints hello from zfile on azure. This is a byte-identical round trip through nginx on port 80.
In the web UI, the same share action is on the right-click menu of the file. You can send the generated http://<vm-public-ip>/share/<key> page to anyone. Share links support optional passwords and expiry dates.
Server components
Component Version Detail
ZFile 4.5.0 Built from the upstream MIT source (backend + web UI), /opt/zfile/app.jar + /opt/zfile/static/
OpenJDK 21 (headless JRE) Runtime for the Spring Boot backend
nginx Ubuntu 24.04 archive Port 80 reverse proxy, the only public surface
SQLite embedded ZFile's database at /var/lib/zfile/db/zfile on the data disk
Ubuntu 24.04 LTS Fully patched at image capture, unattended security upgrades enabled
Filesystem layout
Mount Point Size Description
/ 30 GB Root filesystem
/boot/efi 1 GB UEFI boot partition (Gen2 Hyper V)
/var/lib/zfile 32 GB Dedicated data disk: db/ (SQLite database) + files/ (Local Storage root)
/mnt varies Azure temporary resource disk
Key directories:
Path Purpose
/opt/zfile/app.jar The ZFile server (built from MIT source)
/opt/zfile/static/ The web interface (built from MIT source)
/opt/zfile/LICENSE The MIT licence text
/opt/zfile/NOTICE.txt Source provenance (repos, tag, commit)
/var/lib/zfile/files/ Local Storage source root - uploaded files land here
/var/lib/zfile/db/ Embedded SQLite database
/var/log/zfile/ Application logs
/root/zfile-credentials.txt Per-VM admin credentials (root only, 0600)
Managing the service
sudo systemctl status zfile.service
# status
sudo systemctl restart zfile.service
# restart ZFile
sudo systemctl restart nginx.service
# restart the reverse proxy
sudo journalctl -u zfile.service -e
# recent logsTroubleshooting
The web UI shows an empty site or "please select a storage source" with nothing listed
You are browsing anonymously. A fresh VM is private by default. Sign in as admin (Step 5) to see the preconfigured Local Storage source, or grant anonymous view permissions on the source (Step 9) to publish it.
Sign in fails
Re-read the exact password with sudo cat /root/zfile-credentials.txt (the value after ZFILE_ADMIN_PASSWORD=). Repeated failed logins are rate-limited to 10 per minute, so wait a minute and retry.
HTTP 502 from nginx
ZFile is starting or has stopped. Check systemctl status zfile.service and sudo journalctl -u zfile.service -e. The Java backend takes roughly 20 to 40 seconds to start on a B2s VM.
Uploads fail for large files
nginx on this image imposes no request size cap (client_max_body_size 0), so check free space on the data disk first with df -h /var/lib/zfile. To grow the disk, resize the Azure data disk and then the filesystem (sudo resize2fs /dev/disk/azure/scsi1/lun0).
I locked myself out / lost the admin password
ZFile stores the password only as a hash inside the database. The simplest recovery on a fresh appliance is to run sudo systemctl stop zfile nginx, sudo rm -rf /var/lib/zfile/db, sudo rm /var/lib/sac/data/zfile-firstboot.done /var/lib/sac/data/zfile-bootstrap-ready, and then sudo reboot. First boot runs again, regenerates a fresh password into /root/zfile-credentials.txt and recreates the Local Storage source. This resets the ZFile settings and accounts. Files under /var/lib/zfile/files are untouched.
On startup
zfile-firstboot.service runs once on the first boot of the VM. It generates the unique admin password, initialises ZFile with it, creates the Local Storage source, proves a real upload round trip through the API and writes /root/zfile-credentials.txt. Only then does it allow nginx, the public surface, to start, so the site is never reachable in an uninitialised state. On every later boot, the service exits immediately (sentinel file /var/lib/sac/data/zfile-firstboot.done).
Security recommendations
- Add TLS for production: Front the VM with your own domain and terminate TLS on
:443(for example with certbot), then restrict:80in your NSG. - Keep anonymous access deliberate: Grant anonymous permissions only on sources that you intend to be public. Use the per-source password and the multi-user system for anything else.
- Restrict SSH: Limit
22/tcpto your management IP range in the NSG. - Loopback binding: ZFile is bound to
127.0.0.1:8080in/etc/systemd/system/zfile.service. Keep it that way, because nginx is the only intended public path. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Deploy on Azure
Launch ZFile File Listing and Sharing Server 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