PdfDing on Ubuntu 24.04 on Azure User Guide
Overview
PdfDing is an open source, self hosted PDF manager, viewer and editor. You upload your documents, organise them with hierarchical tags, and read them in a browser based viewer that remembers your position in every file. You can annotate and highlight as you read, mark documents as favourites, search across the library, and share an individual document by link or QR code. The cloudimg image installs PdfDing 1.10.0 as a Django 5.2 application in a dedicated Python virtual environment, served by gunicorn and reverse proxied behind nginx, then locks it down for a marketplace appliance. gunicorn is bound to loopback 127.0.0.1:8000 and never exposed directly; nginx on port 80 is the only way in, plus PdfDing's own unauthenticated /healthz endpoint for load balancer probes.
PdfDing has its own built in authentication and signs users in by email address. This image is secure by default: PdfDing ships no default account of any kind, and on the first boot of every VM a fresh Django secret key is generated and a single administrator account is created with a unique, randomly generated password written to a root only file. Self service registration is closed by default so a public facing instance cannot be enrolled into by strangers. The browser frontend, including the in browser PDF viewer, is compiled and verified as part of the image rather than left for you to build. Backed by 24/7 cloudimg support.
What is included:
- PdfDing 1.10.0 installed in a dedicated Python virtual environment and running as the
pdfdinggunicorn systemd service - The full PdfDing web application on
:80, fronted by nginx with gunicorn bound to loopback only - The complete browser frontend prebuilt, including the pdf.js in browser reader, so the viewer works on first boot
- Built in email based authentication with no default account and a unique administrator password generated on first boot
- A per VM Django secret key generated on first boot, never baked into the image
- Self service registration closed by default, so only accounts you create can sign in
- Host and cookie settings configured so sign in genuinely works on the public IP address or a custom domain
- PdfDing's unauthenticated
/healthzendpoint for Azure Load Balancer health probes pdfding.service(gunicorn) +nginx.serviceas systemd units, enabled and active- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point; PdfDing is light on resources, though a large library benefits from a bigger OS disk since uploaded PDFs are stored on it. NSG inbound: allow 22/tcp from your management network, 80/tcp for the web application, and 443/tcp if you add TLS. PdfDing serves plain HTTP on port 80; for production use, terminate TLS in front of it with your own domain and restrict access to trusted IP ranges (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for PdfDing by cloudimg, and select Create. On Basics 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). Then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name pdfding \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Open port 80 to your network so you can reach the web application:
az vm open-port --resource-group <your-rg> --name pdfding --port 80
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active pdfding.service nginx.service
Both report active. PdfDing runs under gunicorn on the loopback address 127.0.0.1:8000; nginx fronts it on port 80. The application is never bound to a public interface, so nginx is the only way in.

Step 5 - Retrieve your admin credentials
PdfDing signs you in with an email address, not a username. A single administrator account and a unique password are generated on the first boot of your VM and written to a root only file:
sudo cat /root/pdfding-credentials.txt
This file contains PDFDING_USERNAME (the admin email address), PDFDING_PASSWORD and the PDFDING_URL to open in a browser. The file is mode 0600 root:root. PdfDing ships no default account at all, so no shared or predictable credential exists anywhere in the image. Store the password somewhere safe and change it after first sign in (see Maintenance).

Step 6 - Confirm the health endpoint
PdfDing provides an unauthenticated health endpoint for load balancers and probes:
curl -s -o /dev/null -w 'health: %{http_code}\n' http://localhost/healthz
It returns health: 200. This endpoint never requires authentication, so it is safe to point an Azure Load Balancer health probe at it.
Step 7 - Confirm authentication is required
Because PdfDing manages its own login, your document library cannot be reached without signing in. An unauthenticated request to the library returns HTTP 302 and redirects to the sign in page, while the health endpoint stays open:
echo "health : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/healthz)"
echo "library : $(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/pdf/)"
It prints health : 200 and library : 302. Every document view, the tag browser and the settings pages require the per VM administrator password; only the health endpoint is open. gunicorn is bound to loopback and nginx is the only way in.

Step 8 - Confirm the installed version and components
PdfDing runs on Django in a dedicated virtual environment. Confirm the framework version, the PdfDing release and that the core components are in place:
/opt/pdfding/venv/bin/python -c "import django; print('Django', django.get_version())"
sudo grep VERSION /opt/pdfding/app/pdfding/core/settings/version.py
sudo ls -1 /opt/pdfding/venv/bin/gunicorn /opt/pdfding/data/db/db.sqlite3 /etc/systemd/system/pdfding.service
It reports Django 5.2.15, VERSION = 'v1.10.0', and lists the gunicorn binary, the SQLite database and the systemd unit. Confirm the in browser PDF viewer's assets are being served, which is what makes the reader work:
curl -s -o /dev/null -w 'pdf.js viewer: %{http_code}\n' http://127.0.0.1/static/pdfjs/web/viewer.mjs
It returns pdf.js viewer: 200.

Step 9 - Sign in
Browse to http://<vm-public-ip>/. PdfDing shows its sign in page. Enter the email address and password from Step 5. Note that the field is an email address; entering a username will not work.

After signing in you land on your document library. It is empty on a fresh instance, which is exactly as intended: the image ships no sample documents and no other user's data.

Step 10 - Upload your first PDF
Choose the add or upload control in the library to add a document. Give it a name and, optionally, one or more tags, then confirm. PdfDing stores the file on the VM's own disk under /opt/pdfding/data/media and adds it to your library.
Tags are hierarchical: a tag such as finance/invoices creates a nested structure in the sidebar, so a large library stays navigable. You can also mark documents as favourites and filter by tag or search term from the library toolbar.

Step 11 - Read a PDF in the browser viewer
Select a document to open it in PdfDing's built in reader. The viewer runs entirely in your browser and gives you page navigation, zoom, text selection and search within the document. PdfDing remembers the page you stopped on, so reopening a long document returns you to where you were rather than to page one.

Step 12 - Add more users
Self service registration is disabled on this image by default, so a public facing instance cannot be signed up to by strangers. To add another user, open the admin area from the profile menu and create the account there.
If you would rather open self service registration, set DISABLE_USER_SIGNUP=FALSE in the environment file and restart the service:
sudo sed -i 's/^DISABLE_USER_SIGNUP=TRUE/DISABLE_USER_SIGNUP=FALSE/' /opt/pdfding/pdfding.env
sudo systemctl restart pdfding.service
Only do this if the instance is not reachable from the public internet, or if you are comfortable with anyone who can reach it creating an account.
Maintenance
- Password: the administrator password is generated on first boot and stored in
/root/pdfding-credentials.txt(mode0600 root:root). Change it from the web interface under the profile menu -> Settings, which is the recommended route. - Where your documents live: uploaded PDFs, the SQLite database and the consume drop box are all under
/opt/pdfding/dataon the OS disk. Back that directory up, or take Azure disk snapshots, to protect your library. Growing the OS disk is the simplest way to make room for more documents. - Adding a custom domain: PdfDing validates the hostname each request arrives on, so a new domain must be added to
HOST_NAMEin/opt/pdfding/pdfding.envas a comma separated entry, thensudo systemctl restart pdfding.service. If you skip this, requests on the new name are rejected with a bare HTTP 400 even though every service is healthy. - Adding TLS: terminate TLS in front of PdfDing with your own certificate. Once you are serving over HTTPS, set
CSRF_COOKIE_SECURE=TRUEandSESSION_COOKIE_SECURE=TRUEin/opt/pdfding/pdfding.envand restart the service so the session and CSRF cookies are only ever sent over an encrypted connection. These are deliberatelyFALSEon a plain HTTP appliance because browsers refuse to store secure cookies over HTTP, which would make signing in impossible. - Logs:
sudo journalctl -u pdfding.service -ffor the application and gunicorn,sudo journalctl -u nginx.servicefor the reverse proxy. - Updates: the OS is fully patched at build time and continues to receive unattended security updates. PdfDing itself is pinned to the release this image ships; upgrade it deliberately rather than automatically so a schema migration never runs unattended against your library.
- Health probes: point Azure Load Balancer or Application Gateway probes at
/healthz, which returns 200 without authentication.
Support
This image is published and supported by cloudimg with 24/7 support. For product documentation see the PdfDing documentation. For image or deployment questions, contact cloudimg support.