AtroPIM
Overview
AtroPIM is an open-source Product Information Management system built on the AtroCore data platform. It gives a business one authoritative record for every product: names and identifiers, a configurable attribute model organised into attribute panels, hierarchical categories, classifications that apply whole attribute sets in one step, brands, channels and localised values, and the images and documents that belong to each article. Everything the browser interface can do is also available over a REST API, so the catalogue can sit between your suppliers, your ERP and the sales channels that consume the data.
This SecureAnyCloud image runs AtroPIM 1.16.5 on AtroCore 2.3.10, with PHP 8.4 under PHP FPM, nginx on port 80 and PostgreSQL 16, the database engine upstream recommends. The AtroCore job manager runs from a systemd timer that executes the same console.php cron command upstream documents. Scheduled jobs, import feeds and export feeds are processed without further setup.
The installation wizard is already completed in the image. A stock AtroCore installation ends at a browser setup page that accepts database credentials and creates the first administrator with no authentication. That page should never face the public internet. This image runs the wizard during the build over the loopback interface, so every VM you launch starts at a login screen instead of an open installer. AtroCore removes the installer routes entirely once the system reports itself installed.
Every VM generates a unique administrator password, database password, password salt, encryption key and application identifier on first boot. Upstream fixes the salt and the encryption key at installation time, which would otherwise make them identical on every VM launched from one image. This image replaces all of them per VM and holds the application back from serving anything until it has done so.
What you get:
- AtroPIM 1.16.5 on AtroCore 2.3.10, pinned to exact stable releases and recorded in a
composer.lockthat ships with the image - The free Import, Import HTTP, Export and Export HTTP modules, so you can move data in and out over files or HTTP with no additional licence
- PHP 8.4 FPM, nginx on port 80 and PostgreSQL 16 bound to the loopback interface only
- The AtroCore job manager driven by
atropim-cron.timer, which runs upstream'sconsole.php cronevery 60 seconds - The installation wizard completed at build time and its routes deregistered, so no VM exposes an unauthenticated installer
- A unique administrator password, database password, password salt, encryption key and application identifier, generated on first boot and recorded in a root-only file
- PHP FPM and the job runner held back by a first-boot marker, so nothing serves the application until every secret has been replaced
- A small starter catalogue, with one category, one attribute and three articles, so the interface opens onto working data
- 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 a comfortable starting size and matches upstream's stated minimum. A measured idle appliance uses roughly 660 MiB of the 3.8 GiB available, with PHP FPM capped at five workers. Choose a larger size if you plan to import very large catalogues or run many concurrent editors.
Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp, plus 443/tcp if you add TLS. AtroPIM serves plain HTTP by default, so put your own domain and a trusted certificate in front of it before you expose it to the internet.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for AtroPIM 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).
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:atropim:default:latest
az vm create \
--resource-group <your-rg> \
--name atropim \
--image sac1647283583153:atropim:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardOnce the VM is created, open port 80 so you can reach the web interface:
az vm open-port --resource-group <your-rg> --name atropim --port 80 --priority 900Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>The first boot rotates every secret and writes a summary into the message of the day. Your first SSH session shows the AtroPIM URL and the location of the credentials file.
Step 4 - Confirm the services are running
AtroPIM runs as PHP FPM behind nginx, with PostgreSQL as its database and a systemd timer driving the AtroCore job manager. Confirm all four are active:
systemctl is-active postgresql@16-main.service php8.4-fpm.service nginx.service atropim-cron.timerAll four units report active. Only port 80 is reachable from outside the VM, while PostgreSQL stays on the loopback interface. The exact release set is recorded in the shipped composer.lock.
Step 5 - Confirm AtroPIM is answering
The image exposes a lightweight health endpoint that answers from nginx, with the application behind it. Request the health endpoint, the web interface and the REST API:
curl -s -o /dev/null -w 'health -> HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'web UI -> HTTP %{http_code}\n' http://127.0.0.1/
curl -s -o /dev/null -w 'REST API -> HTTP %{http_code}\n' http://127.0.0.1/api/Expected output:
health -> HTTP 200 web UI -> HTTP 200 REST API -> HTTP 401The 401 on the API is the expected result. It means PHP is rejecting an unauthenticated caller. A 502 in that position would mean nginx is up but PHP FPM is not.
PHP FPM and the job runner both carry a ConditionPathExists on a marker that first boot creates only after every secret has been rotated. On a brand-new VM, they are skipped until the rotation has finished. The installer routes are gone, because the system already reports itself installed.
Step 6 - Retrieve your administrator password
Every secret on this VM was generated during its first boot and written to a root-only file. Check the file's permissions and read the URL and administrator user name:
sudo stat -c 'mode %a owner %U:%G' /root/atropim-credentials.txt
sudo grep -E '^ATROPIM_URL|^ATROPIM_ADMIN_USER' /root/atropim-credentials.txtExpected output:
mode 600 owner root:root ATROPIM_URL=http://<your-vm-public-ip>/ ATROPIM_ADMIN_USER=adminRead the administrator password:
sudo grep '^ATROPIM_ADMIN_PASSWORD=' /root/atropim-credentials.txt | cut -d= -f2-The same file also records ATROPIM_DB_USER and ATROPIM_DB_PASSWORD for the PostgreSQL role AtroPIM uses.
Step 7 - Confirm the default logins are rejected
AtroCore evaluates a user name and password at one route, /api/userSession, which returns the session token used for every other call. This route is the right place to check that no guessable credential works on your VM:
for D in admin password atrocore atropim 123456; do printf 'admin / %-9s -> HTTP %s\n' "$D" \
"$(curl -s -o /dev/null -w '%{http_code}' -m 10 \
-H "Authorization-Token: $(printf 'admin:%s' "$D" | base64 -w0)" \
http://127.0.0.1/api/userSession)" doneExpected output:
admin / admin -> HTTP 401 admin / password -> HTTP 401 admin / atrocore -> HTTP 401 admin / atropim -> HTTP 401 admin / 123456 -> HTTP 401The two accounts listed alongside admin are AtroCore system accounts. Neither holds a password, so neither can sign in.
Step 8 - Query the catalogue over the REST API
Sign in once to obtain a session token, then use that token for every other call:
PW=$(sudo grep '^ATROPIM_ADMIN_PASSWORD=' /root/atropim-credentials.txt | cut -d= -f2-)
TOKEN=$(curl -fsS -m 30 \
-H "Authorization-Token: $(printf 'admin:%s' "$PW" | base64 -w0)" \
http://127.0.0.1/api/userSession \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["user"]["token"])') AUTH="Authorization-Token: $(printf 'admin:%s' "$TOKEN" | base64 -w0)" curl -s -H "$AUTH" 'http://127.0.0.1/api/Product?maxSize=10' \
| python3 -m json.tool | head -30The call returns the starter catalogue. The same records are visible directly in PostgreSQL, which confirms that the application reads and writes the database on this VM and not a cache:
sudo runuser -u postgres -- psql -P pager=off \
-c "SELECT number, name, status FROM product WHERE deleted = false ORDER BY number" atropimExpected output:
number | name | status ----------+------------------+-------- SKU-0001 | Sample Product A | ready SKU-0002 | Sample Product B | ready SKU-0003 | Sample Product C | ready (3 rows)Step 9 - Open AtroPIM in your browser
Browse to http://<your-vm-public-ip>/. AtroPIM opens on its sign-in page.
Step 10 - Sign in
Sign in as admin with the password from Step 6. The dashboard opens with a Getting Started panel and the list of entities that the platform exposes.
Step 11 - Open the Products catalogue
Choose Products in the top navigation. The grid shows the three starter articles with their article numbers, names and status. The category tree sits alongside it.
Step 12 - Open a product record
Select a product name to open its record. The detail view is organised into the panels that make up your data model: Master Data, State, Description, Taxonomy and the attribute panels you define.
Step 13 - Edit product information
Select Edit, or the inline pencil beside any field, to change a value, then save. AtroPIM writes the change straight to PostgreSQL and renders it back immediately.
Step 14 - Work with categories
Categories are hierarchical. Manage them from the tree in the left panel or from the Categories view. Products can belong to several categories, and most downstream channels consume the category structure.
Step 15 - Shape the attribute model
Attributes are the core of a PIM. Each attribute has a type, belongs to an attribute panel and is bound to an entity. You create attributes in the browser, not in code.
From here, remove the starter catalogue, define the attributes your own articles need and group them into panels. Then load your data through the Import module or the REST API.
Server components
Component Version Notes
AtroPIM 1.16.5 The Product Information Management application
AtroCore 2.3.10 The underlying data platform
Import / Import HTTP 1.11.4 / 1.7.3 Free import modules, files and HTTP sources
Export / Export HTTP 1.11.5 / 1.9.3 Free export modules, files and HTTP targets
PHP 8.4 FPM and CLI, from the ondrej PHP packages
PostgreSQL 16 Bound to the loopback interface only
nginx 1.24 Serves port 80 and proxies to PHP FPM
Ubuntu 24.04 LTS Patched at build time, unattended security upgrades enabled
Filesystem layout
Path Purpose
/var/www/atropim Application root, holds composer.json, composer.lock and vendor/
/var/www/atropim/public The nginx document root, the only part of the tree served over HTTP
/var/www/atropim/data Configuration, cache and generated metadata
/var/www/atropim/upload Uploaded product images, datasheets and other assets
/var/lib/postgresql/16/main The PostgreSQL cluster
/root/atropim-credentials.txt Per VM credentials, mode 600, owned by root
/var/lib/sac First boot sentinel and the bootstrap ready marker
Managing the services
systemctl status php8.4-fpm.service --no-pager | head -5Restart the application after you change the configuration:
sudo systemctl restart php8.4-fpm.service nginx.serviceA timer drives the job manager and runs upstream's cron entry every 60 seconds:
systemctl list-timers atropim-cron.timer --no-pager | head -3Clear the AtroCore cache after you change the data model from the command line:
cd /var/www/atropim && sudo runuser -u www-data -- php console.php clear cacheMaintenance
Add your own domain name and a trusted TLS certificate before you put this VM in front of users. The nginx site lives at /etc/nginx/sites-available/atropim and serves plain HTTP on port 80 only. Adding a certificate is the most important change to make.
Back up both halves of the system together. The PostgreSQL database holds your catalogue, and /var/www/atropim/upload holds the files attached to it.
sudo -u postgres pg_dump atropim | gzip > /var/backups/atropim-$(date +%F).sql.gz
sudo tar czf /var/backups/atropim-upload-$(date +%F).tar.gz -C /var/www/atropim uploadAtroCore updates itself through its Module Manager, which uses the composer.phar at the application root. That file sits above the document root and is not reachable over HTTP.
Security notes
- Restrict
22/tcpto your management network and put a certificate in front of port 80. - Change the administrator password after your first sign-in, and create named user accounts instead of sharing the administrator account.
- Keep PostgreSQL on the loopback interface. Nothing outside the VM needs to reach it.
- Remove the starter catalogue once you have loaded your own data.
- Leave unattended security upgrades enabled so the base operating system keeps patching itself.
Support
SecureAnyCloud provides 24/7 support for this image. For questions about AtroPIM itself, the upstream Help Center and community are the best starting points.
Deploy on Azure
Launch AtroPIM 1.16.5 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