System Operations - iamhelitha/3xui-api-client GitHub Wiki
System Operations Guide
ā Status: Fully tested and working
This guide covers all system-level operations using the 3xui-api-client library. System operations include monitoring online clients and creating backups of your 3X-UI configuration.
Table of Contents
- Overview
- Get Online Clients
- Create System Backup
- Server-Side Implementation
- Error Handling
- Best Practices
- Use Cases
Overview
System operations provide essential monitoring and maintenance capabilities for your 3X-UI server:
- Online Client Monitoring: Track currently connected clients in real-time
- System Backups: Create backups of your entire 3X-UI configuration
- Health Monitoring: Monitor system status and connectivity
- Maintenance Operations: Perform routine system maintenance tasks
ā ļø Important: These operations affect the entire system and should be used with appropriate permissions and monitoring.
Get Online Clients
Monitor currently connected clients across all inbounds:
const ThreeXUI = require('3xui-api-client');
async function getOnlineClients() {
try {
console.log('š„ Getting online clients...');
const response = await client.getOnlineClients();
if (response.success) {
const onlineClients = response.obj;
if (onlineClients && Array.isArray(onlineClients) && onlineClients.length > 0) {
console.log(`š Found ${onlineClients.length} online clients:`);
onlineClients.forEach((client, index) => {
console.log(`\nš Client ${index + 1}:`);
console.log(` Email: ${client.email}`);
console.log(` IP Address: ${client.ip}`);
console.log(` Connected Since: ${new Date(client.connectedAt)}`);
console.log(` Inbound ID: ${client.inboundId}`);
console.log(` Protocol: ${client.protocol}`);
console.log(` Location: ${client.location || 'Unknown'}`);
console.log(` Traffic: ā${client.upload} ā${client.download} bytes`);
});
// Group by inbound for summary
const byInbound = onlineClients.reduce((acc, client) => {
acc[client.inboundId] = (acc[client.inboundId] || 0) + 1;
return acc;
}, {});
console.log('\nš Summary by Inbound:');
Object.entries(byInbound).forEach(([inboundId, count]) => {
console.log(` Inbound ${inboundId}: ${count} clients`);
});
} else {
console.log('š No clients currently online');
}
} else {
console.log('ā Failed to get online clients:', response.msg);
}
return response;
} catch (error) {
console.error('ā Error getting online clients:', error.message);
throw error;
}
}
// Usage example
const result = await getOnlineClients();
API Response Example (No Online Clients)
{
"success": true,
"msg": "",
"obj": null
}
Note: The response shows "obj": null
when no clients are currently online. When clients are connected, the response would contain an array of client connection details.
Expected Response Structure (When Clients Are Online)
{
"success": true,
"msg": "",
"obj": [
{
"email": "user23c5n7",
"ip": "192.168.1.100",
"connectedAt": 1735265123000,
"inboundId": 5,
"protocol": "vless",
"location": "US",
"upload": 1024000,
"download": 5120000
}
]
}
Create System Backup
Create a complete backup of your 3X-UI configuration:
async function createBackup() {
try {
console.log('š¾ Creating system backup...');
console.log('ā ļø This will create a backup of the current 3X-UI configuration');
// Confirm before proceeding
console.log('\nš Backup will include:');
console.log(' ⢠All inbound configurations');
console.log(' ⢠Client settings and credentials');
console.log(' ⢠System settings');
console.log(' ⢠Database data');
const response = await client.createBackup();
if (response.success || response === "") {
console.log('ā
Backup created successfully');
// The response might be empty string for successful backup
if (typeof response === 'string' && response === "") {
console.log('š Backup file created on server');
console.log(' Location: Check your 3X-UI backup directory');
console.log(' Filename: Typically includes timestamp');
}
// Log backup creation
const backupInfo = {
created_at: new Date(),
type: 'full_system_backup',
status: 'completed',
file_size: response.fileSize || 'unknown',
backup_path: response.path || 'server_default'
};
console.log('š Backup Details:', backupInfo);
} else {
console.log('ā Backup creation failed:', response.msg || 'Unknown error');
}
return response;
} catch (error) {
console.error('ā Error creating backup:', error.message);
throw error;
}
}
// Usage with confirmation
async function confirmedBackup() {
console.log('š Initiating system backup...');
console.log('ā ļø This operation may take several minutes depending on your data size');
try {
const result = await createBackup();
return result;
} catch (error) {
console.error('š„ Backup operation failed:', error.message);
return { success: false, error: error.message };
}
}
// Execute backup
const backupResult = await confirmedBackup();
API Response Example (Create Backup)
""
Note: The 3X-UI backup API returns an empty string (""
) when the backup is created successfully. This is the expected behavior based on the actual test results.
Response Interpretation
- Empty string (
""
): Backup created successfully - Object with
success: false
: Backup failed with error message - Error thrown: Network or authentication issue
Server-Side Implementation
Complete system operations management with database integration:
const ThreeXUI = require('3xui-api-client');
class SystemOperationsManager {
constructor(serverUrl, username, password, database) {
this.client = new ThreeXUI(serverUrl, username, password);
this.db = database;
}
async ensureAuthenticated() {
const session = await this.db.sessions.findOne({
where: {
server_url: this.client.baseURL,
expires_at: { $gt: new Date() }
}
});
if (!session) {
await this.client.login();
await this.db.sessions.create({
server_url: this.client.baseURL,
session_cookie: this.client.cookie,
created_at: new Date(),
expires_at: new Date(Date.now() + 3600000)
});
} else {
this.client.cookie = session.session_cookie;
this.client.api.defaults.headers.Cookie = session.session_cookie;
}
}
async monitorOnlineClients() {
await this.ensureAuthenticated();
try {
const response = await this.client.getOnlineClients();
if (response.success) {
const onlineClients = response.obj || [];
// Store current online status in database
await this.db.online_snapshots.create({
timestamp: new Date(),
total_online: onlineClients.length,
clients: onlineClients,
server_url: this.client.baseURL
});
// Update client last_seen timestamps
for (const client of onlineClients) {
await this.db.clients.update(
{ email: client.email },
{
last_seen: new Date(),
last_ip: client.ip,
status: 'online'
}
);
}
// Mark offline clients
const onlineEmails = onlineClients.map(c => c.email);
await this.db.clients.updateMany(
{
email: { $nin: onlineEmails },
status: 'online'
},
{ status: 'offline' }
);
return {
success: true,
online_count: onlineClients.length,
clients: onlineClients
};
}
return response;
} catch (error) {
console.error('ā Error monitoring online clients:', error.message);
throw error;
}
}
async createScheduledBackup(schedule = 'daily') {
await this.ensureAuthenticated();
try {
console.log(`š¾ Creating ${schedule} backup...`);
const backupStart = new Date();
const response = await this.client.createBackup();
const backupEnd = new Date();
const isSuccess = response === "" || response.success !== false;
// Log backup in database
await this.db.backups.create({
server_url: this.client.baseURL,
backup_type: 'system_full',
schedule_type: schedule,
started_at: backupStart,
completed_at: backupEnd,
duration_ms: backupEnd - backupStart,
status: isSuccess ? 'completed' : 'failed',
response: response,
automated: true
});
if (isSuccess) {
console.log('ā
Scheduled backup completed successfully');
// Cleanup old backups if configured
await this.cleanupOldBackups();
return { success: true, created_at: backupStart };
} else {
console.log('ā Scheduled backup failed');
return { success: false, error: response.msg || 'Unknown error' };
}
} catch (error) {
// Log failed backup
await this.db.backups.create({
server_url: this.client.baseURL,
backup_type: 'system_full',
schedule_type: schedule,
started_at: new Date(),
status: 'failed',
error: error.message,
automated: true
});
throw error;
}
}
async generateSystemReport() {
await this.ensureAuthenticated();
try {
// Get online clients
const onlineResponse = await this.client.getOnlineClients();
const onlineClients = onlineResponse.success ? (onlineResponse.obj || []) : [];
// Get all inbounds
const inboundsResponse = await this.client.getInbounds();
const inbounds = inboundsResponse.success ? inboundsResponse.obj : [];
// Calculate statistics
const report = {
generated_at: new Date(),
server_url: this.client.baseURL,
system_status: {
online_clients: onlineClients.length,
total_inbounds: inbounds.length,
active_inbounds: inbounds.filter(i => i.enable).length,
total_clients: inbounds.reduce((sum, i) => sum + (i.clientStats?.length || 0), 0)
},
traffic_summary: {
total_upload: inbounds.reduce((sum, i) => sum + i.up, 0),
total_download: inbounds.reduce((sum, i) => sum + i.down, 0),
total_traffic: inbounds.reduce((sum, i) => sum + i.total, 0)
},
inbound_details: inbounds.map(inbound => ({
id: inbound.id,
port: inbound.port,
protocol: inbound.protocol,
enabled: inbound.enable,
client_count: inbound.clientStats?.length || 0,
traffic: { up: inbound.up, down: inbound.down, total: inbound.total }
})),
online_clients: onlineClients
};
// Store report in database
await this.db.system_reports.create(report);
return report;
} catch (error) {
console.error('ā Error generating system report:', error.message);
throw error;
}
}
async healthCheck() {
try {
await this.ensureAuthenticated();
const health = {
timestamp: new Date(),
server_url: this.client.baseURL,
authentication: 'success',
api_responsive: true,
checks: {}
};
// Test online clients endpoint
try {
const onlineResponse = await this.client.getOnlineClients();
health.checks.online_clients = onlineResponse.success ? 'pass' : 'fail';
} catch (error) {
health.checks.online_clients = 'error';
health.api_responsive = false;
}
// Test inbounds endpoint
try {
const inboundsResponse = await this.client.getInbounds();
health.checks.inbounds = inboundsResponse.success ? 'pass' : 'fail';
} catch (error) {
health.checks.inbounds = 'error';
health.api_responsive = false;
}
// Test backup capability
try {
// We don't actually create a backup during health check
health.checks.backup_ready = 'pass';
} catch (error) {
health.checks.backup_ready = 'error';
}
// Store health check result
await this.db.health_checks.create(health);
return health;
} catch (error) {
return {
timestamp: new Date(),
server_url: this.client.baseURL,
authentication: 'failed',
api_responsive: false,
error: error.message
};
}
}
}
module.exports = SystemOperationsManager;
Error Handling
Common errors and solutions:
Authentication Errors
try {
const response = await client.getOnlineClients();
} catch (error) {
if (error.message.includes('401')) {
console.log('Session expired, re-authenticating...');
await client.login();
const response = await client.getOnlineClients();
}
}
Network Connectivity Issues
async function robustSystemOperation(operation) {
let retries = 3;
while (retries > 0) {
try {
return await operation();
} catch (error) {
retries--;
if (error.code === 'ECONNREFUSED' && retries > 0) {
console.log(`š Connection failed, retrying... (${retries} attempts left)`);
await new Promise(resolve => setTimeout(resolve, 5000));
} else {
throw error;
}
}
}
}
// Usage
const result = await robustSystemOperation(() => client.getOnlineClients());
Backup Failures
async function safeBackup() {
try {
const response = await client.createBackup();
// Handle empty string response (success)
if (response === "") {
return { success: true, message: 'Backup created successfully' };
}
// Handle object response
if (typeof response === 'object' && response.success === false) {
throw new Error(response.msg || 'Backup failed');
}
return { success: true, response: response };
} catch (error) {
console.error('ā Backup failed:', error.message);
// Attempt to diagnose the issue
if (error.message.includes('space')) {
console.log('š” Suggestion: Check available disk space on server');
} else if (error.message.includes('permission')) {
console.log('š” Suggestion: Check backup directory permissions');
}
return { success: false, error: error.message };
}
}
Best Practices
1. Regular Monitoring
const cron = require('node-cron');
// Monitor online clients every 5 minutes
cron.schedule('*/5 * * * *', async () => {
try {
const onlineClients = await systemManager.monitorOnlineClients();
// Check for unusual patterns
if (onlineClients.online_count === 0) {
console.log('ā ļø No clients online - check server status');
} else if (onlineClients.online_count > 100) {
console.log('š High client count detected:', onlineClients.online_count);
}
} catch (error) {
console.error('ā Monitoring failed:', error.message);
}
});
2. Automated Backups
// Daily backup at 2 AM
cron.schedule('0 2 * * *', async () => {
console.log('š¾ Starting daily backup...');
try {
const result = await systemManager.createScheduledBackup('daily');
if (result.success) {
console.log('ā
Daily backup completed');
// Send success notification
await sendAdminNotification('Daily backup completed successfully');
} else {
throw new Error(result.error);
}
} catch (error) {
console.error('ā Daily backup failed:', error.message);
await sendAdminAlert('Daily backup failed', error.message);
}
});
// Weekly backup with retention
cron.schedule('0 1 * * 0', async () => {
await systemManager.createScheduledBackup('weekly');
await systemManager.cleanupOldBackups();
});
3. Health Monitoring
// Health check every hour
cron.schedule('0 * * * *', async () => {
const health = await systemManager.healthCheck();
if (!health.api_responsive) {
await sendCriticalAlert('3X-UI API not responding', health);
}
// Check specific service health
Object.entries(health.checks).forEach(([service, status]) => {
if (status === 'error' || status === 'fail') {
console.log(`ā ļø Service ${service} is ${status}`);
}
});
});
4. Performance Monitoring
async function performanceMonitoring() {
const startTime = Date.now();
try {
// Test response times
const onlineStart = Date.now();
await client.getOnlineClients();
const onlineTime = Date.now() - onlineStart;
const inboundsStart = Date.now();
await client.getInbounds();
const inboundsTime = Date.now() - inboundsStart;
const metrics = {
timestamp: new Date(),
response_times: {
online_clients: onlineTime,
get_inbounds: inboundsTime
},
total_time: Date.now() - startTime
};
// Alert if response times are slow
if (onlineTime > 5000 || inboundsTime > 5000) {
console.log('ā ļø Slow API response detected:', metrics);
}
await database.performance_metrics.create(metrics);
} catch (error) {
console.error('ā Performance monitoring failed:', error.message);
}
}
// Run performance monitoring every 15 minutes
setInterval(performanceMonitoring, 900000);
Use Cases
Real-Time Dashboard
class RealTimeDashboard {
constructor(systemManager) {
this.systemManager = systemManager;
this.subscribers = [];
}
async startMonitoring(interval = 30000) {
setInterval(async () => {
try {
const data = await this.gatherDashboardData();
this.broadcastUpdate(data);
} catch (error) {
console.error('ā Dashboard update failed:', error.message);
}
}, interval);
}
async gatherDashboardData() {
const [onlineClients, systemReport] = await Promise.all([
this.systemManager.monitorOnlineClients(),
this.systemManager.generateSystemReport()
]);
return {
timestamp: new Date(),
online_clients: onlineClients.online_count,
total_traffic: systemReport.traffic_summary.total_traffic,
active_inbounds: systemReport.system_status.active_inbounds,
system_health: await this.systemManager.healthCheck()
};
}
broadcastUpdate(data) {
this.subscribers.forEach(callback => {
try {
callback(data);
} catch (error) {
console.error('ā Dashboard subscriber error:', error.message);
}
});
}
subscribe(callback) {
this.subscribers.push(callback);
}
}
// Usage
const dashboard = new RealTimeDashboard(systemManager);
dashboard.subscribe((data) => {
console.log('š Dashboard Update:', data);
// Update web interface, send to monitoring service, etc.
});
dashboard.startMonitoring();
Automated Maintenance System
class MaintenanceSystem {
constructor(systemManager) {
this.systemManager = systemManager;
}
scheduleMaintenanceTasks() {
// Hourly online client monitoring
cron.schedule('0 * * * *', () => {
this.performTask('online_monitoring');
});
// Daily backup
cron.schedule('0 2 * * *', () => {
this.performTask('daily_backup');
});
// Weekly system report
cron.schedule('0 0 * * 0', () => {
this.performTask('weekly_report');
});
// Monthly cleanup
cron.schedule('0 1 1 * *', () => {
this.performTask('monthly_cleanup');
});
}
async performTask(taskType) {
console.log(`š§ Starting ${taskType}...`);
try {
switch (taskType) {
case 'online_monitoring':
await this.monitorAndAlert();
break;
case 'daily_backup':
await this.createDailyBackup();
break;
case 'weekly_report':
await this.generateWeeklyReport();
break;
case 'monthly_cleanup':
await this.performMonthlyCleanup();
break;
}
console.log(`ā
${taskType} completed`);
} catch (error) {
console.error(`ā ${taskType} failed:`, error.message);
await this.sendMaintenanceAlert(taskType, error);
}
}
async monitorAndAlert() {
const onlineClients = await this.systemManager.monitorOnlineClients();
const health = await this.systemManager.healthCheck();
// Check for issues
if (!health.api_responsive) {
await this.sendCriticalAlert('API not responsive', health);
}
if (onlineClients.online_count === 0) {
await this.sendWarningAlert('No clients online', onlineClients);
}
}
async createDailyBackup() {
const result = await this.systemManager.createScheduledBackup('daily');
if (!result.success) {
throw new Error(result.error);
}
await this.sendNotification('Daily backup completed successfully');
}
async generateWeeklyReport() {
const report = await this.systemManager.generateSystemReport();
// Send weekly summary to administrators
await this.sendWeeklyReport(report);
}
async performMonthlyCleanup() {
await this.systemManager.cleanupOldBackups();
// Additional cleanup tasks
await this.cleanupOldLogs();
await this.optimizeDatabase();
}
}
High-Availability Monitoring
class HAMonitoring {
constructor(primarySystem, backupSystems = []) {
this.primary = primarySystem;
this.backups = backupSystems;
this.currentActive = this.primary;
}
async startHAMonitoring() {
setInterval(async () => {
await this.checkSystemHealth();
}, 60000); // Check every minute
}
async checkSystemHealth() {
try {
const health = await this.currentActive.healthCheck();
if (!health.api_responsive) {
console.log('ā ļø Primary system unresponsive, attempting failover...');
await this.attemptFailover();
} else {
console.log('ā
Primary system healthy');
}
} catch (error) {
console.error('ā Health check failed:', error.message);
await this.attemptFailover();
}
}
async attemptFailover() {
for (const backup of this.backups) {
try {
const health = await backup.healthCheck();
if (health.api_responsive) {
console.log('ā
Failing over to backup system');
this.currentActive = backup;
await this.sendFailoverAlert();
return;
}
} catch (error) {
console.log('ā Backup system also unavailable');
}
}
await this.sendCriticalAlert('All systems unavailable');
}
async sendFailoverAlert() {
const alert = {
type: 'failover',
timestamp: new Date(),
message: 'System failover completed',
active_system: this.currentActive.client.baseURL
};
// Send to monitoring service, email, SMS, etc.
console.log('šØ FAILOVER ALERT:', alert);
}
}
Navigation
Previous | Next |
---|---|
ā Traffic Management | Home ā |
Related Documentation
- Authentication Guide - Connection & session management
- Inbound Management - VPN server configuration
- Client Management - User account operations
- Traffic Management - Data monitoring & control
- Home - Main documentation page
Last updated: January 2025