If you manage a NetScaler (now Citrix ADC) environment, you know that understanding the relationships between virtual servers, services, and backend pools can be challenging. The configuration file contains hundreds or thousands of lines, making it difficult to visualize what's actually running and how traffic flows through your infrastructure.
Demo of the UI
This is the main UI before it has the configuration file
Then when you give it the configuration file, you get an analysis of running configuration as below with the option to search, here will will user "autodiscover" as below:
The website will then break off the component down into sub categories as below:
I built a simple HTML-based tool that parses your NetScaler configuration file and displays it in an interactive, easy-to-understand format. Here's how to use it.
Step 1: Download Your NetScaler Running Configuration
First, you need to get the current running configuration from your NetScaler appliance.
Using the GUI (Web Interface):
- Log into your NetScaler management interface (typically
http://[NSIP]orhttps://[NSIP]) - Navigate to System → Diagnostics
- In the right pane, look for Technical Support Tools
- Click on Running Configuration
- The configuration will display in your browser
- Save the content to a file (you can use your browser's save function or copy/paste into a text file)
- Name it something like ns-running.conf
Alternatively, you can download the saved configuration file:
- Go to System → Diagnostics
- Under the Configuration section, you'll see ns.conf
- Click the Download button to save it locally
Using SSH/CLI:
If you prefer the command line, connect via SSH and run:
show ns runningConfig
Or download the file directly using SCP:
scp nsroot@<NSIP>:/nsconfig/ns.conf ./ns.conf
Step 2: Understanding the Analyzer Tool
The tool I created is a single HTML file with embedded JavaScript. It parses the NetScaler configuration syntax and extracts key information about your load balancing setup.
What It Shows (Enabled Objects Only)
By default, the analyzer displays only enabled services and virtual servers. This filters out disabled or test configurations, giving you a clean view of what's actually handling production traffic.
The tool organizes your configuration into four collapsible sections:
- Load Balancing Virtual Servers - Your LB vservers with their backend services
- Content Switching Virtual Servers - CS vservers with their target LB vservers and policies
- Services - Individual services mapped to backend servers
- Service Groups - Pooled services with member servers and weights
How the Parser Works
The JavaScript parser reads through the configuration file line by line, using regular expressions to extract configuration objects. Here's an example of how it parses a load balancing virtual server:
if (line.startsWith('add lb vserver ')) {
const match = line.match(/add lb vserver (\S+) (\S+) (\S+) (\S+)/);
if (match) {
const state = line.includes('-state DISABLED') ? 'DISABLED' : 'ENABLED';
const persistence = line.match(/-persistenceType (\S+)/);
const lbMethod = line.match(/-lbMethod (\S+)/);
configData.lbVservers[match[1]] = {
name: match[1],
protocol: match[2],
ip: match[3],
port: match[4],
state: state,
persistence: persistence ? persistence[1] : 'NONE',
lbMethod: lbMethod ? lbMethod[1] : 'ROUNDROBIN',
services: []
};
}
}
This code captures the vserver name, protocol (SSL, HTTP, TCP, etc.), VIP address, port, and optional parameters like persistence type and load balancing method.
Service-to-Server Mapping
The tool also resolves the relationship between services and their backend servers. When you click on a backend server tag, it displays the server details in a modal popup:
function showServerDetails(serverName) {
event.stopPropagation();
const server = configData.servers[serverName];
if (server) {
const modalContent = `
<h3>Server Details: ${serverName}</h3>
<div class="detail-section">
<h4>IP Address:</h4>
<div>${server.ip}</div>
</div>
${server.comment ? `
<div class="detail-section">
<h4>Comment:</h4>
<div>${server.comment}</div>
</div>
` : ''}
`;
document.getElementById('modalContent').innerHTML = modalContent;
document.getElementById('detailModal').classList.add('show');
}
}
Interactive Features
Each service card is clickable to expand additional details:
- Timeout settings (client and server)
- Compression settings
- Source IP preservation (USIP)
- The raw configuration command from the file
The search box at the top filters all cards in real-time, making it easy to find specific services, IP addresses, or protocols.
Step 3: Showing All Objects (Including Disabled)
If you want to see all objects including disabled ones, you need to modify the filtering logic in the displayResults()function.
Current Code (Enabled Only):
document.getElementById('lbVservers').innerHTML = Object.values(configData.lbVservers)
.filter(v => v.state === 'ENABLED')
.map(v => createLBCard(v)).join('') || '<p>No enabled LB VServers found</p>';
Modified Code (All Objects):
document.getElementById('lbVservers').innerHTML = Object.values(configData.lbVservers)
.map(v => createLBCard(v)).join('') || '<p>No LB VServers found</p>';
Simply remove the .filter(v => v.state === 'ENABLED') line.
You'll need to do this for all four sections:
Content Switching VServers:
// Change this:
document.getElementById('csVservers').innerHTML = Object.values(configData.csVservers)
.filter(v => v.state === 'ENABLED')
.map(v => createCSCard(v)).join('') || '<p>No enabled CS VServers found</p>';
// To this:
document.getElementById('csVservers').innerHTML = Object.values(configData.csVservers)
.map(v => createCSCard(v)).join('') || '<p>No CS VServers found</p>';
Services:
// Change this:
document.getElementById('services').innerHTML = Object.values(configData.services)
.filter(s => s.state === 'ENABLED')
.map(s => createServiceCard(s)).join('') || '<p>No enabled services found</p>';
// To this:
document.getElementById('services').innerHTML = Object.values(configData.services)
.map(s => createServiceCard(s)).join('') || '<p>No services found</p>';
Service Groups:
Service groups don't have a state filter by default, but the members do. To show disabled members, modify the createSGCard() function:
// Change this line:
const enabledMembers = sg.members.filter(m => m.state === 'ENABLED');
// To this:
const enabledMembers = sg.members; // Shows all members regardless of state
If you make these changes, I recommend adding a visual indicator for disabled objects. You can modify the card creation functions to add a badge:
<div class="service-type">${v.protocol}${v.state === 'DISABLED' ? ' <span style="background:#e74c3c;margin-left:5px;padding:2px 6px;border-radius:3px;font-size:10px;">DISABLED</span>' : ''}</div>
Why This Tool is Useful
Traditional NetScaler configuration files are text-based and can be overwhelming. This analyzer provides:
- Visual clarity - See what's enabled vs disabled at a glance
- Relationship mapping - Understand which backends serve which virtual servers
- Search capability - Quickly find services by name, IP, or protocol
- No installation required - Just open the HTML file in any modern browser
- Offline analysis - Parse configurations without accessing the NetScaler itself
I use this tool whenever I need to document a NetScaler environment, troubleshoot traffic flow issues, or audit which services are actually in use. It's particularly helpful when inheriting a NetScaler configuration from another team or preparing for migration projects.
The entire tool is self-contained in a single HTML file, making it easy to share with colleagues or use across different systems without dependencies.