istSOS 4
Overview
istSOS is an open source server for collecting, managing and publishing environmental and monitoring sensor data over open OGC standards. It implements the SensorThings API and the Sensor Observation Service data model. You register sensors, things, observed properties and datastreams, then load and serve the time series observations they produce through a REST API and an interactive API explorer.
This SecureAnyCloud image runs istSOS 4 (istsos4 v1.0.0) as a FastAPI application served by uvicorn behind nginx on Ubuntu 24.04 on Azure. It is backed by PostgreSQL 16 with the PostGIS spatial extension and a local Redis 7 instance for token handling. The SensorThings API is served under the versioned path /istsos4/v1.1, with an interactive Swagger explorer at /istsos4/v1.1/docs.
On every fresh virtual machine, istsos-firstboot.service rotates the istSOS administrator password, the PostgreSQL account passwords and the JWT signing key to strong per-VM values before the API is reachable. The upstream default administrator login no longer works. A demo network of five sensor stations, two observed properties and 1680 time series observations is seeded at build time, so the API and its explorer show real data as soon as you launch.
What you get:
- istSOS 4 (istsos4 v1.0.0) served by uvicorn from a Python 3.12 virtual environment at
/opt/istsos/venv istsos-api.service(uvicorn, 2 workers) fronted by nginx on TCP 80istsos-firstboot.service, a systemd oneshot that rotates the admin password, the PostgreSQL passwords and the JWT signing key on first boot- PostgreSQL 16 with the PostGIS 3.4 spatial extension as the SensorThings datastore (database
istsos) - Redis 7 from the Ubuntu 24.04 main repository, used for token handling
- The SensorThings API at
/istsos4/v1.1with an interactive Swagger explorer at/istsos4/v1.1/docs - Anonymous read access to the sensor collections for easy browsing, with every write requiring the administrator token
- A seeded demo network: five sensor stations, two observed properties (rainfall and temperature), ten datastreams and 1680 observations
- Ubuntu 24.04 LTS base with the latest security patches applied at build time
- Azure Linux Agent for cloud integration and SSH key injection
- 24/7 SecureAnyCloud support with a guaranteed 24 hour response SLA
Prerequisites
Before you start, make sure you have:
- An active Azure subscription
- A subscription to the istSOS 4 on Ubuntu 24.04 listing on Azure Marketplace
- An SSH public key for VM authentication
- A virtual network and subnet in the target region
Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is sufficient for evaluation and small monitoring networks. For production networks that ingest high-frequency observations from many stations, scale up to Standard_D2s_v5 or larger.
Deploy from the Azure Portal
In the Azure Portal, open Marketplace, search for istSOS 4, select the SecureAnyCloud publisher entry and click Create.
On the Networking tab, attach a network security group that allows inbound TCP 22 from your management IP range and TCP 80 from your trusted client networks. Do not expose port 80 to the public internet without TLS. The SensorThings API serves plain HTTP by design, so terminate TLS at a reverse proxy (see Step 12).
Click Review + create, wait for validation, then click Create. Deployment takes around two minutes.
Deploy from the Azure CLI
RG="istsos-prod" LOCATION="eastus" VM_NAME="istsos-01" ADMIN_USER="azureuser" IMAGE_URN="sac1647283583153:istsos-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create \
--resource-group "$RG" \
--name istsos-vnet --address-prefix 10.96.0.0/16 \
--subnet-name istsos-subnet --subnet-prefix 10.96.1.0/24 az network nsg create --resource-group "$RG" --name istsos-nsg az network nsg rule create \
--resource-group "$RG" --nsg-name istsos-nsg \
--name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create \
--resource-group "$RG" --nsg-name istsos-nsg \
--name allow-http --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" \
--destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:istsos-ubuntu-24-04:default:latest
az vm create \
--resource-group "$RG" --name "$VM_NAME" \
--image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username "$ADMIN_USER" --ssh-key-values "$SSH_KEY" \
--vnet-name istsos-vnet --subnet istsos-subnet --nsg istsos-nsg \
--public-ip-sku StandardConnect via SSH
ssh azureuser@<vm-ip>By the time you connect, istsos-api.service and nginx are running, and istsos-firstboot.service has already rotated the administrator password to a per-VM value.
Verify the istSOS services
Check that each service is active:
for s in istsos-api postgresql redis-server nginx; do printf '%-16s %s\n' "$s" "$(systemctl is-active $s)"; doneThe output shows one line per service, and every service reports active:
istsos-api active postgresql active redis-server active nginx activeConfirm the listeners. nginx listens on port 80, uvicorn on 8018, and PostgreSQL and Redis on loopback:
sudo ss -tln | grep -E ':80 |:8018 |:5432 |:6379 'Retrieve the administrator credentials
On first boot, the VM writes its per-VM administrator password, PostgreSQL passwords and JWT signing key to a root-only file. Read it with sudo:
sudo cat /stage/scripts/istsos-credentials.logThe file contains entries like the following. The values are redacted here, and your VM has its own unique values:
admin_username=admin admin_password=<ADMIN_PASSWORD> db_superuser_password=<DB_SUPERUSER_PASSWORD> secret_key=<SECRET_KEY> ISTSOS_URL=http://<vm-ip>/istsos4/v1.1The same content is also written to /root/istsos-credentials.txt. Both files are mode 0600 (root only). Store the administrator password in your secret store.
The SensorThings API service root
The SensorThings API is served under /istsos4/v1.1. Request the service root to list every entity collection:
curl -s http://localhost/istsos4/v1.1 | python3 -m json.tool | head -22The response lists the eight SensorThings collections, each with its URL: Things, Sensors, Datastreams, Observations, ObservedProperties, Locations, HistoricalLocations and FeaturesOfInterest.
The interactive API explorer
Open http://<vm-ip>/istsos4/v1.1/docs in your browser to reach the Swagger explorer. It documents every SensorThings operation and lets you try each one from the browser.
Read operations (the GET endpoints) are open for anonymous browsing. Write operations (POST, PATCH and DELETE, shown with a padlock) require the administrator token, which you obtain through the Authorize button.
Browse the seeded sensor stations
A fresh VM already holds a demo network, so you can explore istSOS right away. List the seeded sensor stations (Things):
curl -s "http://localhost/istsos4/v1.1/Things?\$count=true" | python3 -m json.tool | head -20The response lists the five seeded stations. To confirm the full seeded dataset, query the database directly:
sudo -u postgres psql -d istsos -P pager=off -c "SELECT 'Things' AS entity, count(*) FROM sensorthings.\"Thing\" UNION ALL SELECT 'Datastreams', count(*) FROM sensorthings.\"Datastream\" UNION ALL SELECT 'Observations', count(*) FROM sensorthings.\"Observation\" ORDER BY 1;"View the time series observations
Observations are the individual measurements recorded by each datastream. Fetch the most recent observations, newest first:
curl -s "http://localhost/istsos4/v1.1/Observations?\$top=5&\$orderby=phenomenonTime%20desc&\$count=true" | python3 -m json.tool | head -30Each record carries a phenomenonTime and a numeric result. The seeded network holds 1680 observations, which span seven days of hourly readings for rainfall and temperature.
Authenticate and write
Reads are anonymous, while writes require an administrator JSON Web Token. Log in with the per-VM administrator credentials to obtain a token, then use it to create a new Thing.
The following command reads the administrator password from the credentials file, logs in and creates an example station. Writes also require a commit-message header.
BASE="http://localhost/istsos4/v1.1" ADMIN_PW="$(sudo sed -n 's/^admin_password=//p' /stage/scripts/istsos-credentials.log | head -n1)" TOKEN="$(curl -s -X POST "$BASE/Login" --data-urlencode 'username=admin' --data-urlencode "password=$ADMIN_PW" | python3 -c 'import sys,json;print(json.load(sys.stdin)["access_token"])')" curl -s -o /dev/null -w 'create example-station -> HTTP %{http_code}\n' -X POST "$BASE/Things" \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-H 'commit-message: example station from the sac guide' \
-d '{"name":"example-station","description":"Created from the sac guide"}'A successful write prints create example-station -> HTTP 201. A write attempted without the token is rejected with HTTP 401, and the upstream default admin / admin login no longer works. Both behaviors are verified on every VM.
Add your own sensor network
The SensorThings model links entities together. A Thing (a physical station) has Locations and Datastreams. Each Datastream links a Sensor to an ObservedProperty and holds Observations.
Using the token from Step 10, build a full station with a single deep-insert POST to /Things, embedding its Locations and Datastreams. Then push observations to the created datastream. The interactive explorer at /istsos4/v1.1/docs documents the exact request bodies for each entity, and the OGC SensorThings API specification describes the full data model.
For bulk historical loads, POST a SensorThings dataArray to /CreateObservations.
Put TLS in front (production)
istSOS serves plain HTTP behind nginx by design. For production, terminate TLS using one of two common approaches.
Option A: enable TLS on the on-box nginx. Obtain a certificate for your DNS name and add a listen 443 ssl; server block that proxies to http://127.0.0.1:8018;. The nginx site file is at /etc/nginx/sites-available/istsos.
Option B: place Azure Application Gateway in front. Create an Application Gateway with TLS termination and point the backend pool at the VM private IP on port 80. Restrict the NSG to allow inbound port 80 from the Application Gateway subnet only.
The SecureAnyCloud nginx-ssl-certbot-ubuntu-24-04 image is built for Option A. Deploy it on a separate small VM and point it at the private IP of this istSOS VM.
Server components
These are the key paths on the VM:
- Application code: /opt/istsos/app/
- Python virtual environment: /opt/istsos/venv/
- Demo data generator: /opt/istsos/dummy_data/generator.py
- Environment file: /etc/istsos/istsos.env
- API systemd unit: /etc/systemd/system/istsos-api.service
- First-boot script: /usr/local/sbin/istsos-firstboot.sh
- First-boot service: /etc/systemd/system/istsos-firstboot.service
- nginx site:
/etc/nginx/sites-available/istsos - Credentials files: /stage/scripts/istsos-credentials.log and
/root/istsos-credentials.txt - First-boot sentinel: /var/lib/sac/data/istsos-firstboot.done
- PostgreSQL data: /var/lib/postgresql/16/main/
- PostgreSQL istSOS settings: /etc/postgresql/16/main/conf.d/istsos.conf
Managing the services
Check the service status:
sudo systemctl status istsos-api.service --no-pager | head -n 15Restart the service (use stop or start in place of restart as needed):
sudo systemctl restart istsos-api.serviceView the application log:
sudo tail -n 50 /var/log/istsos/uvicorn.logView the first-boot log:
sudo tail -n 30 /var/log/istsos/firstboot.log 2>/dev/null || echo "firstboot log is written on first boot"Backup and restore
The SensorThings datastore lives in the istsos database in PostgreSQL 16 on the same VM. Back it up with pg_dump:
sudo -u postgres pg_dump -Fc istsos > /var/backups/istsos.dumpTo restore on a new VM, stop the API service and run pg_restore. Replace <backup-dir> with the directory that holds your dump file:
sudo systemctl stop istsos-api.service
sudo -u postgres pg_restore -d istsos --clean --if-exists <backup-dir>/istsos.dump
sudo systemctl start istsos-api.serviceFor production, schedule a nightly pg_dump and copy it to Azure Blob Storage with azcopy.
Troubleshooting
Cannot reach the API on port 80
- Confirm the services are running:
sudo systemctl is-active istsos-api.service nginx - Confirm the listeners are bound:
sudo ss -tln | grep -E ':80 |:8018 ' - Check the log:
sudo tail -n 50 /var/log/istsos/uvicorn.log - Confirm the NSG allows TCP 80 from your client source IP.
Login returns 401
- Confirm you are using the per-VM password from
/stage/scripts/istsos-credentials.log, not the upstream default. - Confirm Redis is running:
sudo systemctl is-active redis-server
A write returns 422
- Writes require both the
Authorization: Bearerheader and acommit-messageheader. Include both (see Step 10).
Service fails to start
- Check the journal:
sudo journalctl -u istsos-api.service --no-pager -n 100 - Verify the datastore is reachable:
sudo -u postgres psql -d istsos -c '\dt sensorthings.*' | head
Security Recommendations
- Rotate the administrator password again after your first login, and store it in your secret store.
- Restrict port 22 to your management IP ranges only.
- Restrict port 80 to trusted client networks only, and pair it with TLS (Step 12) for any non-trivial deployment.
- Remember that read access is anonymous. The SensorThings collections are readable anonymously by design for easy integration. Front the VM with a firewall or gateway if your observation data is sensitive.
- Schedule nightly backups of the PostgreSQL datastore (Step 15) to Azure Blob Storage.
- Delete the credentials files once the password is in your secret store:
sudo shred -u /stage/scripts/istsos-credentials.log /root/istsos-credentials.txt
Support and licensing
istSOS is licensed under the Apache License 2.0 and is developed by SUPSI. There is no per-user, per-sensor or per-server fee.
SecureAnyCloud provides commercial support for this image, separate from the upstream project.
Email: sales@secureanycloud.com
Website: secureanycloud.com
Support hours: 24/7 with guaranteed 24 hour response SLA
Deploy on Azure
Launch istSOS 4 on Ubuntu 24.04 with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Deploy on Azure
Launch istSOS 4 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