Deployment guide

CGRateS

Overview

This guide covers the deployment and use of CGRateS on Ubuntu 24.04 on Azure using SecureAnyCloud Azure Marketplace images.

CGRateS is a carrier-grade, real-time charging system from ITsysCOM. It rates, charges and bills usage for metered services such as voice calls, VoIP, SMS, data and any custom usage record, with pluggable rating plans, destinations, tariffs, balances, chargers, attributes and CDR handling. Everything is driven through a JSON-RPC API and the cgr-console CLI, so it slots in behind session managers and agents (FreeSWITCH, Kamailio, Asterisk, Diameter, Radius) or in front of your own provisioning.

This image delivers CGRateS 0.10.5 installed from the official CGRateS apt repository, fully configured and hardened, so the engine is answering and rating calls within minutes of first boot.

What you get:

  • CGRateS 0.10.5 installed from the official CGRateS apt repository, running under systemd as cgrates.service
  • The full CGRateS tool set on the default PATH: cgr-engine, cgr-loader, cgr-console, cgr-tester, cgr-migrator
  • Self-contained by design. The DataDB (active accounts, rating data) is a local Redis bound to loopback with a per-VM password, and the StorDB is CGRateS's own internal store, so there is no external SQL database to install, run or secure. The only datastore on the box is the loopback-only Redis.
  • Loopback-only engine listeners. The engine's RPC and HTTP JSON-RPC listeners are bound to 127.0.0.1 only and are never exposed off the box. They carry no authentication of their own, which is why they must stay on loopback.
  • An nginx TLS reverse proxy on port 443 in front of the loopback JSON-RPC HTTP API, with a per-VM self-signed TLS certificate and per-VM HTTP Basic Auth. Port 80 redirects to 443.
  • A unique Redis password, Basic Auth password and TLS certificate generated on first boot for each VM, and written to the root-only file /root/cgrates-credentials.txt. No credential is baked into the image.
  • A sample tariff plan (accounts 1001-1004 with balances, destinations, rating plans and chargers) loaded on first boot, so the engine rates a call and returns balances the moment the VM is up
  • No swap in the image; the stack fits a Standard_B2s in RAM

Deploying the VM

Launch the image from the Azure Marketplace as you would any other VM. The recommended size is Standard_B2s (2 vCPU / 4 GiB). Higher call volumes benefit from more memory for Redis and the rater. Move to a larger size if you load large tariff plans or keep many active sessions.

CGRateS is reached off the box only through nginx on TCP 443, with port 80 redirecting to 443. The Azure network security group (NSG) is your first line of defense. Open 443 only to the client addresses or subnets that need the API, never to the whole internet. The per-VM Basic Auth password and TLS are the second and third layers, but only the NSG keeps unwanted traffic off the box entirely. The engine's own ports (2012, 2013, 2080) and Redis (6379) are bound to loopback and are never in the NSG.

First boot

On the first boot of each VM, a one-shot service, cgrates-firstboot.service, prepares the instance. It:

  • Generates a per-VM Redis password and applies it to Redis (loopback only)
  • Writes that password into the engine config (/etc/cgrates/cgrates.json)
  • Generates a per-VM self-signed TLS certificate whose common name is the VM's public IP
  • Generates a per-VM HTTP Basic Auth password for the nginx front door (user admin)
  • Writes /root/cgrates-credentials.txt (mode 600, root only)
  • Starts the engine and loads the sample tariff plan, so the engine rates a call out of the box

No two VMs share a credential. The engine does not start until first boot has generated the real per-VM Redis password, so the vendor default never runs.

Retrieve your per-VM credentials

Connect over SSH as azureuser, then read the root-only credentials file:

sudo cat /root/cgrates-credentials.txt

Expected output (secrets shown here as ****):

# CGRateS 0.10.5 — generated on first boot by cgrates-firstboot.service
# These credentials are unique to this VM. Store them somewhere safe. cgrates.url=https://20.0.0.10/jsonrpc
# 1) HTTP Basic Auth guards the nginx TLS front door to the CGRateS JSON-RPC HTTP API: cgrates.basicauth.user=admin cgrates.basicauth.pass=****
# 2) Redis (CGRateS DataDB) per-VM password — loopback only, 127.0.0.1:6379, logical DB 10: cgrates.redis.pass=****

Keep this file safe. It is the only copy of the per-VM secrets, and only root can read it.

Check service health

Three services back the appliance: redis-server (the DataDB), cgrates (the engine) and nginx (the TLS front door). Confirm that all three are active and that the engine answers its JSON-RPC ping:

sudo systemctl is-active redis-server cgrates nginx cgr-engine -version curl -s http://127.0.0.1:2080/jsonrpc \
  -H 'Content-Type: application/json' \
  -d '{"id":1,"method":"CoreSv1.Ping","params":[{}]}'

Expected output:

active active active CGRateS@v0.10.5 {"id":1,"result":"Pong","error":null}

Pong from CoreSv1.Ping confirms the engine is up and dispatching RPC. The engine binds 127.0.0.1 only, on ports 2012 (JSON-RPC), 2013 (GOB-RPC) and 2080 (HTTP JSON-RPC). Nothing off the box reaches it directly.

Review the sample tariff plan

A tariff plan is the set of destinations, rates, rating plans, rating profiles, account actions, chargers and attributes that tells CGRateS how to price usage. The image preloads the sample tutorial plan on first boot; You can reload it at any time with cgr-loader, which reads the per-VM Redis password from the credentials file:

RP=$(sudo grep '^cgrates.redis.pass=' /root/cgrates-credentials.txt | cut -d= -f2-) sudo cgr-loader -verbose \
  -path=/usr/share/cgrates/tariffplans/tutorial \
  -datadb_passwd="$RP" 2>&1 | tail -5

Expected output (the loader prints the tables it writes, then completes):

2026/08/11 11:34:59 Processing folder /usr/share/cgrates/tariffplans/tutorial 2026/08/11 11:34:59 Writing to DataDB 2026/08/11 11:34:59 Done.

Rate a call and query a balance

Rating calls is the core job of the engine. The sample plan provisions accounts 1001 to 1004. Query the balance of account 1001, then rate a 20-second call from 1001 to 1002:

cgr-console 'accounts Tenant="cgrates.org" AccountIDs=["1001"]' cgr-console 'cost Category="call" Tenant="cgrates.org" Subject="1001" Destination="1002" AnswerTime="2014-08-04T13:00:00Z" Usage="20s"'

The account query returns a *monetary balance of 10; the cost query returns a Cost for the rated call:

[ { "BalanceMap": { "*monetary": [ { "ID": "test", "Value": 10, "Weight": 10 } ] }, "ID": "cgrates.org:1001", "Disabled": false } ] { "Cost": 0.6, "Charges": [ { "RatingID": "2e7fc13", "Increments": [ ... ] } ], "Tenant": "cgrates.org", "Subject": "1001", "Destination": "1002", "Usage": "20s" }

A non-zero Cost means the engine walked the destination, rating plan and rate tables and priced the call end to end. This is the definitive check that the engine is live and rating.

Call the API through the nginx TLS front door

Off the box, you reach the JSON-RPC API over HTTPS through nginx, guarded by HTTP Basic Auth. The certificate is a per-VM self-signed certificate, so pass -k or install your own certificate (see below). Replace <CGRATES_BASICAUTH_PASSWORD> with the cgrates.basicauth.pass value from your credentials file, and use the VM's public IP:

curl -sk -u "admin:<CGRATES_BASICAUTH_PASSWORD>" https://127.0.0.1/jsonrpc \
  -H 'Content-Type: application/json' \
  -d '{"id":1,"method":"APIerSv1.GetAccount","params":[{"Tenant":"cgrates.org","Account":"1001"}]}'

Expected output (the same account, now fetched through the authenticated TLS front door):

{"id":1,"result":{"ID":"*out:cgrates.org:1001","BalanceMap":{"*monetary*out":[{"ID":"test","Value":10,"Weight":10}]},"Disabled":false},"error":null}

Without the -u credential, the front door returns 401. A wrong password also returns 401. Only the per-VM Basic Auth password gets through to the engine.

Load your own tariff plans

Author your own plan as a folder of CSV files that follow the same schema as the sample. Load it the same way, replacing the path with your own:

$
RP=$(sudo grep '^cgrates.redis.pass=' /root/cgrates-credentials.txt | cut -d= -f2-) $
sudo cgr-loader -verbose -path=/path/to/your/tariffplan -datadb_passwd="$RP"

The CSV schema is documented at cgrates.readthedocs.io. The sample plan under /usr/share/cgrates/tariffplans/tutorial is a working reference to copy and adapt.

Install your own TLS certificate

The image ships a per-VM self-signed certificate so the API is encrypted from first boot. Replace it with a certificate for your own domain (for example from Let's Encrypt) and point nginx at it:

$
sudo cp /path/to/fullchain.pem /etc/nginx/ssl/cgrates.crt $
sudo cp /path/to/privkey.pem /etc/nginx/ssl/cgrates.key $
sudo chmod 600 /etc/nginx/ssl/cgrates.key $
sudo nginx -t && sudo systemctl reload nginx

Change the credentials

Change the nginx Basic Auth password. You are prompted for the new password:

$
sudo htpasswd /etc/nginx/.cgrates.htpasswd admin $
sudo systemctl reload nginx

To change the Redis password, set a new requirepass in /etc/redis/redis.conf and the matching data_db.db_password in /etc/cgrates/cgrates.json. Then restart both services:

$
sudo systemctl restart redis-server cgrates

Where things live

These are the main paths and what each one holds:

  • /usr/bin/cgr-engine: the CGRateS engine daemon (run by cgrates.service)
  • /usr/bin/cgr-loader: loads tariff plan CSVs into the DataDB
  • /usr/bin/cgr-console: JSON-RPC CLI client for a running engine
  • /etc/cgrates/cgrates.json: engine config (loopback listeners, Redis DataDB, internal StorDB)
  • /etc/redis/redis.conf: Redis (DataDB) config, loopback only, per-VM password
  • /etc/nginx/sites-available/cgrates: nginx TLS reverse proxy vhost (:443)
  • /etc/nginx/ssl/cgrates.crt / .key: per-VM TLS certificate
  • /etc/nginx/.cgrates.htpasswd: per-VM HTTP Basic Auth users
  • /root/cgrates-credentials.txt: per-VM secrets (root only, mode 600)
  • /usr/share/cgrates/tariffplans/tutorial: the sample tariff plan

Switch StorDB to MySQL or Postgres

The StorDB is *internal by default, which keeps CDRs and offline data in process. This suits a self-contained appliance. If you need durable CDR archival or the offline API, install MySQL or Postgres and load the CGRateS schema (shipped under /usr/share/cgrates/storage). Then set stor_db.db_type in /etc/cgrates/cgrates.json accordingly and restart cgrates. The DataDB stays on Redis. SecureAnyCloud support can walk you through this.

Security checklist

  • Restrict the NSG. Expose only port 443 (and 22 for SSH) to the specific clients that need it. The engine and Redis are already loopback only.
  • Install a real TLS certificate for your domain and remove the self-signed one.
  • Rotate the Basic Auth and Redis passwords if the credentials file is ever exposed.
  • Keep the OS patched. unattended-upgrades is enabled, so security updates apply automatically.

Troubleshooting

  • Engine not answering Pong: check sudo systemctl status cgrates and sudo journalctl -u cgrates -n 50. A DataDB authentication error means the Redis password in cgrates.json and redis.conf do not match.
  • 401 from the front door: the Basic Auth credential is missing or the password is wrong. Re-read /root/cgrates-credentials.txt.
  • cost returns nothing or a zero cost: the tariff plan is not loaded. Re-run cgr-loader as shown above and confirm that accounts 1001-1004 exist.
  • First boot did not run: check sudo systemctl status cgrates-firstboot and confirm /var/lib/sac/data/cgrates-firstboot.done exists.

Further reading

  • CGRateS documentation: cgrates.readthedocs.io
  • CGRateS source (AGPL-3.0): github.com/cgrates/cgrates

Support

SecureAnyCloud provides 24/7 technical support for this CGRateS image by email at sales@secureanycloud.com. We help with deployment, writing and loading tariff plans, using the JSON-RPC API and cgr-console, adding TLS and a custom domain, switching StorDB to MySQL or Postgres, integrating session and agent modules, performance tuning, upgrades and troubleshooting.

Deploy on Azure

Launch CGRateS on Ubuntu 24.04 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