Traccar
Overview
Traccar is the reference open-source GPS tracking and fleet telematics server. It receives position reports from vehicle trackers, asset tags and phones, and stores them with a complete history. It turns that history into live maps, trip replay, geofences, scheduled and on-demand reports, event notifications, and driver and maintenance records. Everything the web interface does is also available through a full REST API.
Traccar understands more than two hundred device protocols. This image ships a small, explicitly documented set of protocol listeners rather than all of them, and Step 9 shows you how to enable the one your own trackers speak.
This SecureAnyCloud image delivers Traccar 6.15.3 on Ubuntu 24.04, served over HTTPS and backed by PostgreSQL. The database starts empty, and every secret is generated on the first boot of your VM.
What you get:
- Traccar 6.15.3 at
/opt/traccar, run by systemd as the unprivilegedtraccaruser on Ubuntu's own OpenJDK 21 runtime, with its web application bound to127.0.0.1:8082only - The Traccar web interface, served by nginx over HTTPS on port 443 with a certificate generated for your VM. Port 80 only redirects to HTTPS, and also serves a plain
/healthzfor load balancer probes. - PostgreSQL 16 on the loopback address only, holding devices, positions, users and reports
- Three device-protocol listeners enabled by default, with every other protocol disabled in the configuration:
osmandon 5055 (the Traccar Client phone app),teltonikaon 5027 andgt06on 5023 - No default login and no open enrollment. The administrator account is created, with a random password, on your VM's first boot, before the web interface is allowed to start.
postgresql,traccarandnginxsystemd services, enabled and active- 24/7 SecureAnyCloud support
Traccar is a trademark of its respective owner. 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. This image packages the unmodified open-source software, which is distributed under the Apache License 2.0.
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), which runs Traccar comfortably for a small to medium fleet. Choose a larger size for hundreds of devices that report at short intervals.
- Network security group inbound rules for
22/tcpfrom your management network,443/tcpfor the web interface, and optionally80/tcp, which only redirects to HTTPS - An inbound rule for the device-protocol port your trackers use:
5055/tcpfor the Traccar Client app,5027/tcpfor Teltonika hardware, or5023/tcpfor GT06-family trackers
Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Traccar by SecureAnyCloud 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 HTTPS (443). Then select Review + create and Create. Once the VM exists, add the device-protocol port your trackers use as an extra inbound rule (Step 9).
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:traccar-ubuntu-24-04:default:latest
az vm create \
--resource-group my-resource-group \
--name my-traccar \
--image sac1647283583153:traccar-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard \
--os-disk-delete-option Delete \
--nic-delete-option DeleteThen open the ports you need.
az vm open-port --resource-group my-resource-group --name my-traccar --port 443 --priority 1001
az vm open-port --resource-group my-resource-group --name my-traccar --port 5055 --priority 1002Connect to your VM
ssh azureuser@<vm-ip>The login user is azureuser (or whichever administrator name you chose at deployment). The image carries no build-time account and no password login.
Confirm the Traccar stack is running
First boot takes about a minute. It generates this VM's database password, TLS certificate and administrator password, creates an empty database, and only then allows nginx to start. Until first boot finishes, the web interface is deliberately not reachable.
sudo systemctl is-active postgresql postgresql@16-main traccar nginxactive active active activepostgresql.service on Ubuntu is a wrapper that reports active as soon as it has dispatched. For that reason, the previous commands check postgresql@16-main, the cluster that actually holds your data, separately.
Check the runtime and versions.
java -versionopenjdk version "21.0.12" 2026-07-21 OpenJDK Runtime Environment (build 21.0.12+8-1-24.04-Ubuntu)Traccar runs on Ubuntu's own OpenJDK package rather than a bundled runtime, so unattended-upgrades keeps the JVM patched along with the rest of the system.
Check what the network can reach
sudo /usr/local/sbin/traccar-port-check.shoff-box TCP exactly [22 80 443 5023 5027 5055]; Traccar web 127.0.0.1:8082; PostgreSQL loopback TRACCAR_PORTS_OKThat is the complete off-box surface of this image: SSH, the HTTPS front door, the HTTP redirect, and the three device-protocol listeners. Traccar's own web application listens on 127.0.0.1:8082 and is never directly reachable, because nginx is the only web door. PostgreSQL is bound to loopback.
sudo ss -Hltn | awk '{print $4}' | sort -t: -k2 -n | paste -sd' '[::]:22 [::]:443 [::]:80 [::ffff:127.0.0.1]:8082 0.0.0.0:22 127.0.0.53%lo:53 127.0.0.54:53 0.0.0.0:80 0.0.0.0:443 *:5023 *:5027 *:5055 127.0.0.1:5432Retrieve the first-boot credentials
sudo stat -c '%A %U:%G %n' /root/traccar-credentials.txt-rw------- root:root /root/traccar-credentials.txtsudo cat /root/traccar-credentials.txtThe file records this VM's web address, the administrator login and the password generated for it. None of these values exists in the image. Each one is generated on this VM's first boot, before the web interface is allowed to serve a single request.
Sign in
Open https://<vm-ip>/ in a browser. The certificate is generated for your VM and is self-signed, so the browser warns on the first visit. Step 11 shows how to install a certificate for a real domain name.
Sign in as admin with the password from Step 6. You land on the live map. A fresh instance has no devices yet, so the fleet list stays empty until you add a device in Step 8.
You can confirm the same thing from the command line without a browser. The server's public settings show that self-registration is closed.
curl -sk https://127.0.0.1/api/server \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({k: d[k] for k in ("id","registration","readonly","deviceReadonly")}, indent=2))'{ "id": 1, "registration": false, "readonly": false, "deviceReadonly": false }Then sign in through the front door, reading the password from your own credentials file rather than typing it.
PASS=$(sudo grep '^TRACCAR_ADMIN_PASSWORD=' /root/traccar-credentials.txt | cut -d= -f2-)
curl -sk -c /tmp/traccar.jar -X POST \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "email=admin" --data-urlencode "password=$PASS" \
https://127.0.0.1/api/session \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(json.dumps({k: d[k] for k in ("id","name","login","email","administrator")}, indent=2))'{ "id": 1, "name": "Administrator", "login": "admin", "email": "admin@localhost", "administrator": true }Add your first tracker
Every tracker identifies itself to Traccar by a unique identifier, usually its IMEI, which is printed on the device or returned by an SMS status command. Register the identifier first. Traccar refuses positions from identifiers it does not know, so an unregistered device cannot inject data into your fleet.
In the web interface, choose Settings > Devices > +, give the device a name, enter its identifier and save.
The quickest way to see the system working end to end is the official Traccar Client app for Android or iOS, which speaks the osmand protocol already enabled on port 5055. Do not use https://<vm-ip> as the server address, because that is the web interface. Enter http://<vm-ip>:5055 as the server URL, because the app uses port 5055. Set the device identifier to the same value you registered. Positions start arriving within a minute, and the device turns Online on the map.
Select a device to see its live status card, which shows fix time, position, speed and total distance.
Enable the protocol your trackers speak
Traccar supports over two hundred device protocols. This image deliberately enables only three. A marketplace image that opens two hundred unauthenticated listeners is a security liability, and Azure network security groups cap a single VM configuration at one hundred ports. Everything else is disabled in the configuration, not merely firewalled.
Check what is enabled.
sudo grep -E "protocols.enable|\.port'" /opt/traccar/conf/traccar.xml | sed 's/^ *//'<entry key='web.port'>8082</entry> <entry key='protocols.enable'>osmand,teltonika,gt06</entry> <entry key='osmand.port'>5055</entry> <entry key='teltonika.port'>5027</entry> <entry key='gt06.port'>5023</entry>To enable another protocol, you need three things: its name added to protocols.enable, a <protocol>.port entry, and the matching inbound rule in your network security group. Traccar's device list gives the protocol name and the conventional port for every supported tracker. For example, to add the h02 protocol on its conventional port 5013, use the following commands.
sudo cp /opt/traccar/conf/traccar.xml /opt/traccar/conf/traccar.xml.bak
sudo sed -i \
-e "s|<entry key='protocols.enable'>osmand,teltonika,gt06</entry>|<entry key='protocols.enable'>osmand,teltonika,gt06,h02</entry>|" \
-e "s|</properties>| <entry key='h02.port'>5013</entry>\n</properties>|" \
/opt/traccar/conf/traccar.xml
sudo systemctl restart traccar.service az network nsg rule create \
--resource-group my-resource-group \
--nsg-name my-traccar-nsg \
--name allow-h02 --priority 1010 \
--protocol Tcp --destination-port-ranges 5013 --access AllowWherever your mobile operator allows it, restrict each protocol rule to the address ranges your trackers report from. Device protocols are unauthenticated by design, and the device identifier is the only credential. The identifier register from Step 8 and a tight NSG rule are what protect the listener.
To remove a protocol, take its name out of protocols.enable, delete its .port entry, restart traccar.service and remove the NSG rule.
Run reports
Choose Reports in the navigation. Route and Positions list every stored fix. Trips and Stops group the fixes into journeys and dwell time. Summary and Chart aggregate distance, engine hours and speed. Pick a device and a period, then select Show.
The same data is available through the API. The following commands continue with the session cookie from Step 7.
curl -sk -b /tmp/traccar.jar https://127.0.0.1/api/devices \
| python3 -c 'import json,sys try: devices = json.load(sys.stdin) except Exception: devices = [] print(json.dumps([{k: d[k] for k in ("id","name","uniqueId","status")} for d in devices], indent=2))'[ { "id": 1, "name": "Delivery Van 1", "uniqueId": "864035050000001", "status": "online" } ]DEV=$(curl -sk -b /tmp/traccar.jar https://127.0.0.1/api/devices \
| python3 -c 'import json,sys try: d = json.load(sys.stdin) except Exception: d = [] print(d[0]["id"] if d else "")') if [ -n "$DEV" ]; then curl -sk -b /tmp/traccar.jar "https://127.0.0.1/api/positions?deviceId=$DEV" \
| python3 -c 'import json,sys try: d = json.load(sys.stdin) except Exception: d = [] print(json.dumps([{k: p[k] for k in ("deviceId","fixTime","latitude","longitude","speed")} for p in d[:1]], indent=2))' else echo "no devices registered yet - add one in Step 8" fi[ { "deviceId": 1, "fixTime": "2026-09-20T13:37:29.000+00:00", "latitude": 51.5426, "longitude": -0.0717, "speed": 22.5 } ]The full API reference is at traccar.org/api-reference. When you have finished, remove the cookie jar with rm -f /tmp/traccar.jar.
Use a domain name and your own certificate
Point a DNS A record at your VM's public address, then obtain a certificate and install it where nginx expects it.
sudo apt-get install -y certbot
sudo certbot certonly --standalone -d <your-domain> --agree-tos -m <your-email> --non-interactive sudo install -o root -g root -m 0640 /etc/letsencrypt/live/<your-domain>/privkey.pem /etc/ssl/traccar/traccar.key
sudo install -o root -g root -m 0644 /etc/letsencrypt/live/<your-domain>/fullchain.pem /etc/ssl/traccar/traccar.crt
sudo nginx -t && sudo systemctl reload nginxCertbot's standalone mode needs port 80 free. Stop nginx for the issuance and start it again afterward, or use a DNS challenge. Renewals replace the Let's Encrypt files, so add a deploy hook that repeats the two install commands and reloads nginx.
Add more users
Self-registration is disabled on this image, so nobody who finds your VM can enroll themselves. Add users yourself from Settings > Users > +, or through the API as the administrator.
curl -sk -b /tmp/traccar.jar -X POST -H 'Content-Type: application/json' \
--data '{"name":"Dispatcher","email":"dispatch@example.com","password":"<new-password>"}' \
https://127.0.0.1/api/usersGrant each user access to specific devices from Settings > Users > Show, next to the user's row. Leave Admin off for everyday accounts.
If you deliberately want open enrollment, turn it on in Settings > Server > Registration. Do not do this on an instance reachable from the public internet unless you intend anyone to be able to create an account.
Security model
- No default credential. Traccar creates no administrator in a fresh database, but an empty user table makes the first anonymous account creation an administrator. First boot consumes that window itself, on the loopback interface, before nginx is allowed to start. The first account that ever exists on your instance is therefore yours, with a random 24-character password.
- The front door stays shut until first boot finishes.
nginx.servicedoes not start until first boot has written/var/lib/sac/data/traccar.bootstrap-ready, andtraccar.servicedoes not start until first boot has written this VM's database password. Service ordering alone would not be enough, because it would still let the application start if first boot were slow or failed. - Self-registration is off. The setting is re-asserted on every first boot rather than inherited from an upstream default.
- Traccar is not directly reachable. It binds
127.0.0.1:8082. nginx terminates TLS and setsX-Forwarded-ForandX-Real-IPfrom the real connection address, so a caller cannot forge the address Traccar records. nginx also clearsForwardedandX-Forwarded-Prefix, and stampsSecure,HttpOnlyandSameSite=Laxonto the session cookie. - PostgreSQL is loopback-only with a password unique to this VM.
- No outbound calls by default. Traccar's anonymous usage-statistics upload and its geocoder are both disabled in the shipped configuration. Your browser fetches map tiles, not the server.
- Device protocols are unauthenticated by design. The device identifier is the credential, so register identifiers deliberately (Step 8) and restrict the protocol port in your NSG (Step 9).
A single command re-checks all of it.
sudo /usr/local/sbin/traccar-selftest.sh[ports] off-box TCP exactly [22 80 443 5023 5027 5055]; Traccar web 127.0.0.1:8082; PostgreSQL loopback [ports] TRACCAR_PORTS_OK [login] per-VM credential authenticates as administrator (200); admin/admin, blank and weak refused [login] self-registration closed (anonymous POST /api/users -> 400); cookie Secure+HttpOnly+SameSite [login] TRACCAR_LOGIN_OK [xff] through nginx Traccar recorded [127.0.0.1], not the forged [203.0.113.77] [xff] known-bad control (bypassing nginx) recorded [203.0.113.77] as expected [xff] TRACCAR_XFF_OK [http] port 80 redirects to HTTPS [registration] self-registration disabled TRACCAR_SELFTEST_OKBack up your data
Everything Traccar stores (devices, users, positions, geofences and reports) lives in the traccar PostgreSQL database. Uploaded media lives in /opt/traccar/media, and the configuration lives in /opt/traccar/conf/traccar.xml.
sudo -u postgres pg_dump -Fc traccar > <backup-dir>/traccar-$(date +%F).dump
sudo tar czf <backup-dir>/traccar-config-$(date +%F).tar.gz \
/opt/traccar/conf/traccar.xml /opt/traccar/mediaTo restore onto a fresh instance, stop traccar.service, drop and recreate the database, restore with pg_restore, put the configuration back, and start the service again. Keep the dumps off the VM, for example in an Azure storage account or a managed backup vault.
Logs, upgrades and maintenance
sudo journalctl -u traccar.service -n 50 --no-pager sudo tail -n 50 /opt/traccar/logs/tracker-server.logTraccar's own log records every protocol connection and every decoded message, which makes it the fastest way to diagnose a tracker that is not reporting. If the device connects but Traccar answers Unknown device, the identifier is not registered (Step 8). If nothing appears at all, the NSG rule or the protocol port is wrong (Step 9).
unattended-upgrades applies operating system security updates automatically, including OpenJDK, PostgreSQL and nginx. To upgrade Traccar itself, back up first (Step 14). Then replace /opt/traccar with a newer release archive, keeping conf/traccar.xml, and restart the service. Traccar migrates its own schema on start.
sudo systemctl restart traccar.service
sudo systemctl is-active traccaractiveSupport
SecureAnyCloud provides 24/7 support for this image, covering deployment, tracker onboarding, additional device protocols, TLS certificates and custom domains, database tuning, backups and scaling. Contact us at secureanycloud.com.
Deploy on Azure
Launch Traccar GPS Tracking 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