Files
Archive/nodepass/docs/en/api.md
2025-09-06 20:35:55 +02:00

1138 lines
41 KiB
Markdown

# NodePass API Reference
## Overview
NodePass provides RESTful API in Master Mode, supporting frontend integration and automation. This document covers all interfaces, data structures, and best practices.
## Master Mode API
In Master Mode (`master://`), NodePass supports:
1. Creating and managing server/client instances
2. Real-time monitoring of status, traffic, and health checks
3. Instance control (start, stop, restart, reset traffic)
4. Auto-restart policy configuration
5. Flexible parameter configuration
### Base URL
```
master://<api_addr>/<prefix>?<log>&<tls>
```
- `<api_addr>`: Listen address (e.g., `0.0.0.0:9090`)
- `<prefix>`: API path prefix (default `/api`)
### Starting Master Mode
```bash
nodepass "master://0.0.0.0:9090?log=info"
nodepass "master://0.0.0.0:9090/admin?log=info&tls=1"
```
### Main Endpoints
| Endpoint | Method | Description |
|--------------------|--------|--------------------------|
| `/instances` | GET | Get all instances |
| `/instances` | POST | Create new instance |
| `/instances/{id}` | GET | Get instance details |
| `/instances/{id}` | PATCH | Update/control instance |
| `/instances/{id}` | PUT | Update instance URL |
| `/instances/{id}` | DELETE | Delete instance |
| `/events` | GET | SSE real-time event stream |
| `/info` | GET | Get master service info |
| `/tcping` | GET | TCP connection test |
| `/openapi.json` | GET | OpenAPI specification |
| `/docs` | GET | Swagger UI documentation |
### API Authentication
API Key authentication is enabled by default, automatically generated and saved in `nodepass.gob` on first startup.
- Protected endpoints: `/instances`, `/instances/{id}`, `/events`, `/info`, `/tcping`
- Public endpoints: `/openapi.json`, `/docs`
- Authentication method: Add `X-API-Key: <key>` to request headers
- Reset Key: PATCH `/instances/********`, body `{ "action": "restart" }`
### Instance Data Structure
```json
{
"id": "a1b2c3d4",
"alias": "alias",
"type": "client|server",
"status": "running|stopped|error",
"url": "...",
"restart": true,
"mode": 0,
"ping": 0,
"pool": 0,
"tcps": 0,
"udps": 0,
"tcprx": 0,
"tcptx": 0,
"udprx": 0,
"udptx": 0
}
```
- `mode`: Instance mode
- `ping`/`pool`: Health check data
- `tcps`/`udps`: Current active connection count statistics
- `tcprx`/`tcptx`/`udprx`/`udptx`: Cumulative traffic statistics
- `restart`: Auto-restart policy
### Instance URL Format
- Server: `server://<bind_addr>:<bind_port>/<target_host>:<target_port>?<parameters>`
- Client: `client://<server_host>:<server_port>/<local_host>:<local_port>?<parameters>`
- Supported parameters: `log`, `tls`, `crt`, `key`, `min`, `max`, `mode`, `read`, `rate`
### URL Query Parameters
- `log`: Log level (`none`, `debug`, `info`, `warn`, `error`, `event`)
- `tls`: TLS encryption mode (`0`, `1`, `2`) - Server/Master mode only
- `crt`/`key`: Certificate/key file paths (when `tls=2`)
- `min`/`max`: Connection pool capacity (`min` set by client, `max` set by server and passed to client during handshake)
- `mode`: Runtime mode control (`0`, `1`, `2`) - Controls operation behavior
- For server: `0`=auto, `1`=reverse mode, `2`=forward mode
- For client: `0`=auto, `1`=single-end forwarding, `2`=dual-end handshake
- `read`: Data read timeout duration (e.g., 1h, 30m, 15s)
- `rate`: Bandwidth rate limit in Mbps (0=unlimited)
- `proxy`: PROXY protocol support (`0`, `1`) - When enabled, sends PROXY protocol v1 header before data transmission
### Real-time Event Stream (SSE)
- Event types: `initial`, `create`, `update`, `delete`, `shutdown`, `log`
- `log` events only push normal logs, traffic/health check logs are filtered
- Connect to `/events` for real-time instance changes and logs
### Additional Notes
- All instances, traffic, health checks, aliases, and auto-restart policies are persistently stored and automatically restored after restart
- Detailed API specification at `/openapi.json`, Swagger UI at `/docs`
```javascript
// Regenerate API Key (requires knowing current API Key)
async function regenerateApiKey() {
const response = await fetch(`${API_URL}/instances/${apiKeyID}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'current-api-key'
},
body: JSON.stringify({ action: 'restart' })
});
const result = await response.json();
return result.url; // New API Key
}
```
**Note**: API Key ID is fixed as `********` (eight asterisks). In the internal implementation, this is a special instance ID used to store and manage the API Key.
### Using SSE for Real-time Event Monitoring
NodePass now supports Server-Sent Events (SSE) functionality for real-time monitoring of instance state changes. This enables frontend applications to receive immediate notifications of instance creation, updates, and deletions without the need for polling.
#### Using the SSE Endpoint
The SSE endpoint is located at:
```
GET /events
```
This endpoint establishes a persistent connection and delivers events in real-time using the SSE protocol format. If API Key authentication is enabled, you need to include a valid API Key in the request headers.
#### Event Types
The following event types are supported:
1. `initial` - Sent when connection is established, contains current state of all instances
2. `create` - Sent when a new instance is created
3. `update` - Sent when an instance is updated (state changes, start/stop operations)
4. `delete` - Sent when an instance is deleted
5. `shutdown` - Sent when the master service is about to shut down, notifying frontend applications to close connections
6. `log` - Sent when an instance produces new log content, contains log text
#### Handling Instance Logs
In frontend applications, you can handle instance logs by listening to `log` events. Here's an example function to append logs to a specific instance's UI:
```javascript
// Handle log events
function appendLogToInstanceUI(instanceId, logText) {
// Find or create log container
let logContainer = document.getElementById(`logs-${instanceId}`);
if (!logContainer) {
logContainer = document.createElement('div');
logContainer.id = `logs-${instanceId}`;
document.getElementById('instance-container').appendChild(logContainer);
}
// Create new log entry
const logEntry = document.createElement('div');
logEntry.className = 'log-entry';
// You can parse ANSI color codes or format logs here
logEntry.textContent = logText;
// Add to container
logContainer.appendChild(logEntry);
// Scroll to latest log
logContainer.scrollTop = logContainer.scrollHeight;
}
```
Best practices for log integration:
1. **Buffer management**: Limit the number of log entries to prevent memory issues
2. **ANSI color parsing**: Parse ANSI color codes in logs for better readability
3. **Filtering options**: Provide options to filter logs by severity or content
4. **Search functionality**: Allow users to search within instance logs
5. **Log persistence**: Optionally save logs to local storage for viewing after page refresh
#### JavaScript Client Implementation
Here's an example of consuming the SSE endpoint in JavaScript frontend:
```javascript
function connectToEventSource() {
const eventSource = new EventSource(`${API_URL}/events`, {
// If authentication is needed, native EventSource doesn't support custom headers
// Need to use fetch API to implement custom SSE client
});
// If using API Key, need to use custom implementation instead of native EventSource
// Below is an example using native EventSource
eventSource.addEventListener('instance', (event) => {
const data = JSON.parse(event.data);
switch (data.type) {
case 'initial':
console.log('Initial instance state:', data.instance);
updateInstanceUI(data.instance);
break;
case 'create':
console.log('Instance created:', data.instance);
addInstanceToUI(data.instance);
break;
case 'update':
console.log('Instance updated:', data.instance);
updateInstanceUI(data.instance);
break;
case 'delete':
console.log('Instance deleted:', data.instance);
removeInstanceFromUI(data.instance.id);
break;
case 'log':
console.log(`Instance ${data.instance.id} log:`, data.logs);
appendLogToInstanceUI(data.instance.id, data.logs);
break;
case 'shutdown':
console.log('Master service is shutting down');
// Close event source and show notification
eventSource.close();
showShutdownNotification();
break;
}
});
eventSource.addEventListener('error', (error) => {
console.error('SSE connection error:', error);
// Try to reconnect after delay
setTimeout(() => {
eventSource.close();
connectToEventSource();
}, 5000);
});
return eventSource;
}
// Example of creating SSE connection with API Key
function connectToEventSourceWithApiKey(apiKey) {
// Native EventSource doesn't support custom headers, need to use fetch API
fetch(`${API_URL}/events`, {
method: 'GET',
headers: {
'X-API-Key': apiKey,
'Cache-Control': 'no-cache'
}
}).then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';
function processStream() {
reader.read().then(({ value, done }) => {
if (done) {
console.log('Connection closed');
// Try to reconnect
setTimeout(() => connectToEventSourceWithApiKey(apiKey), 5000);
return;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.trim() === '') continue;
const eventMatch = line.match(/^event: (.+)$/m);
const dataMatch = line.match(/^data: (.+)$/m);
if (eventMatch && dataMatch) {
const data = JSON.parse(dataMatch[1]);
// Handle events - see switch code above
}
}
processStream();
}).catch(error => {
console.error('Read error:', error);
// Try to reconnect
setTimeout(() => connectToEventSourceWithApiKey(apiKey), 5000);
});
}
processStream();
}).catch(error => {
console.error('Connection error:', error);
// Try to reconnect
setTimeout(() => connectToEventSourceWithApiKey(apiKey), 5000);
});
}
```
#### Advantages of SSE over Polling
Using SSE for monitoring instance state provides several advantages over traditional polling:
1. **Reduced latency**: Changes are delivered in real-time
2. **Reduced server load**: Eliminates unnecessary polling requests
3. **Bandwidth efficiency**: Data is only sent when changes occur
4. **Native browser support**: Built-in browser support without additional libraries
5. **Automatic reconnection**: Browser automatically reconnects when connection is lost
#### Best Practices for SSE Implementation
When implementing SSE in frontend:
1. **Handle reconnection**: While browsers automatically attempt reconnection, implement custom logic to ensure persistent connection
2. **Efficient event handling**: Keep event handlers fast to avoid UI blocking
3. **Implement fallback**: Implement polling fallback for environments that don't support SSE
4. **Handle errors**: Properly handle connection errors and disconnections
5. **Log management**: Maintain log buffers for each instance to prevent unlimited growth
## Frontend Integration Guide
When integrating NodePass with frontend applications, consider the following important aspects:
### Instance Persistence
NodePass Master Mode now supports instance persistence using gob serialization format. Instances and their states are saved to a `nodepass.gob` file in the same directory as the executable and automatically restored when the master restarts.
Key persistence features:
- Instance configurations are automatically saved to disk
- Instance states (running/stopped) are preserved
- Auto-restart policies are maintained across master restarts
- Traffic statistics are maintained between restarts
- Instances with auto-restart enabled automatically start when master restarts
- No need to manually re-register after restart
#### Automatic Backup Feature
NodePass Master Mode provides automatic backup functionality to periodically backup state files to prevent data loss:
- **Backup File**: Automatically creates `nodepass.gob.backup` backup file
- **Backup Interval**: Automatically backs up every 1 hour (configurable via `NP_RELOAD_INTERVAL` environment variable)
- **Backup Strategy**: Uses single backup file, new backups overwrite old backups
- **Backup Content**: Includes all instance configurations, states, auto-restart policies, and statistics
- **Disaster Recovery**: When the main file is corrupted, backup file can be manually used for recovery
- **Auto Start**: Backup functionality starts automatically with master service, no additional configuration required
Backup file location: `nodepass.gob.backup` in the same directory as the main state file `nodepass.gob`
**Note:** While instance configurations are now persistent and automatically backed up, frontend applications should still maintain their own instance configuration records as an additional backup strategy.
### Instance Lifecycle Management
To properly manage lifecycles:
1. **Creation**: Store instance configuration and URL
```javascript
async function createNodePassInstance(config) {
const response = await fetch(`${API_URL}/instances`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey // If API Key is enabled
},
body: JSON.stringify({
url: `server://0.0.0.0:${config.port}/${config.target}?tls=${config.tls}`
})
});
const data = await response.json();
// Configure auto-restart policy based on type
if (data.success) {
const shouldAutoRestart = config.type === 'server' || config.critical === true;
await setAutoStartPolicy(data.data.id, shouldAutoRestart);
}
// Store in frontend persistence storage
saveInstanceConfig({
id: data.data.id,
originalConfig: config,
url: data.data.url
});
return data;
}
```
2. **Status Monitoring**: Monitor instance state changes
NodePass provides two methods for monitoring instance status:
A. **Using SSE (Recommended)**: Receive real-time events through persistent connection
```javascript
function connectToEventSource() {
const eventSource = new EventSource(`${API_URL}/events`, {
// If authentication is needed, use custom implementation
});
// Or use custom implementation with API Key
// connectToEventSourceWithApiKey(apiKey);
eventSource.addEventListener('instance', (event) => {
const data = JSON.parse(event.data);
// Handle different event types: initial, create, update, delete, log
// ...handling logic see "Using SSE for Real-time Event Monitoring" section above
});
// Error handling and reconnection logic
// ...see previous examples
return eventSource;
}
```
B. **Traditional Polling (Alternative)**: Use in environments that don't support SSE
```javascript
function startInstanceMonitoring(instanceId, interval = 5000) {
return setInterval(async () => {
try {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
headers: {
'X-API-Key': apiKey // If API Key is enabled
}
});
const data = await response.json();
if (data.success) {
updateInstanceStatus(instanceId, data.data.status);
updateInstanceMetrics(instanceId, {
connections: data.data.connections,
pool_size: data.data.pool_size,
uptime: data.data.uptime
});
}
} catch (error) {
markInstanceUnreachable(instanceId);
}
}, interval);
}
```
**Recommendation:** Prioritize SSE method as it provides more efficient real-time monitoring and reduces server load. Only use polling when client doesn't support SSE or specific environment compatibility is needed.
3. **Instance Alias Management**: Set readable names for instances
```javascript
// Batch set instance aliases
async function setInstanceAliases(instances) {
for (const instance of instances) {
// Generate meaningful aliases based on instance type and purpose
const alias = `${instance.type}-${instance.region || 'default'}-${instance.port || 'auto'}`;
await updateInstanceAlias(instance.id, alias);
}
}
// Find instance by alias
async function findInstanceByAlias(targetAlias) {
const response = await fetch(`${API_URL}/instances`, {
headers: { 'X-API-Key': apiKey }
});
const data = await response.json();
if (data.success) {
return data.data.find(instance => instance.alias === targetAlias);
}
return null;
}
```
4. **Control Operations**: Start, stop, restart instances
```javascript
async function controlInstance(instanceId, action) {
// action can be: start, stop, restart
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PATCH', // Note: API has been updated to use PATCH method instead of PUT
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey // If API Key is enabled
},
body: JSON.stringify({ action })
});
const data = await response.json();
return data.success;
}
// Update instance alias
async function updateInstanceAlias(instanceId, alias) {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey // If API Key is enabled
},
body: JSON.stringify({ alias })
});
const data = await response.json();
return data.success;
}
// Update instance URL configuration
async function updateInstanceURL(instanceId, newURL) {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey // If API Key is enabled
},
body: JSON.stringify({ url: newURL })
});
const data = await response.json();
return data.success;
}
```
5. **Auto-restart Policy Management**: Configure automatic startup behavior
```javascript
async function setAutoStartPolicy(instanceId, enableAutoStart) {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({ restart: enableAutoStart })
});
const data = await response.json();
return data.success;
}
async function controlInstanceWithAutoStart(instanceId, action, enableAutoStart) {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({
action: action,
restart: enableAutoStart
})
});
const data = await response.json();
return data.success;
}
async function updateInstanceComplete(instanceId, alias, action, enableAutoStart) {
const response = await fetch(`${API_URL}/instances/${instanceId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({
alias: alias,
action: action,
restart: enableAutoStart
})
});
const data = await response.json();
return data.success;
}
```
#### Complete Auto-restart Policy Usage Example
Here's a comprehensive example showing how to implement auto-restart policy management in real scenarios:
```javascript
// Scenario: Establish load-balanced server cluster with auto-restart policies
async function setupServerCluster(serverConfigs) {
const clusterInstances = [];
for (const config of serverConfigs) {
try {
// Create server instance
const instance = await createNodePassInstance({
type: 'server',
port: config.port,
target: config.target,
critical: config.isPrimary, // Primary servers are critical instances
tls: config.enableTLS
});
if (instance.success) {
// Set meaningful instance alias
const alias = `${config.role}-server-${config.port}`;
await updateInstanceAlias(instance.data.id, alias);
// Configure auto-restart policy based on server role
const autoStartPolicy = config.isPrimary || config.role === 'essential';
await setAutoStartPolicy(instance.data.id, autoStartPolicy);
// Start instance
await controlInstance(instance.data.id, 'start');
clusterInstances.push({
id: instance.data.id,
alias: alias,
role: config.role,
autoStartEnabled: autoStartPolicy
});
console.log(`Server ${alias} created, auto-restart policy: ${autoStartPolicy}`);
}
} catch (error) {
console.error(`Failed to create server ${config.role}:`, error);
}
}
return clusterInstances;
}
// Monitor cluster health and dynamically adjust auto-restart policies
async function monitorClusterHealth(clusterInstances) {
const healthyInstances = [];
for (const cluster of clusterInstances) {
const instance = await fetch(`${API_URL}/instances/${cluster.id}`, {
headers: { 'X-API-Key': apiKey }
});
const data = await instance.json();
if (data.success && data.data.status === 'running') {
healthyInstances.push(cluster);
} else {
// If critical instance is down, enable auto-restart for backup instances
if (cluster.role === 'primary') {
await enableBackupInstanceAutoStart(clusterInstances);
}
}
}
return healthyInstances;
}
async function enableBackupInstanceAutoStart(clusterInstances) {
const backupInstances = clusterInstances.filter(c => c.role === 'backup');
for (const backup of backupInstances) {
await setAutoStartPolicy(backup.id, true);
console.log(`Enabled auto-restart policy for backup instance: ${backup.id}`);
}
}
```
### Traffic Statistics
The Master API provides traffic statistics, but there are important considerations:
1. **Basic Traffic Metrics**: NodePass periodically provides cumulative values for TCP and UDP traffic in both inbound and outbound directions. Frontend applications need to store and process these values to obtain meaningful statistics.
```javascript
function processTrafficStats(instanceId, currentStats) {
// Store current timestamp
const timestamp = Date.now();
// If we have previous stats for this instance, calculate differences
if (previousStats[instanceId]) {
const timeDiff = timestamp - previousStats[instanceId].timestamp;
const tcpInDiff = currentStats.tcp_in - previousStats[instanceId].tcp_in;
const tcpOutDiff = currentStats.tcp_out - previousStats[instanceId].tcp_out;
const udpInDiff = currentStats.udp_in - previousStats[instanceId].udp_in;
const udpOutDiff = currentStats.udp_out - previousStats[instanceId].udp_out;
// Store historical data for chart display
storeTrafficHistory(instanceId, {
timestamp,
tcp_in_rate: tcpInDiff / timeDiff * 1000, // bytes per second
tcp_out_rate: tcpOutDiff / timeDiff * 1000,
udp_in_rate: udpInDiff / timeDiff * 1000,
udp_out_rate: udpOutDiff / timeDiff * 1000
});
}
// Update previous stats for next calculation
previousStats[instanceId] = {
timestamp,
tcp_in: currentStats.tcp_in,
tcp_out: currentStats.tcp_out,
udp_in: currentStats.udp_in,
udp_out: currentStats.udp_out
};
}
```
2. **Data Persistence**: Since the API only provides cumulative values, the frontend must implement proper storage and calculation logic
```javascript
// Frontend traffic history storage structure example
const trafficHistory = {};
function storeTrafficHistory(instanceId, metrics) {
if (!trafficHistory[instanceId]) {
trafficHistory[instanceId] = {
timestamps: [],
tcp_in_rates: [],
tcp_out_rates: [],
udp_in_rates: [],
udp_out_rates: []
};
}
trafficHistory[instanceId].timestamps.push(metrics.timestamp);
trafficHistory[instanceId].tcp_in_rates.push(metrics.tcp_in_rate);
trafficHistory[instanceId].tcp_out_rates.push(metrics.tcp_out_rate);
trafficHistory[instanceId].udp_in_rates.push(metrics.udp_in_rate);
trafficHistory[instanceId].udp_out_rates.push(metrics.udp_out_rate);
// Keep history data manageable
const MAX_HISTORY = 1000;
if (trafficHistory[instanceId].timestamps.length > MAX_HISTORY) {
trafficHistory[instanceId].timestamps.shift();
trafficHistory[instanceId].tcp_in_rates.shift();
trafficHistory[instanceId].tcp_out_rates.shift();
trafficHistory[instanceId].udp_in_rates.shift();
trafficHistory[instanceId].udp_out_rates.shift();
}
}
```
### Instance ID Persistence
Since NodePass now uses gob format for persistent storage of instance state, instance IDs **no longer change** after master restart. This means:
1. Frontend applications can safely use instance IDs as unique identifiers
2. Instance configurations, states, and statistics are automatically restored after restart
3. No longer need to implement logic for handling instance ID changes
This greatly simplifies frontend integration, eliminating the previous complexity of handling instance recreation and ID mapping.
### Auto-restart Policy Management
NodePass now supports configuring auto-restart policies for instances, enabling automated instance management and improving reliability. The auto-restart policy feature has the following characteristics:
1. **Automatic Instance Recovery**: Instances with auto-restart enabled automatically start when the master service restarts
2. **Selective Auto-start**: Configure which instances should auto-start based on their importance or role
3. **Persistent Policy Storage**: Auto-restart policies are saved and restored across master restarts
4. **Fine-grained Control**: Each instance can have its own auto-restart policy setting
#### How Auto-restart Policy Works
- **Policy Assignment**: Each instance has a `restart` boolean field that determines its auto-start behavior
- **Master Startup**: When master starts, it automatically starts all instances with `restart: true`
- **Policy Persistence**: Auto-restart policies are saved with other instance data in the `nodepass.gob` file
- **Runtime Management**: Auto-restart policies can be modified while instances are running
#### Auto-restart Policy Best Practices
1. **Enable for Server Instances**: Server instances should typically have auto-restart enabled for high availability
2. **Selective Client Auto-start**: Only enable auto-restart for critical client connections
3. **Testing Scenarios**: Disable auto-restart for temporary or testing instances
4. **Load Balancing**: Use auto-restart policies to maintain minimum instance count for load distribution
```javascript
// Example: Configure auto-restart policies based on instance role
async function configureAutoStartPolicies(instances) {
for (const instance of instances) {
// Enable auto-start for servers and critical clients
const shouldAutoStart = instance.type === 'server' ||
instance.tags?.includes('critical');
await setAutoStartPolicy(instance.id, shouldAutoStart);
}
}
```
## Instance Data Structure
The instance object in API responses contains the following fields:
```json
{
"id": "a1b2c3d4", // Instance unique identifier
"alias": "web-server-01", // Instance alias (optional, for friendly display name)
"type": "server", // Instance type: server or client
"status": "running", // Instance status: running, stopped, or error
"url": "server://...", // Instance configuration URL
"restart": true, // Auto-restart policy
"mode": 0, // Instance mode
"tcprx": 1024, // TCP received bytes
"tcptx": 2048, // TCP transmitted bytes
"udprx": 512, // UDP received bytes
"udptx": 256 // UDP transmitted bytes
}
```
**Note:**
- `alias` field is optional, empty string if not set
- `mode` field indicates the current runtime mode of the instance
- `restart` field controls the auto-restart behavior of the instance
## System Information Endpoint
The `/info` endpoint provides system information about the NodePass master service. This endpoint is useful for monitoring, troubleshooting, and system status validation.
### Request
```
GET /info
```
Requires API Key authentication: Yes
### Response
The response contains the following system information fields:
```json
{
"os": "linux", // Operating system type
"arch": "amd64", // System architecture
"cpu": 45, // CPU usage percentage (Linux only)
"mem_total": 8589934592, // Total memory in bytes (Linux only)
"mem_free": 2684354560, // Free memory in bytes (Linux only)
"swap_total": 3555328000, // Total swap space in bytes (Linux only)
"swap_free": 3555328000, // Free swap space in bytes (Linux only)
"netrx": 1048576000, // Network received bytes (cumulative, Linux only)
"nettx": 2097152000, // Network transmitted bytes (cumulative, Linux only)
"diskr": 4194304000, // Disk read bytes (cumulative, Linux only)
"diskw": 8388608000, // Disk write bytes (cumulative, Linux only)
"sysup": 86400, // System uptime in seconds (Linux only)
"ver": "1.2.0", // NodePass version
"name": "example.com", // Tunnel hostname
"uptime": 11525, // API uptime in seconds
"log": "info", // Log level
"tls": "1", // TLS enabled status
"crt": "/path/to/cert", // Certificate path
"key": "/path/to/key" // Key path
}
```
### Usage Example
```javascript
// Get system information
async function getSystemInfo() {
const response = await fetch(`${API_URL}/info`, {
method: 'GET',
headers: {
'X-API-Key': apiKey
}
});
return await response.json();
}
// Display service uptime and system resource usage
function displaySystemStatus() {
getSystemInfo().then(info => {
console.log(`Service uptime: ${info.uptime} seconds`);
// Format uptime for friendlier display
const hours = Math.floor(info.uptime / 3600);
const minutes = Math.floor((info.uptime % 3600) / 60);
const seconds = info.uptime % 60;
console.log(`Service uptime: ${hours}h ${minutes}m ${seconds}s`);
// Display system resource usage (Linux only)
if (info.os === 'linux') {
if (info.cpu !== -1) {
console.log(`CPU usage: ${info.cpu}%`);
}
if (info.mem_total > 0) {
const memUsagePercent = ((info.mem_total - info.mem_free) / info.mem_total * 100).toFixed(1);
console.log(`Memory usage: ${memUsagePercent}% (${(info.mem_free / 1024 / 1024 / 1024).toFixed(1)}GB free of ${(info.mem_total / 1024 / 1024 / 1024).toFixed(1)}GB total)`);
}
if (info.swap_total > 0) {
const swapUsagePercent = ((info.swap_total - info.swap_free) / info.swap_total * 100).toFixed(1);
console.log(`Swap usage: ${swapUsagePercent}% (${(info.swap_free / 1024 / 1024 / 1024).toFixed(1)}GB free of ${(info.swap_total / 1024 / 1024 / 1024).toFixed(1)}GB total)`);
}
} else {
console.log('CPU, memory, swap space, network I/O, disk I/O, and system uptime monitoring is only available on Linux systems');
}
// Display network I/O statistics (cumulative values)
if (info.os === 'linux') {
console.log(`Network received: ${(info.netrx / 1024 / 1024).toFixed(2)} MB (cumulative)`);
console.log(`Network transmitted: ${(info.nettx / 1024 / 1024).toFixed(2)} MB (cumulative)`);
console.log(`Disk read: ${(info.diskr / 1024 / 1024).toFixed(2)} MB (cumulative)`);
console.log(`Disk write: ${(info.diskw / 1024 / 1024).toFixed(2)} MB (cumulative)`);
console.log(`System uptime: ${Math.floor(info.sysup / 3600)} hours`);
}
});
}
```
### Monitoring Best Practices
- **Regular checks**: Poll this endpoint regularly to ensure service is running properly
- **Version verification**: Check version number after deploying updates
- **Uptime monitoring**: Monitor uptime to detect unexpected restarts
- **Log level verification**: Ensure current log level meets expectations
- **Resource monitoring**: On Linux systems, monitor CPU, memory, swap space, network I/O, disk I/O usage to ensure optimal performance
- CPU usage is calculated by parsing `/proc/stat` (percentage of non-idle time)
- Memory information is obtained by parsing `/proc/meminfo` (total and free memory in bytes)
- Swap space information is obtained by parsing `/proc/meminfo` (total and free swap space in bytes)
- Network I/O is calculated by parsing `/proc/net/dev` (cumulative bytes, excluding virtual interfaces)
- Disk I/O is calculated by parsing `/proc/diskstats` (cumulative bytes, major devices only)
- System uptime is obtained by parsing `/proc/uptime`
- Values of -1 or 0 indicate system information is unavailable (non-Linux systems)
- Network and disk I/O fields provide cumulative values; frontend applications need to store historical data and calculate differences to get real-time rates (bytes/second)
## API Endpoint Documentation
For detailed API documentation including request and response examples, use the built-in Swagger UI documentation available at the `/docs` endpoint. This interactive documentation provides comprehensive information about:
- Available endpoints
- Required parameters
- Response formats
- Request and response examples
- Schema definitions
### Accessing Swagger UI
To access the Swagger UI documentation:
```
http(s)://<api_addr>[<prefix>]/docs
```
For example:
```
http://localhost:9090/api/docs
```
The Swagger UI provides a convenient way to explore and test the API directly in your browser. You can execute API calls against your running NodePass master instance and see actual responses.
## Complete API Reference
### Instance Management Endpoints Detail
#### GET /instances
- **Description**: Get list of all instances
- **Authentication**: Requires API Key
- **Response**: Array of instances
- **Example**:
```javascript
const instances = await fetch(`${API_URL}/instances`, {
headers: { 'X-API-Key': apiKey }
});
```
#### POST /instances
- **Description**: Create new instance
- **Authentication**: Requires API Key
- **Request body**: `{ "url": "client:// or server:// format URL" }`
- **Response**: Newly created instance object
- **Example**:
```javascript
const newInstance = await fetch(`${API_URL}/instances`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({ url: 'server://0.0.0.0:8080/localhost:3000' })
});
```
#### GET /instances/{id}
- **Description**: Get specific instance details
- **Authentication**: Requires API Key
- **Response**: Instance object
- **Example**:
```javascript
const instance = await fetch(`${API_URL}/instances/abc123`, {
headers: { 'X-API-Key': apiKey }
});
```
#### PATCH /instances/{id}
- **Description**: Update instance state, alias, or perform control operations
- **Authentication**: Requires API Key
- **Request body**: `{ "alias": "new alias", "action": "start|stop|restart|reset", "restart": true|false }`
- **Features**: Does not interrupt running instances, only updates specified fields. `action: "reset"` can reset traffic statistics (tcprx, tcptx, udprx, udptx) for the instance to zero.
- **Example**:
```javascript
// Update alias and auto-restart policy
await fetch(`${API_URL}/instances/abc123`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({
alias: 'Web Server',
restart: true
})
});
// Control instance operations
await fetch(`${API_URL}/instances/abc123`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({ action: 'restart' })
});
// Reset traffic statistics
await fetch(`${API_URL}/instances/abc123`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({ action: 'reset' })
});
```
#### PUT /instances/{id}
- **Description**: Completely update instance URL configuration
- **Authentication**: Requires API Key
- **Request body**: `{ "url": "new client:// or server:// format URL" }`
- **Features**: Will restart the instance.
- **Restrictions**: API Key instance (ID `********`) does not support this operation
- **Example**:
```javascript
// Update instance URL
await fetch(`${API_URL}/instances/abc123`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
},
body: JSON.stringify({
url: 'server://0.0.0.0:9090/localhost:8080?tls=1'
})
});
```
#### DELETE /instances/{id}
- **Description**: Delete instance
- **Authentication**: Requires API Key
- **Response**: 204 No Content
- **Restrictions**: API Key instance (ID `********`) cannot be deleted
- **Example**:
```javascript
await fetch(`${API_URL}/instances/abc123`, {
method: 'DELETE',
headers: { 'X-API-Key': apiKey }
});
```
### Other Endpoints
#### GET /events
- **Description**: Establish SSE connection to receive real-time events
- **Authentication**: Requires API Key
- **Response**: Server-Sent Events stream
- **Event types**: `initial`, `create`, `update`, `delete`, `shutdown`, `log`
#### GET /info
- **Description**: Get master service information
- **Authentication**: Requires API Key
- **Response**: Contains system information, version, uptime, CPU and RAM usage, etc.
#### GET /tcping
- **Description**: TCP connection test, checks connectivity and latency to target address
- **Authentication**: Requires API Key
- **Parameters**:
- `target` (required): Target address in format `host:port`
- **Response**:
```json
{
"target": "example.com:80",
"connected": true,
"latency": 45,
"error": null
}
```
- **Example**: `GET /api/tcping?target=fast.com:443`
#### GET /openapi.json
- **Description**: Get OpenAPI 3.1.1 specification
- **Authentication**: No authentication required
- **Response**: JSON format API specification
#### GET /docs
- **Description**: Swagger UI documentation interface
- **Authentication**: No authentication required
- **Response**: HTML format interactive documentation
### Instance URL Format Specification
Instance URLs must follow these formats:
#### Server Mode
```
server://<bind_address>:<bind_port>/<target_host>:<target_port>?<parameters>
```
Examples:
- `server://0.0.0.0:8080/localhost:3000` - Listen on port 8080, forward to local port 3000
- `server://0.0.0.0:9090/localhost:8080?tls=1&mode=1` - TLS-enabled server, force reverse mode
#### Client Mode
```
client://<server_host>:<server_port>/<local_host>:<local_port>?<parameters>
```
Examples:
- `client://example.com:8080/localhost:3000` - Connect to remote server, listen locally on port 3000
- `client://remote.example.com:443/localhost:22?mode=2&min=32` - Through remote server, force dual-end mode
#### Supported Parameters
| Parameter | Description | Values | Default | Scope |
|-----------|-------------|--------|---------|-------|
| `log` | Log level | `none`, `debug`, `info`, `warn`, `error`, `event` | `info` | Both |
| `tls` | TLS encryption level | `0`(none), `1`(self-signed), `2`(certificate) | `0` | Server only |
| `crt` | Certificate path | File path | None | Server only |
| `key` | Private key path | File path | None | Server only |
| `mode` | Runtime mode control | `0`(auto), `1`(force mode 1), `2`(force mode 2) | `0` | Both |
| `min` | Minimum pool capacity | Integer > 0 | `64` | Client dual-end handshake mode only |
| `max` | Maximum pool capacity | Integer > 0 | `1024` | Dual-end handshake mode |
| `read` | Read timeout duration | Time duration (e.g., `10m`, `30s`, `1h`) | `10m` | Both |
| `rate` | Bandwidth rate limit | Integer (Mbps), 0=unlimited | `0` | Both |
| `proxy` | PROXY protocol support | `0`(disabled), `1`(enabled) | `0` | Both |