Skip to main content

RAN Monitor Runtime Configuration Guide

Understanding config/runtime.exs


Table of Contents

  1. Overview
  2. Database Configuration
  3. Web Endpoints
  4. Logger Configuration
  5. Nokia Integration
  6. InfluxDB Configuration
  7. Configuration Best Practices

Overview

The config/runtime.exs file is the primary configuration file for RAN Monitor. It's evaluated at runtime (when the application starts), allowing you to configure all aspects of the system's behavior.

What Gets Configured:

  • Database connections (MySQL)
  • Web server endpoints and ports
  • Nokia base station details
  • InfluxDB time-series database
  • Logging behavior
  • Security credentials

File Location:

config/runtime.exs

Who Should Use This Guide

Important: All RAN Monitor configuration is performed by Omnitouch as part of the initial deployment and ongoing support. This guide is provided for:

  • Advanced users who want to understand the system configuration
  • Self-managed deployments where customers maintain their own configuration
  • Troubleshooting and understanding how the system is configured
  • Custom deployments with specific requirements

If you are an Omnitouch-managed customer, contact Omnitouch support for any configuration changes.

For understanding what data is being collected, see Nokia Counter Reference. For dashboard creation, see Grafana Integration.


Database Configuration

MySQL/MariaDB Connection

config :ran_monitor, RanMonitor.Repo,
username: "omnitouch",
password: "omnitouch2024",
hostname: "localhost",
database: "ran_monitor",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10

Purpose: Configures the connection to the MySQL database used for session state management and operational data.

Parameters Explained

username (String)

  • Database user account
  • Current value: "omnitouch"
  • Usage: Must have CREATE, SELECT, INSERT, UPDATE, DELETE privileges
  • Security: Consider using a dedicated user with minimum required privileges

password (String)

  • Database password for authentication
  • Current value: "omnitouch2024"
  • Security: Should be stored in environment variables in production
  • Recommendation: Use strong, unique passwords

hostname (String)

  • Database server address
  • Current value: "localhost"
  • Options:
    • "localhost" - Database on same machine
    • "127.0.0.1" - TCP connection to local machine
    • "10.179.2.135" - Remote database server IP
    • "db.example.com" - Remote database hostname

database (String)

  • Database name to use
  • Current value: "ran_monitor"
  • Note: Database must exist before starting RAN Monitor
  • Creation: CREATE DATABASE ran_monitor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

stacktrace (Boolean)

  • Include stacktraces in error messages
  • Current value: true
  • Development: true - Helps with debugging
  • Production: false - Reduces log noise

show_sensitive_data_on_connection_error (Boolean)

  • Show credentials in connection error messages
  • Current value: true
  • Development: true - Easier troubleshooting
  • Production: false - Prevents credential exposure in logs

pool_size (Integer)

  • Number of database connections to maintain
  • Current value: 10
  • Sizing Guide:
    • 1-5 devices: pool_size: 5
    • 6-20 devices: pool_size: 10
    • 21-50 devices: pool_size: 15
    • 50+ devices: pool_size: 20
  • Formula: Roughly 2 connections per base station + 5 for web UI

Web Endpoints

RAN Monitor runs multiple web servers for different purposes.

Main SOAP/API Endpoint

config :ran_monitor, RanMonitor.Web.Endpoint,
http: [ip: {0, 0, 0, 0}, port: 8080],
check_origin: false,
secret_key_base: "v5tOS1/QRonjwOky7adGGfkBbrJmiJyXhpesJy/jvSZhqLZkREV+rlo1/pR8lkbu",
server: true

Purpose: Main endpoint for base station communication (SOAP interface for Nokia NE3S protocol).

ip (Tuple)

  • Interface to bind to
  • Current value: {0, 0, 0, 0} (all interfaces)
  • Options:
    • {0, 0, 0, 0} - Listen on all network interfaces
    • {127, 0, 0, 1} - Listen only on localhost
    • {10, 179, 2, 135} - Listen on specific IP address

port (Integer)

  • TCP port number
  • Current value: 8080
  • Note: Base stations must be configured to send data to this port
  • Firewall: Ensure port is open for base station IPs

check_origin (Boolean)

  • Validate WebSocket/HTTP origin headers
  • Current value: false
  • Explanation: Set to false for SOAP API (not user-facing web UI)

secret_key_base (String)

  • Cryptographic signing key for sessions
  • Current value: 64-character random string
  • Generation: mix phx.gen.secret
  • Security: Keep this secret, never commit to public repositories
  • Impact: Changing this invalidates all existing sessions

server (Boolean)

  • Start the endpoint when application starts
  • Current value: true
  • Always: Should be true in runtime.exs

Control Panel Web UI

# Get HTTPS port from environment variable, default to 9443
https_port = String.to_integer(System.get_env("CONTROL_PANEL_HTTPS_PORT") || "9443")

config :control_panel, ControlPanelWeb.Endpoint,
url: [host: "0.0.0.0", port: https_port, scheme: "https"],
https: [
ip: {0, 0, 0, 0},
port: https_port,
keyfile: "priv/cert/omnitouch.pem",
certfile: "priv/cert/omnitouch.crt"
]

Purpose: HTTPS endpoint for the web-based control panel UI.

Environment Variables:

  • CONTROL_PANEL_HTTPS_PORT - HTTPS port number (default: 9443)
    • Set this environment variable to change the HTTPS port at runtime
    • Example: export CONTROL_PANEL_HTTPS_PORT=8443

url (Keyword list)

  • External URL configuration
  • host: "0.0.0.0" - Accept connections from any host
  • port: Uses https_port variable (configurable via CONTROL_PANEL_HTTPS_PORT)
  • scheme: "https" - Use HTTPS protocol

https (Keyword list)

  • HTTPS server configuration
  • ip: {0, 0, 0, 0} - Bind to all interfaces
  • port: Uses https_port variable (must match url port)
  • keyfile: Path to SSL private key
  • certfile: Path to SSL certificate

SSL Certificate Files:

  • Must be valid SSL/TLS certificates
  • Self-signed certificates work for lab environments
  • Production should use CA-signed certificates
  • Generate self-signed:
    openssl req -newkey rsa:2048 -nodes -keyout omnitouch.pem -x509 -days 365 -out omnitouch.crt

Nokia AirScale Webhook Endpoint

config :ran_monitor, RanMonitor.Web.Nokia.Airscale.Endpoint,
url: [host: "0.0.0.0"],
http: [ip: {0, 0, 0, 0}, port: 9076],
server: true

Purpose: Receives real-time performance data from Nokia AirScale base stations.

port (Integer)

  • Current value: 9076
  • Note: Must match the port configured in base station PMCADM (rTpmCollEntityPortNum)
  • Coordination: This port must match what you configured in the Nokia WebLM Parameter Editor

Logger Configuration

config :logger,
level: :info

config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]

Log Level

level (Atom)

  • Controls verbosity of logging
  • Current value: :info
  • Options:
    • :debug - Extremely verbose, all details
    • :info - Normal operations, recommended for production
    • :warning - Only warnings and errors
    • :error - Only errors

When to Use Each Level:

  • Development: :debug - See all internal operations
  • Production: :info - Balance between visibility and noise
  • Troubleshooting: Temporarily set to :debug, then revert
  • Quiet Production: :warning - Only alert on issues

Console Format

format (String)

  • How log messages appear
  • Current value: "$time $metadata[$level] $message\n"
  • Variables:
    • $time - Timestamp
    • $metadata - Contextual information
    • $level - Log level (info, error, etc.)
    • $message - Actual log message

metadata (List of atoms)

  • Additional context to include
  • Current value: [:request_id]
  • request_id: Tracks individual HTTP requests through the system

Nokia Integration

This section configures how RAN Monitor communicates with Nokia base stations.

config :ran_monitor,
general: %{
mcc: "505",
mnc: "57"
},
nokia: %{
ne3s: %{
webhook_url: "http://10.5.198.200:9076/webhook",
private_key: Path.join(Application.app_dir(:ran_monitor, "priv"), "external/nokia/ne.key.pem"),
public_key: Path.join(Application.app_dir(:ran_monitor, "priv"), "external/nokia/ne.cert.der"),
reregister_interval: 30
},
airscales: [
%{
address: "10.7.15.67",
name: "ONS-Lab-Airscale",
port: "8080",
web_username: "Nemuadmin",
web_password: "nemuuser"
}
]
}

General Settings

mcc (String)

  • Mobile Country Code
  • Current value: "505"
  • Usage: Identifies the country for 3GPP networks
  • Format: 3 digits
  • Reference: ITU-T E.212

mnc (String)

  • Mobile Network Code
  • Current value: "57"
  • Usage: Identifies the specific network operator
  • Format: 2 or 3 digits

NE3S Configuration (Nokia NE3S Protocol)

webhook_url (String)

  • URL where base stations send notifications
  • Current value: "http://10.5.198.200:9076/webhook"
  • Format: http://<ran-monitor-ip>:<port>/webhook
  • IP Address: Must be IP address where RAN Monitor is running
  • Port: Must match RanMonitor.Web.Nokia.Airscale.Endpoint port (9076)
  • Path: Always /webhook

private_key (String - File path)

  • Private key for manager authentication
  • Current value: priv/external/nokia/ne.key.pem
  • Format: PEM encoded private key
  • Security: Keep this file secure, never share
  • Generation: Provided by Nokia or generated with OpenSSL

public_key (String - File path)

  • Public certificate for manager identity
  • Current value: priv/external/nokia/ne.cert.der
  • Format: DER encoded certificate
  • Usage: Sent to base station during registration
  • Pair: Must correspond to private_key

reregister_interval (Integer)

  • How often to re-register with base stations (seconds)
  • Current value: 30
  • Explanation: Sessions expire, periodic re-registration maintains connection
  • Range: 30-300 seconds
  • Recommendation: 30 seconds for reliable monitoring

AirScale Base Stations

airscales (List of maps)

  • List of Nokia AirScale base stations to monitor
  • Current value: One base station configured

Each base station entry requires:

address (String)

  • IP address of the base station
  • Current value: "10.7.15.66"
  • Format: IPv4 address as string
  • Network: Must be reachable from RAN Monitor server
  • Verification: ping 10.7.15.66 should succeed

name (String)

  • Friendly name for identification
  • Current value: "ONS-Lab-Airscale"
  • Usage: Appears in Web UI, logs, and InfluxDB tags
  • Recommendation: Use descriptive names (site codes, locations, etc.)
  • Examples:
    • "NYC-Site-A-BS1"
    • "LAX-Tower-Main"
    • "TestLab-Airscale-01"

port (String)

  • Management interface port on base station
  • Current value: "8080"
  • Standard: Nokia AirScale typically uses 8080
  • Verification: Check base station documentation
  • Note: Value is a string, not integer

web_username (String)

  • Username for WebLM authentication
  • Current value: "Nemuadmin"
  • Usage: Used for API calls to manage base station
  • Privileges: Should have configuration read/write access
  • Note: Case-sensitive

web_password (String)

  • Password for WebLM authentication
  • Current value: "nemuuser"
  • Security: Should be stored in environment variables in production
  • Rotation: Change regularly according to security policy

Adding Multiple Base Stations

To monitor multiple base stations, add additional entries to the airscales list:

airscales: [
%{
address: "10.7.15.66",
name: "ONS-Lab-Airscale",
port: "8080",
web_username: "Nemuadmin",
web_password: "nemuuser"
},
%{
address: "10.7.15.67",
name: "Site-A-Tower-1",
port: "8080",
web_username: "admin",
web_password: "password123"
},
%{
address: "192.168.100.50",
name: "Site-B-Indoor",
port: "8080",
web_username: "admin",
web_password: "different_password"
}
]

InfluxDB Configuration

config :ran_monitor, RanMonitor.InfluxDbConnection,
auth: [
username: "monitor",
password: "sideunderTexasgalaxyview_61"
],
database: "nokia-monitor",
host: "10.179.2.135"

Purpose: Configures connection to InfluxDB time-series database for storing metrics, alarms, and configuration data.

Parameters Explained

auth (Keyword list)

  • Authentication credentials for InfluxDB
  • username: InfluxDB user account ("monitor")
  • password: InfluxDB password ("sideunderTexasgalaxyview_61")
  • Note: For InfluxDB 2.x, this might be an API token instead

database (String)

  • Bucket/database name in InfluxDB
  • Current value: "nokia-monitor"
  • InfluxDB 1.x: Database name
  • InfluxDB 2.x: Bucket name
  • Creation: Must be created before starting RAN Monitor
    # InfluxDB 1.x
    influx -execute 'CREATE DATABASE "nokia-monitor"'

    # InfluxDB 2.x
    influx bucket create -n nokia-monitor -o your-org

host (String)

  • InfluxDB server address
  • Current value: "10.179.2.135"
  • Format: IP address or hostname
  • Port: Default InfluxDB port (8086) is assumed
  • Examples:
    • "localhost" - Same server as RAN Monitor
    • "10.179.2.135" - Remote InfluxDB server
    • "influxdb.example.com" - Hostname

InfluxDB Connection Notes

Network Access:

  • RAN Monitor must be able to reach InfluxDB server on port 8086
  • Verify: curl http://10.179.2.135:8086/ping

Retention Policies:

  • Set via Web UI Data Retention page
  • Default: 30 days (720 hours)
  • Can be customized per base station

Data Retention Dashboard

Write Performance:

  • InfluxDB receives writes every collection interval (60s default)
  • Each base station generates hundreds of data points per interval
  • Monitor InfluxDB disk space regularly

Configuration Best Practices

Security

1. Protect Sensitive Data

# Instead of hardcoded passwords:
password: "omnitouch2024"

# Use environment variables:
password: System.get_env("DB_PASSWORD") || "default_password"

2. Restrict File Permissions

chmod 600 config/runtime.exs
chown ran_monitor:ran_monitor config/runtime.exs

3. Never Commit Secrets

  • Use .gitignore for runtime.exs if it contains secrets
  • Use environment variables or secret management systems
  • Rotate passwords regularly

Performance

1. Database Pool Sizing

  • Monitor connection usage
  • Increase pool_size if seeing connection timeout errors
  • Each device needs ~2 connections during active polling

2. Collection Intervals

  • Balance between data granularity and system load
  • 60 second intervals work well for most deployments
  • Shorter intervals (15s) for troubleshooting

3. InfluxDB Optimization

  • Use retention policies to manage disk usage
  • Monitor InfluxDB write performance
  • Consider separate InfluxDB server for large deployments

Reliability

1. Network Configuration

  • Use static IP addresses for all components
  • Verify network routes between RAN Monitor and base stations
  • Test connectivity before adding devices
  • Configure firewall rules appropriately

2. Logging Strategy

  • Development: :debug for detailed troubleshooting
  • Production: :info for operational visibility
  • Critical systems: Consider external log aggregation

3. Monitoring RAN Monitor

  • Monitor the monitor (meta-monitoring)
  • Watch for database connection errors
  • Track InfluxDB write success rates
  • Alert on base station disconnections

Maintenance

1. Configuration Changes

  • Always backup runtime.exs before changes
  • Test configuration in development first
  • Document changes with comments
  • Restart RAN Monitor after configuration changes

2. Adding Base Stations

# 1. Edit runtime.exs
vim config/runtime.exs

# 2. Validate Elixir syntax
elixir -c config/runtime.exs

# 3. Restart application
systemctl restart ran_monitor

3. Scaling Considerations

  • Monitor resource usage (CPU, memory, network)
  • Increase database pool size as device count grows
  • Consider separate InfluxDB instance at 50+ devices
  • Monitor disk space for both MySQL and InfluxDB

Example: Complete Configuration

Here's a complete example with multiple base stations and best practices applied:

import Config

# =============================================================================
# Database Configuration
# =============================================================================

config :ran_monitor, RanMonitor.Repo,
username: System.get_env("DB_USERNAME") || "ran_monitor_user",
password: System.get_env("DB_PASSWORD") || "change_this_password",
hostname: System.get_env("DB_HOST") || "localhost",
database: "ran_monitor",
stacktrace: false, # Production: hide stacktraces
show_sensitive_data_on_connection_error: false, # Production: hide credentials
pool_size: 15 # 6 base stations * 2 + 3 overhead

# =============================================================================
# Web Endpoints
# =============================================================================

config :ran_monitor, RanMonitor.Web.Endpoint,
http: [ip: {0, 0, 0, 0}, port: 8080],
check_origin: false,
secret_key_base: System.get_env("SECRET_KEY_BASE") || "generate_with_mix_phx_gen_secret",
server: true

config :control_panel, ControlPanelWeb.Endpoint,
url: [host: "0.0.0.0", port: 9443, scheme: "https"],
https: [
ip: {0, 0, 0, 0},
port: 9443,
keyfile: "priv/cert/server.key",
certfile: "priv/cert/server.crt"
]

config :ran_monitor, RanMonitor.Web.Nokia.Airscale.Endpoint,
url: [host: "0.0.0.0"],
http: [ip: {0, 0, 0, 0}, port: 9076],
server: true

# =============================================================================
# Logger Configuration
# =============================================================================

config :logger,
level: :info # Production setting

config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]

# =============================================================================
# Nokia Configuration
# =============================================================================

config :ran_monitor,
general: %{
mcc: "001",
mnc: "001"
},
nokia: %{
ne3s: %{
webhook_url: "http://10.179.2.135:9076/webhook",
private_key: Path.join(Application.app_dir(:ran_monitor, "priv"), "external/nokia/ne.key.pem"),
public_key: Path.join(Application.app_dir(:ran_monitor, "priv"), "external/nokia/ne.cert.der"),
reregister_interval: 30
},
airscales: [
# Site A - Main Tower
%{
address: "10.7.15.66",
name: "Site-A-Main-Tower",
port: "8080",
web_username: "admin",
web_password: System.get_env("BS_SITE_A_PASSWORD") || "password1"
},

# Site A - Backup Tower
%{
address: "10.7.15.67",
name: "Site-A-Backup-Tower",
port: "8080",
web_username: "admin",
web_password: System.get_env("BS_SITE_A_PASSWORD") || "password1"
},

# Site B - Indoor
%{
address: "10.7.16.10",
name: "Site-B-Indoor-DAS",
port: "8080",
web_username: "admin",
web_password: System.get_env("BS_SITE_B_PASSWORD") || "password2"
},

# Site C - Rooftop
%{
address: "192.168.100.50",
name: "Site-C-Rooftop",
port: "8080",
web_username: "admin",
web_password: System.get_env("BS_SITE_C_PASSWORD") || "password3"
},

# Lab - Test Equipment
%{
address: "10.5.198.100",
name: "Lab-Test-Airscale-01",
port: "8080",
web_username: "Nemuadmin",
web_password: "nemuuser"
},

# Lab - Development
%{
address: "10.5.198.101",
name: "Lab-Dev-Airscale-02",
port: "8080",
web_username: "Nemuadmin",
web_password: "nemuuser"
}
]
}

# =============================================================================
# InfluxDB Configuration
# =============================================================================

config :ran_monitor, RanMonitor.InfluxDbConnection,
auth: [
username: System.get_env("INFLUX_USERNAME") || "monitor",
password: System.get_env("INFLUX_PASSWORD") || "change_this_password"
],
database: "nokia-monitor",
host: System.get_env("INFLUX_HOST") || "10.179.2.135"