mbai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/mbai.js +335 -0
- package/package.json +31 -0
package/bin/mbai.js
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync, spawn } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const https = require('https');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const crypto = require('crypto');
|
|
9
|
+
|
|
10
|
+
const BINARY_BASE_URL = 'https://managedbyai.dev/bin';
|
|
11
|
+
const RELAY_URL = 'wss://atlas-ws.managedbyai.dev';
|
|
12
|
+
const CONFIG_DIR = '/etc/atlas';
|
|
13
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.yaml');
|
|
14
|
+
const BINARY_PATH = '/usr/local/bin/atlas-agent';
|
|
15
|
+
const SERVICE_NAME = 'atlas-agent';
|
|
16
|
+
const TRIAL_DAYS = 30;
|
|
17
|
+
|
|
18
|
+
function checkRoot() {
|
|
19
|
+
if (process.getuid() !== 0) {
|
|
20
|
+
console.error('Error: This command requires root privileges.');
|
|
21
|
+
console.error('Run with: sudo mbai <command>');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getFingerprint() {
|
|
27
|
+
const parts = [];
|
|
28
|
+
|
|
29
|
+
// Machine ID
|
|
30
|
+
try {
|
|
31
|
+
const machineId = fs.readFileSync('/etc/machine-id', 'utf8').trim();
|
|
32
|
+
parts.push(machineId);
|
|
33
|
+
} catch (e) {}
|
|
34
|
+
|
|
35
|
+
// Hostname
|
|
36
|
+
parts.push(os.hostname());
|
|
37
|
+
|
|
38
|
+
// Combine and hash
|
|
39
|
+
const combined = parts.join('-');
|
|
40
|
+
const hash = crypto.createHash('sha256').update(combined).digest('hex').slice(0, 16);
|
|
41
|
+
return `atlas-${hash}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function getBinaryName() {
|
|
45
|
+
const platform = os.platform();
|
|
46
|
+
let arch = os.arch();
|
|
47
|
+
|
|
48
|
+
// Map architecture
|
|
49
|
+
if (arch === 'x64') arch = 'amd64';
|
|
50
|
+
if (arch === 'arm64' || arch === 'aarch64') arch = 'arm64';
|
|
51
|
+
|
|
52
|
+
if (platform === 'darwin') {
|
|
53
|
+
return `atlas-agent-darwin-${arch}`;
|
|
54
|
+
} else if (platform === 'linux') {
|
|
55
|
+
return `atlas-agent-linux-${arch}`;
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error(`Unsupported platform: ${platform}/${arch}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function downloadFile(url, dest) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
const file = fs.createWriteStream(dest);
|
|
64
|
+
https.get(url, (response) => {
|
|
65
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
66
|
+
// Follow redirect
|
|
67
|
+
https.get(response.headers.location, (res) => {
|
|
68
|
+
res.pipe(file);
|
|
69
|
+
file.on('finish', () => {
|
|
70
|
+
file.close();
|
|
71
|
+
resolve();
|
|
72
|
+
});
|
|
73
|
+
}).on('error', reject);
|
|
74
|
+
} else {
|
|
75
|
+
response.pipe(file);
|
|
76
|
+
file.on('finish', () => {
|
|
77
|
+
file.close();
|
|
78
|
+
resolve();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}).on('error', reject);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function cmdSetup() {
|
|
86
|
+
checkRoot();
|
|
87
|
+
|
|
88
|
+
console.log('='.repeat(50));
|
|
89
|
+
console.log(' ATLAS - AI-Powered Server Monitoring');
|
|
90
|
+
console.log(' 30-day free trial. No credit card required.');
|
|
91
|
+
console.log('='.repeat(50));
|
|
92
|
+
console.log();
|
|
93
|
+
|
|
94
|
+
const fingerprint = getFingerprint();
|
|
95
|
+
console.log(`Server ID: ${fingerprint}`);
|
|
96
|
+
|
|
97
|
+
// Stop existing service if running
|
|
98
|
+
try {
|
|
99
|
+
const result = execSync('systemctl is-active atlas-agent 2>/dev/null', { encoding: 'utf8' }).trim();
|
|
100
|
+
if (result === 'active') {
|
|
101
|
+
console.log('\nStopping existing Atlas service...');
|
|
102
|
+
execSync('systemctl stop atlas-agent', { stdio: 'inherit' });
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {}
|
|
105
|
+
|
|
106
|
+
// Create directories
|
|
107
|
+
console.log('\nCreating directories...');
|
|
108
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
109
|
+
fs.mkdirSync('/var/atlas/snapshots', { recursive: true });
|
|
110
|
+
fs.mkdirSync('/usr/local/bin', { recursive: true });
|
|
111
|
+
|
|
112
|
+
// Download binary
|
|
113
|
+
const binaryName = getBinaryName();
|
|
114
|
+
const binaryUrl = `${BINARY_BASE_URL}/${binaryName}`;
|
|
115
|
+
console.log(`Downloading Atlas agent (${binaryName})...`);
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
await downloadFile(binaryUrl, BINARY_PATH);
|
|
119
|
+
fs.chmodSync(BINARY_PATH, 0o755);
|
|
120
|
+
console.log(` Installed: ${BINARY_PATH}`);
|
|
121
|
+
} catch (e) {
|
|
122
|
+
console.error(`Error downloading binary: ${e.message}`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Download auto-discover script
|
|
127
|
+
const discoverUrl = `${BINARY_BASE_URL}/auto-discover.sh`;
|
|
128
|
+
const discoverPath = '/usr/local/bin/atlas-discover';
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
await downloadFile(discoverUrl, discoverPath);
|
|
132
|
+
fs.chmodSync(discoverPath, 0o755);
|
|
133
|
+
console.log(` Installed: ${discoverPath}`);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
console.log(' Warning: Could not download auto-discover script');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Generate config
|
|
139
|
+
console.log('\nGenerating configuration...');
|
|
140
|
+
|
|
141
|
+
// Run auto-discovery if available
|
|
142
|
+
if (fs.existsSync(discoverPath)) {
|
|
143
|
+
console.log('Running service discovery...');
|
|
144
|
+
try {
|
|
145
|
+
execSync(`${discoverPath} ${CONFIG_FILE} "" "${RELAY_URL}"`, { stdio: 'inherit' });
|
|
146
|
+
} catch (e) {}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Create basic config if discovery didn't create one
|
|
150
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
151
|
+
const config = `# Atlas Agent Configuration
|
|
152
|
+
server_id: "${fingerprint}"
|
|
153
|
+
relay_url: "${RELAY_URL}"
|
|
154
|
+
trial_start: ${Math.floor(Date.now() / 1000)}
|
|
155
|
+
trial_days: ${TRIAL_DAYS}
|
|
156
|
+
hostname: "${os.hostname()}"
|
|
157
|
+
|
|
158
|
+
metrics:
|
|
159
|
+
enabled: true
|
|
160
|
+
interval_seconds: 30
|
|
161
|
+
|
|
162
|
+
log_watcher:
|
|
163
|
+
enabled: true
|
|
164
|
+
paths:
|
|
165
|
+
- /var/log/syslog
|
|
166
|
+
- /var/log/messages
|
|
167
|
+
|
|
168
|
+
playbooks:
|
|
169
|
+
enabled: true
|
|
170
|
+
`;
|
|
171
|
+
fs.writeFileSync(CONFIG_FILE, config);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
console.log(` Config: ${CONFIG_FILE}`);
|
|
175
|
+
|
|
176
|
+
// Create systemd service
|
|
177
|
+
console.log('\nCreating systemd service...');
|
|
178
|
+
const serviceContent = `[Unit]
|
|
179
|
+
Description=Atlas Agent - AI-Powered Server Monitoring
|
|
180
|
+
Documentation=https://managedbyai.dev
|
|
181
|
+
After=network-online.target
|
|
182
|
+
Wants=network-online.target
|
|
183
|
+
|
|
184
|
+
[Service]
|
|
185
|
+
Type=simple
|
|
186
|
+
User=root
|
|
187
|
+
Group=root
|
|
188
|
+
ExecStart=${BINARY_PATH} daemon -c ${CONFIG_FILE}
|
|
189
|
+
Restart=always
|
|
190
|
+
RestartSec=10
|
|
191
|
+
Environment=ATLAS_SNAPSHOT_DIR=/var/atlas/snapshots
|
|
192
|
+
StandardOutput=journal
|
|
193
|
+
StandardError=journal
|
|
194
|
+
SyslogIdentifier=atlas-agent
|
|
195
|
+
LimitNOFILE=65536
|
|
196
|
+
LimitNPROC=4096
|
|
197
|
+
|
|
198
|
+
[Install]
|
|
199
|
+
WantedBy=multi-user.target
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
fs.writeFileSync(`/etc/systemd/system/${SERVICE_NAME}.service`, serviceContent);
|
|
203
|
+
execSync('systemctl daemon-reload');
|
|
204
|
+
execSync(`systemctl enable ${SERVICE_NAME}`);
|
|
205
|
+
|
|
206
|
+
console.log();
|
|
207
|
+
console.log('='.repeat(50));
|
|
208
|
+
console.log(' SETUP COMPLETE');
|
|
209
|
+
console.log('='.repeat(50));
|
|
210
|
+
console.log();
|
|
211
|
+
console.log(`Server ID: ${fingerprint}`);
|
|
212
|
+
console.log();
|
|
213
|
+
console.log('Next steps:');
|
|
214
|
+
console.log(' 1. Start monitoring: sudo mbai start');
|
|
215
|
+
console.log(' 2. Check status: sudo mbai status');
|
|
216
|
+
console.log(' 3. View logs: sudo mbai logs');
|
|
217
|
+
console.log();
|
|
218
|
+
console.log(`Trial: ${TRIAL_DAYS} days free. Claim at https://managedbyai.dev/dashboard`);
|
|
219
|
+
console.log();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function cmdStart() {
|
|
223
|
+
checkRoot();
|
|
224
|
+
|
|
225
|
+
if (!fs.existsSync(BINARY_PATH)) {
|
|
226
|
+
console.error("Error: Atlas not installed. Run 'sudo mbai setup' first.");
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
console.log('Starting Atlas agent...');
|
|
231
|
+
execSync(`systemctl start ${SERVICE_NAME}`, { stdio: 'inherit' });
|
|
232
|
+
|
|
233
|
+
// Wait a moment then show status
|
|
234
|
+
setTimeout(() => {
|
|
235
|
+
execSync(`systemctl status ${SERVICE_NAME} --no-pager`, { stdio: 'inherit' });
|
|
236
|
+
}, 2000);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function cmdStop() {
|
|
240
|
+
checkRoot();
|
|
241
|
+
console.log('Stopping Atlas agent...');
|
|
242
|
+
execSync(`systemctl stop ${SERVICE_NAME}`, { stdio: 'inherit' });
|
|
243
|
+
console.log('Stopped.');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function cmdStatus() {
|
|
247
|
+
try {
|
|
248
|
+
execSync(`systemctl status ${SERVICE_NAME} --no-pager`, { stdio: 'inherit' });
|
|
249
|
+
} catch (e) {}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function cmdLogs() {
|
|
253
|
+
const lines = process.argv[3] || '50';
|
|
254
|
+
execSync(`journalctl -u ${SERVICE_NAME} -n ${lines} --no-pager`, { stdio: 'inherit' });
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function cmdUninstall() {
|
|
258
|
+
checkRoot();
|
|
259
|
+
|
|
260
|
+
console.log('Stopping Atlas agent...');
|
|
261
|
+
try {
|
|
262
|
+
execSync(`systemctl stop ${SERVICE_NAME}`, { stdio: 'pipe' });
|
|
263
|
+
execSync(`systemctl disable ${SERVICE_NAME}`, { stdio: 'pipe' });
|
|
264
|
+
} catch (e) {}
|
|
265
|
+
|
|
266
|
+
console.log('Removing files...');
|
|
267
|
+
const filesToRemove = [
|
|
268
|
+
BINARY_PATH,
|
|
269
|
+
'/usr/local/bin/atlas-discover',
|
|
270
|
+
`/etc/systemd/system/${SERVICE_NAME}.service`
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
for (const f of filesToRemove) {
|
|
274
|
+
if (fs.existsSync(f)) {
|
|
275
|
+
fs.unlinkSync(f);
|
|
276
|
+
console.log(` Removed: ${f}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
console.log();
|
|
281
|
+
console.log('Uninstalled. Config preserved at /etc/atlas/');
|
|
282
|
+
console.log('To fully remove: sudo rm -rf /etc/atlas /var/atlas');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function showHelp() {
|
|
286
|
+
console.log(`
|
|
287
|
+
Atlas Agent - AI-powered server monitoring
|
|
288
|
+
|
|
289
|
+
Usage: mbai <command>
|
|
290
|
+
|
|
291
|
+
Commands:
|
|
292
|
+
setup Download binary, generate config (run first)
|
|
293
|
+
start Start the monitoring daemon
|
|
294
|
+
stop Stop the daemon
|
|
295
|
+
status Check daemon status
|
|
296
|
+
logs View recent logs
|
|
297
|
+
uninstall Remove Atlas agent
|
|
298
|
+
|
|
299
|
+
30-day free trial. No API key required.
|
|
300
|
+
https://managedbyai.dev
|
|
301
|
+
`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Main
|
|
305
|
+
const command = process.argv[2];
|
|
306
|
+
|
|
307
|
+
switch (command) {
|
|
308
|
+
case 'setup':
|
|
309
|
+
cmdSetup();
|
|
310
|
+
break;
|
|
311
|
+
case 'start':
|
|
312
|
+
cmdStart();
|
|
313
|
+
break;
|
|
314
|
+
case 'stop':
|
|
315
|
+
cmdStop();
|
|
316
|
+
break;
|
|
317
|
+
case 'status':
|
|
318
|
+
cmdStatus();
|
|
319
|
+
break;
|
|
320
|
+
case 'logs':
|
|
321
|
+
cmdLogs();
|
|
322
|
+
break;
|
|
323
|
+
case 'uninstall':
|
|
324
|
+
cmdUninstall();
|
|
325
|
+
break;
|
|
326
|
+
case '--help':
|
|
327
|
+
case '-h':
|
|
328
|
+
case undefined:
|
|
329
|
+
showHelp();
|
|
330
|
+
break;
|
|
331
|
+
default:
|
|
332
|
+
console.error(`Unknown command: ${command}`);
|
|
333
|
+
showHelp();
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mbai",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "AI-powered server monitoring that automatically fixes issues",
|
|
5
|
+
"bin": {
|
|
6
|
+
"mbai": "./bin/mbai.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"server",
|
|
10
|
+
"monitoring",
|
|
11
|
+
"devops",
|
|
12
|
+
"automation",
|
|
13
|
+
"ai",
|
|
14
|
+
"self-healing",
|
|
15
|
+
"atlas"
|
|
16
|
+
],
|
|
17
|
+
"author": "ManagedByAI <support@managedbyai.dev>",
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"homepage": "https://managedbyai.dev",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/managedbyai/atlas-agent"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=14.0.0"
|
|
26
|
+
},
|
|
27
|
+
"os": [
|
|
28
|
+
"linux",
|
|
29
|
+
"darwin"
|
|
30
|
+
]
|
|
31
|
+
}
|