Apache Syncope on Ubuntu 24.04 on Azure User Guide
Overview
Apache Syncope is an open source identity management and identity governance platform. It manages the full lifecycle of users, groups and accounts, provisions and reconciles them against directories, databases and SaaS applications through ConnId connectors, and applies approval workflows, password policies and audit trails.
The cloudimg image deploys the three Syncope web applications on a single Apache Tomcat 10.1 instance backed by a local PostgreSQL 16 database, with nginx in front on TCP 80:
| Application | Path | What it is for |
|---|---|---|
| Core | /syncope/rest/ |
The REST API, persistence, provisioning engine and self Keymaster |
| Admin console | /syncope-console/ |
The administrator web interface |
| Self service | /syncope-enduser/ |
The end user portal for profile and password self service |
A unique administrator password, JWT signing key, encryption key and database password are generated on the first boot of every VM, so no published upstream default is ever reachable. Backed by 24/7 cloudimg support.
What is included:
- Apache Syncope 4.1.2 Core, admin console and self service portal on Apache Tomcat 10.1.57
- OpenJDK 21 with the JVM heap sized to run comfortably alongside PostgreSQL, with no swap
- PostgreSQL 16 holding the Master domain, tuned for a small single node VM
- 16 ConnId provisioning connector bundles including LDAP, database, CSV, SCIM, REST, SOAP, Active Directory, Azure, Okta, Google Apps and ServiceNow
- The Flowable workflow engine for approval and user request workflows
- nginx reverse proxy on
:80with/redirecting to the admin console - Per VM administrator password, anonymous key, JWT signing key, AES encryption key and database password generated at first boot, in a root only file
postgresql.service,syncope.serviceandnginx.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_B2ms (2 vCPU / 8 GiB RAM) is a good starting point: Tomcat's JVM and PostgreSQL run together, and an identity workload with many connectors benefits from the headroom. NSG inbound: allow 22/tcp from your management network and 80/tcp from the people who use the console and the self service portal. Front port 80 with TLS before exposing it publicly, see Enabling HTTPS.
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apache Syncope 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 and Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name syncope \
--image <marketplace-image-urn> \
--size Standard_B2ms \
--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 syncope --port 80 --priority 1010
Step 3 — Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 — Confirm the services are running
First boot generates the per VM secrets and only then allows Syncope to start, so give the VM a couple of minutes after its first power on before expecting the console.
systemctl is-active postgresql syncope nginx
All three report active.

Step 5 — Confirm the web applications answer
curl -s -o /dev/null -w 'console -> HTTP %{http_code}\n' http://127.0.0.1/syncope-console/
curl -s -o /dev/null -w 'enduser -> HTTP %{http_code}\n' http://127.0.0.1/syncope-enduser/
curl -s -o /dev/null -w 'rest api -> HTTP %{http_code}\n' http://127.0.0.1/syncope/rest/users/self
The two web applications return HTTP 302, which is the redirect to their login pages, and the REST API returns HTTP 401 because it requires authentication. Those are the healthy responses.
Step 6 — Retrieve your administrator password
The administrator password is generated uniquely on the first boot of your VM and written to a root only file:
sudo grep -E '^SYNCOPE_(URL|ENDUSER_URL|ADMIN_USER|ADMIN_PASSWORD)' /root/syncope-credentials.txt
SYNCOPE_ADMIN_USER is admin and SYNCOPE_ADMIN_PASSWORD is the password. The same file also holds the self service URL, the REST base URL and the PostgreSQL password.

Step 7 — Verify authentication against the REST API
The following proves that the published upstream default is refused and that your per VM password is accepted:
PW=$(sudo grep '^SYNCOPE_ADMIN_PASSWORD=' /root/syncope-credentials.txt | cut -d= -f2-)
echo "upstream default admin/password -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -u admin:password http://127.0.0.1/syncope/rest/users/self)"
echo "per-VM admin password -> HTTP $(curl -s -o /dev/null -w '%{http_code}' -u "admin:$PW" http://127.0.0.1/syncope/rest/users/self)"
The upstream default returns HTTP 401 and your per VM password returns HTTP 200.

Step 8 — Sign in to the admin console
Open http://<vm-public-ip>/ in a browser. The root path redirects to the admin console. Sign in as admin with the password from Step 6.

After signing in you land on the dashboard, which summarises the deployment and the identity store.

Step 9 — Explore realms
Realms are the hierarchical containers that organise identities and scope administrative delegation. A fresh deployment ships with the root realm /, which you can view under Realms.

You can also read the realm tree over the REST API:
PW=$(sudo grep '^SYNCOPE_ADMIN_PASSWORD=' /root/syncope-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" -H 'Accept: application/json' http://127.0.0.1/syncope/rest/realms | jq -r '.result[] | "realm \(.fullPath) key=\(.key)"'
Step 10 — Create your first user
In the console choose Realms, select the realm, open the USER tab and select the + button to create a user. Fill in the username, password and any attributes, then save. The user appears in the list.

The same operation over the REST API:
PW=$(sudo grep '^SYNCOPE_ADMIN_PASSWORD=' /root/syncope-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" -X POST -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Prefer: return-content' \
-d '{"_class":"org.apache.syncope.common.lib.request.UserCR","realm":"/","username":"g.verdi","password":"Ch@ngeMe2026!","plainAttrs":[{"schema":"email","values":["g.verdi@example.com"]}]}' \
http://127.0.0.1/syncope/rest/users | jq -r '.entity.username, .entity.key'
Step 11 — Review the bundled provisioning connectors
Syncope provisions identities into external systems through ConnId connector bundles. The image ships the standard set, ready to configure under Topology in the console.
PW=$(sudo grep '^SYNCOPE_ADMIN_PASSWORD=' /root/syncope-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" -H 'Accept: application/json' http://127.0.0.1/syncope/rest/connectors/bundles | jq -r '.[].bundleName' | sed 's/net.tirasa.connid.bundles.//' | sort -u

Step 12 — The self service portal
End users manage their own profile, password and security question at http://<vm-public-ip>/syncope-enduser/. Self registration and password reset are enabled by default and are controlled from Configuration in the admin console.
curl -s -o /dev/null -w 'self service portal -> HTTP %{http_code}\n' http://127.0.0.1/syncope-enduser/
Enabling HTTPS
For production, terminate TLS at nginx with a real domain pointed at the VM's public IP. Install certbot and request a certificate, replacing the domain:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com
Syncope trusts the X-Forwarded-Proto header that nginx sets, so the console and portal generate correct HTTPS links once the certificate is in place.
Backup and maintenance
All identity data lives in the PostgreSQL syncope database. Back it up with a standard dump:
sudo -u postgres pg_dump syncope | gzip > /var/backups/syncope-$(date +%F).sql.gz
Snapshot the VM's disk in Azure for a full point in time copy, and keep the OS patched with sudo apt update && sudo apt upgrade. Syncope restarts cleanly with sudo systemctl restart syncope. Tomcat listens on 127.0.0.1:8080 only and is never exposed directly; all external traffic goes through nginx on port 80.
Application logs are under /var/log/syncope/:
sudo tail -n 20 /var/log/syncope/core.log
Support
This image is backed by 24/7 cloudimg support. Contact us by email and chat for help with realm design, connector and resource configuration, provisioning and reconciliation tasks, workflow customisation, TLS and backups.
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.