Deployment guide

Animal Shelter Manager

Overview

Animal Shelter Manager (ASM3) is a long-established open source management system for animal shelters, rescues and sanctuaries. It runs their day-to-day operations from one web application. Staff and volunteers record every animal that arrives, with its intake reason, species, breed and location on site, then follow it through fostering, reservation, adoption or return to owner.

Alongside the animal record, ASM3 manages medical and vaccination schedules, diary entries and tasks, waiting lists, and lost-and-found matching. It also covers the people side of the shelter: adopters, fosterers, volunteers, donors and veterinary contacts. Built-in reports and shelter views turn that data into the figures a shelter has to produce.

This SecureAnyCloud image installs ASM3 from the pinned upstream release and runs it as an unprivileged system user behind nginx. It bundles a tuned single-node PostgreSQL database on the same VM, so the appliance is self-contained.

What you get:

  • Animal Shelter Manager 3, installed from the pinned upstream tag 51-1 (GPL-3.0), laid out where upstream's own Debian package puts it (/usr/lib/sheltermanager3, config /etc/asm3.conf)
  • A bundled PostgreSQL 16 database on the same VM, tuned for the VM size rather than left at stock defaults, listening on loopback only
  • The application bound to 127.0.0.1:5000 and fronted by nginx on port 80, with an unauthenticated /healthz for load-balancer probes
  • No usable default login. Upstream ASM3 seeds a documented user/letmein superuser and a guest/guest account. This image removes guest entirely and ships every account locked. A unique administrator password, database password and PostgreSQL superuser password are generated on the first boot of each VM.
  • asm3-credential-audit.py and asm3-admin-password.py, shipped as tools so you can prove that no publicly known credential works and rotate the admin password from the shell
  • Report and document generation with WeasyPrint, ReportLab and xhtml2pdf, and XLSX export with openpyxl
  • Base patched at build time, with unattended security upgrades enabled
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is the recommended size. It comfortably runs both the application and the bundled database for a typical shelter. Choose a larger size if you have many concurrent staff users or a large media library.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp for the web interface. Nothing else needs to be open. The database and the application process are bound to loopback and are not reachable from the network.

The appliance serves plain HTTP on port 80 on the VM's own IP, so you can evaluate it immediately. Add a real hostname and a TLS certificate before you store live animal, adopter or veterinary records. See "Set your own domain and TLS".

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Animal Shelter Manager by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size (Standard_B2s). Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

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:animal-shelter-manager-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name animal-shelter-manager \
  --image sac1647283583153:animal-shelter-manager-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Open the web port on the VM's NSG:

az vm open-port --resource-group <your-rg> --name animal-shelter-manager --port 80 --priority 900

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot, the image generates this VM's administrator password, its PostgreSQL role password and a password for the PostgreSQL superuser. It also points the application at the VM's own address and starts the stack. Confirm that all four services are active:

systemctl is-active postgresql memcached nginx asm3

Only port 80 is reachable from outside the VM. The application, the database and the cache are all bound to the loopback interface:

sudo ss -tlnp | grep -E ':80 |:5000 |:5432 |:11211 '

Step 5 - Check the health endpoint

The unauthenticated /healthz endpoint returns 200 and is intended for load-balancer and monitoring probes. It exposes nothing about the shelter:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/healthz

The ASM3 login page also returns 200:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/login

Step 6 - Retrieve the per-VM administrator credentials

Every secret on this VM is generated on its first boot and written to a root-only file. Nothing is shared with any other deployment of this image. Read the file:

sudo cat /root/asm3-credentials.txt

The file records the web URL, the administrator username and password, the ASM3 database name, user name and password, and the PostgreSQL superuser password.

Step 7 - Confirm the upstream default login does not work

This is the most important difference between this image and a manual ASM3 install. Upstream ASM3 seeds two accounts into every new database and publishes both in its own manual: user with the password letmein, which is a superuser, and guest with the password guest.

On this image, the guest account is deleted. The user account ships with a password hash that no input can satisfy until first boot replaces it with a random per-VM password. Verify this yourself. Both of these commands return FAIL:

curl -s -X POST http://127.0.0.1/login --data-urlencode 'username=user' --data-urlencode 'password=letmein' --data-urlencode 'database='; echo
curl -s -X POST http://127.0.0.1/login --data-urlencode 'username=guest' --data-urlencode 'password=guest' --data-urlencode 'database='; echo

A shipped audit tool checks every account row against upstream's published defaults and common weak passwords, using ASM3's own password-verification code. You can run it at any time:

sudo /usr/local/sbin/asm3-credential-audit.py

The tool prints CREDENTIAL_AUDIT_CLEAN and exits with 0 when no publicly known credential works.

Step 8 - Sign in to the web interface

Browse to http://<vm-public-ip>/ and sign in with the username and password from the credentials file. You land on the ASM3 main screen. It shows quick links to the shelter and calendar views, a recently changed strip, the shelter overview counters, alerts, your diary and a timeline of shelter activity.

ASM3 redirects to its configured address. ASM3 records its own base URL in /etc/asm3.conf. If the address in your browser does not match it, ASM3 redirects you there. First boot sets the base URL to this VM's public IP, so browsing to the VM's IP works out of the box.

If you put a DNS name, a load balancer or a reverse proxy in front of the VM, you must update base_url and service_url in /etc/asm3.conf and restart asm3.service. Otherwise the browser is redirected back to the raw IP. For the same reason, an SSH port-forward to localhost does not work until you change base_url to match.

Step 9 - Add your first animal

Choose ASM, then Add an animal. Enter a name, species, sex and an estimated age or date of birth. Pick an entry reason and a location on the shelter, and select Save.

ASM3 generates a shelter code automatically and opens the full animal record. The record has tabs for vaccinations, tests, medical treatment, clinic appointments, licenses, diet, costs, payments, media, diary, transport and movements.

The shelter view groups every animal currently on the shelter by location. You can see the whole shelter at a glance and drag animals between locations:

Step 10 - The bundled PostgreSQL database

The database runs on this VM and is bound to the loopback interface, so it is never exposed to the network. It is tuned for the VM size rather than left at PostgreSQL's stock defaults. The following settings are what the image ships:

sudo -u postgres psql -tAc "SELECT name || ' = ' || setting || COALESCE(unit,'') FROM pg_settings WHERE name IN ('listen_addresses','shared_buffers','effective_cache_size','work_mem','max_connections','random_page_cost') ORDER BY name"

Animal records live in the animal table of the asm database. You can read them directly, for example for reporting or to confirm a backup:

sudo -u postgres psql -d asm -c "SELECT ID, AnimalName, ShelterCode, DateBroughtIn::date AS entered FROM animal ORDER BY ID"

Step 11 - Back up the shelter database

The shelter database is the one thing you cannot recreate. Take a compressed dump with the PostgreSQL superuser password from the credentials file, and copy it off the VM:

sudo -u postgres pg_dump -Fc asm > /var/tmp/asm-backup-$(date +%Y%m%d).dump && ls -lh /var/tmp/asm-backup-*.dump

Media such as animal photos and scanned paperwork is stored on the filesystem under /var/lib/sheltermanager3/media, which keeps the database small. Back up that directory alongside the dump. To restore, run pg_restore into an empty database.

Step 12 - Change the administrator password

Change the password in the web interface under Settings, then System user accounts, or from the shell with the shipped tool. The tool hashes the password exactly as the web interface does. It reports success only if the new password then authenticates:

sudo /usr/local/sbin/asm3-admin-password.py user '<your new password>'

Create an individual named account for each staff member instead of sharing the administrator login, and give each account only the roles it needs.

Set your own domain and TLS

The appliance boots on plain HTTP on the VM's IP so you can evaluate it immediately. Before you enter real animal, adopter or veterinary records, complete these steps:

  • Point a DNS record (for example shelter.example.org) at the VM's public IP.
  • Install a certificate, for example with sudo apt-get install certbot python3-certbot-nginx and sudo certbot --nginx -d shelter.example.org. Certbot updates server_name in /etc/nginx/sites-available/asm3 and adds the TLS listener.
  • Update /etc/asm3.conf so ASM3 knows its own address. Set base_url = https://shelter.example.org and service_url = https://shelter.example.org/service. Because the site is now HTTPS-only, also set session_secure_cookie = true.
  • Restart the application so it loads the new configuration:
sudo systemctl restart asm3 nginx

The configuration change in the third item is required. ASM3 redirects any request whose address does not match base_url, so a certificate without the matching configuration change sends your browser back to the IP.

Maintenance and production notes

  • Logs. The application logs to /var/log/asm3/asm3.log, rotated weekly. Use journalctl -u asm3 for service-level start-up problems and journalctl -u asm3-firstboot to see what first boot did.
  • Scheduled tasks. ASM3's daily batch (animal figures, diary and waiting-list maintenance, publishing) runs from cron.py. First set your organization's details in Settings, then Options. To schedule the batch, review /usr/lib/sheltermanager3/cron.py all.
  • Email. The image configures no mail transport. Set smtp_server and from_address in /etc/asm3.conf before you use the email, mail-merge or online-form features.
  • Updates. Apply OS security updates with sudo apt update && sudo apt upgrade. Unattended security upgrades are already enabled. ASM3 version upgrades follow upstream's release notes and require python3 cron.py maint_db_update from /usr/lib/sheltermanager3 after you replace the application tree.
  • Security. This image ships no usable default credential. Keep /root/asm3-credentials.txt protected, and delete it once you have stored the passwords elsewhere. Re-run sudo asm3-credential-audit.py after any user administration to confirm that no weak credential has appeared.

Animal Shelter Manager is free software licensed under the GPL-3.0. This image is produced by SecureAnyCloud and is not affiliated with, sponsored by, or endorsed by the Animal Shelter Manager project or Sheltermanager Ltd.

Deploy on Azure

Launch Animal Shelter Manager 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

Deploy on Azure