main Initial commit
This commit is contained in:
commit
ac7df91600
65 changed files with 8957 additions and 0 deletions
331
manage.ts
Normal file
331
manage.ts
Normal file
|
|
@ -0,0 +1,331 @@
|
|||
#!/usr/bin/env bun
|
||||
|
||||
/**
|
||||
* Management CLI for NGINX Proxy Manager
|
||||
* Usage: bun manage.ts <command> [options]
|
||||
*/
|
||||
|
||||
import { program } from 'commander';
|
||||
import { database } from './src/database/index.js';
|
||||
import { UserModel } from './src/models/User.js';
|
||||
import { ProxyModel } from './src/models/Proxy.js';
|
||||
import { CertificateModel } from './src/models/Certificate.js';
|
||||
import { SSLService } from './src/services/SSLService.js';
|
||||
import { NginxService } from './src/services/NginxService.js';
|
||||
import bcrypt from 'bcryptjs';
|
||||
import logger from './src/utils/logger.js';
|
||||
|
||||
program
|
||||
.name('nginx-proxy-manager')
|
||||
.description('NGINX Proxy Manager CLI')
|
||||
.version('1.0.0');
|
||||
|
||||
// User management commands
|
||||
const userCmd = program.command('user').description('User management commands');
|
||||
|
||||
userCmd
|
||||
.command('create')
|
||||
.description('Create a new admin user')
|
||||
.requiredOption('-u, --username <username>', 'Username')
|
||||
.requiredOption('-p, --password <password>', 'Password')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const hashedPassword = await bcrypt.hash(options.password, 10);
|
||||
const user = await UserModel.create({
|
||||
username: options.username,
|
||||
password: hashedPassword
|
||||
});
|
||||
console.log(`✅ User created: ${user.username} (ID: ${user.id})`);
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to create user: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
userCmd
|
||||
.command('change-password')
|
||||
.description('Change user password')
|
||||
.requiredOption('-u, --username <username>', 'Username')
|
||||
.requiredOption('-p, --password <password>', 'New password')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const user = await UserModel.findByUsername(options.username);
|
||||
if (!user) {
|
||||
console.error(`❌ User not found: ${options.username}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const hashedPassword = await bcrypt.hash(options.password, 10);
|
||||
await UserModel.updatePassword(user.id!, hashedPassword);
|
||||
console.log(`✅ Password updated for user: ${options.username}`);
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to update password: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// Proxy management commands
|
||||
const proxyCmd = program.command('proxy').description('Proxy management commands');
|
||||
|
||||
proxyCmd
|
||||
.command('list')
|
||||
.description('List all proxies')
|
||||
.action(async () => {
|
||||
try {
|
||||
const proxies = await ProxyModel.findAll();
|
||||
console.log(`\n📋 Found ${proxies.length} proxy(ies):\n`);
|
||||
|
||||
proxies.forEach(proxy => {
|
||||
console.log(`🔗 ${proxy.domain} → ${proxy.target}`);
|
||||
console.log(` SSL: ${proxy.ssl_type}`);
|
||||
console.log(` ID: ${proxy.id}`);
|
||||
console.log(` Created: ${proxy.created_at}\n`);
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to list proxies: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
proxyCmd
|
||||
.command('delete')
|
||||
.description('Delete a proxy by ID')
|
||||
.requiredOption('-i, --id <id>', 'Proxy ID')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const id = parseInt(options.id);
|
||||
const proxy = await ProxyModel.findById(id);
|
||||
|
||||
if (!proxy) {
|
||||
console.error(`❌ Proxy not found with ID: ${id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove NGINX config
|
||||
await NginxService.removeConfig(proxy.domain);
|
||||
|
||||
// Delete from database
|
||||
await ProxyModel.delete(id);
|
||||
|
||||
// Reload NGINX
|
||||
const result = await NginxService.reload();
|
||||
if (result.success) {
|
||||
console.log(`✅ Proxy deleted: ${proxy.domain}`);
|
||||
} else {
|
||||
console.log(`⚠️ Proxy deleted but NGINX reload failed: ${result.output}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to delete proxy: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// Certificate management commands
|
||||
const certCmd = program.command('cert').description('Certificate management commands');
|
||||
|
||||
certCmd
|
||||
.command('list')
|
||||
.description('List all certificates')
|
||||
.action(async () => {
|
||||
try {
|
||||
const certificates = await CertificateModel.findAll();
|
||||
console.log(`\n🔐 Found ${certificates.length} certificate(s):\n`);
|
||||
|
||||
certificates.forEach(cert => {
|
||||
console.log(`📜 ${cert.domain}`);
|
||||
console.log(` Type: ${cert.type}`);
|
||||
console.log(` Status: ${cert.status}`);
|
||||
console.log(` Expiry: ${cert.expiry || 'N/A'}`);
|
||||
console.log(` ID: ${cert.id}\n`);
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to list certificates: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
certCmd
|
||||
.command('renew')
|
||||
.description('Renew certificates expiring soon')
|
||||
.option('-d, --days <days>', 'Days before expiry to renew', '30')
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const days = parseInt(options.days);
|
||||
console.log(`🔍 Checking for certificates expiring within ${days} days...`);
|
||||
|
||||
await SSLService.autoRenewCertificates();
|
||||
console.log('✅ Certificate renewal process completed');
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Certificate renewal failed: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// NGINX management commands
|
||||
const nginxCmd = program.command('nginx').description('NGINX management commands');
|
||||
|
||||
nginxCmd
|
||||
.command('test')
|
||||
.description('Test NGINX configuration')
|
||||
.action(async () => {
|
||||
try {
|
||||
const result = await NginxService.testConfig();
|
||||
if (result.success) {
|
||||
console.log('✅ NGINX configuration is valid');
|
||||
} else {
|
||||
console.log('❌ NGINX configuration test failed:');
|
||||
console.log(result.output);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to test NGINX: ${error.message}`);
|
||||
} finally {
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
nginxCmd
|
||||
.command('reload')
|
||||
.description('Reload NGINX configuration')
|
||||
.action(async () => {
|
||||
try {
|
||||
const result = await NginxService.reload();
|
||||
if (result.success) {
|
||||
console.log('✅ NGINX reloaded successfully');
|
||||
} else {
|
||||
console.log('❌ NGINX reload failed:');
|
||||
console.log(result.output);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to reload NGINX: ${error.message}`);
|
||||
} finally {
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
nginxCmd
|
||||
.command('status')
|
||||
.description('Get NGINX status')
|
||||
.action(async () => {
|
||||
try {
|
||||
const result = await NginxService.getStatus();
|
||||
if (result.success) {
|
||||
console.log('✅ NGINX Status:');
|
||||
console.log(result.output);
|
||||
} else {
|
||||
console.log('❌ Failed to get NGINX status:');
|
||||
console.log(result.output);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to get NGINX status: ${error.message}`);
|
||||
} finally {
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// Database management commands
|
||||
const dbCmd = program.command('db').description('Database management commands');
|
||||
|
||||
dbCmd
|
||||
.command('init')
|
||||
.description('Initialize database')
|
||||
.action(async () => {
|
||||
try {
|
||||
console.log('🗄️ Initializing database...');
|
||||
// Database initialization happens automatically when imported
|
||||
console.log('✅ Database initialized successfully');
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Database initialization failed: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
dbCmd
|
||||
.command('backup')
|
||||
.description('Create database backup')
|
||||
.option('-o, --output <path>', 'Output file path', `./backups/backup-${new Date().toISOString().split('T')[0]}.db`)
|
||||
.action(async (options) => {
|
||||
try {
|
||||
const fs = await import('fs');
|
||||
const path = await import('path');
|
||||
|
||||
// Ensure backup directory exists
|
||||
const backupDir = path.dirname(options.output);
|
||||
if (!fs.existsSync(backupDir)) {
|
||||
fs.mkdirSync(backupDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy database file
|
||||
fs.copyFileSync('./data/proxy_manager.db', options.output);
|
||||
console.log(`✅ Database backed up to: ${options.output}`);
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Backup failed: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// Status command
|
||||
program
|
||||
.command('status')
|
||||
.description('Show application status')
|
||||
.action(async () => {
|
||||
try {
|
||||
console.log('📊 NGINX Proxy Manager Status\n');
|
||||
|
||||
// Check database
|
||||
console.log('🗄️ Database:');
|
||||
const proxies = await ProxyModel.findAll();
|
||||
const certificates = await CertificateModel.findAll();
|
||||
console.log(` Proxies: ${proxies.length}`);
|
||||
console.log(` Certificates: ${certificates.length}`);
|
||||
|
||||
// Check NGINX
|
||||
console.log('\n🔧 NGINX:');
|
||||
const nginxStatus = await NginxService.getStatus();
|
||||
if (nginxStatus.success) {
|
||||
console.log(' Status: ✅ Running');
|
||||
console.log(` Version: ${nginxStatus.output.trim()}`);
|
||||
} else {
|
||||
console.log(' Status: ❌ Not running or error');
|
||||
}
|
||||
|
||||
// Check config
|
||||
const configTest = await NginxService.testConfig();
|
||||
console.log(` Config: ${configTest.success ? '✅ Valid' : '❌ Invalid'}`);
|
||||
|
||||
// Check expiring certificates
|
||||
console.log('\n🔐 Certificates:');
|
||||
const expiring = await SSLService.checkExpiringCertificates(30);
|
||||
console.log(` Expiring soon (30 days): ${expiring.length}`);
|
||||
|
||||
} catch (error: any) {
|
||||
console.error(`❌ Failed to get status: ${error.message}`);
|
||||
} finally {
|
||||
await database.close();
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
// Parse arguments
|
||||
program.parse();
|
||||
|
||||
// If no command provided, show help
|
||||
if (!process.argv.slice(2).length) {
|
||||
program.outputHelp();
|
||||
process.exit();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue