Files
nixpanel-server/server/src/routes/nixserver/webserver.ts
T
NixReaper 92d08d7b79 feat: rename WHM→NixServer, cPanel→NixClient, bump v0.2.0
- Rename frontend workspaces: whm/ → nixserver/, cpanel/ → nixclient/
- Rename server route dirs: routes/whm/ → routes/nixserver/, routes/cpanel/ → routes/nixclient/
- Update all API prefixes: /api/whm → /api/nixserver, /api/cpanel → /api/nixclient
- Rename env vars: WHM_PORT → NIXSERVER_PORT, CPANEL_PORT → NIXCLIENT_PORT
- Update config properties: whmPort → nixserverPort, cpanelPort → nixclientPort
- Update all UI labels, login pages, sidebar branding, and error messages
- Update installer and update scripts to match new names
- Add cpanel email route (missing from initial scaffold)
- Add .gitattributes to enforce LF line endings
- Bump version to 0.2.0 across all package.json files
2026-04-05 10:54:15 -05:00

75 lines
3.1 KiB
TypeScript

import type { FastifyInstance } from 'fastify'
import { z } from 'zod'
import { requireAdmin } from '../../middleware/auth.js'
import { exec } from '../../core/exec.js'
import { readFile } from 'fs/promises'
export default async function webserverRoutes(fastify: FastifyInstance) {
// GET /api/nixserver/webserver/status
fastify.get('/status', { preHandler: [requireAdmin] }, async (request, reply) => {
const [nginx, apache] = await Promise.all([
exec('systemctl', ['is-active', 'nginx']),
exec('systemctl', ['is-active', 'apache2']),
])
return reply.send({
success: true,
data: {
nginx: { active: nginx.stdout.trim() === 'active' },
apache: { active: apache.stdout.trim() === 'active' },
},
})
})
// GET /api/nixserver/webserver/vhosts
fastify.get('/vhosts', { preHandler: [requireAdmin] }, async (request, reply) => {
const result = await exec('find', ['/etc/nginx/sites-enabled', '-name', '*.conf', '-type', 'f'])
const files = result.stdout.split('\n').filter(Boolean)
const vhosts = files.map(f => ({
path: f,
domain: f.split('/').pop()?.replace('.conf', '') ?? '',
}))
return reply.send({ success: true, data: vhosts })
})
// GET /api/nixserver/webserver/vhosts/:domain
fastify.get('/vhosts/:domain', { preHandler: [requireAdmin] }, async (request, reply) => {
const { domain } = request.params as { domain: string }
if (domain.includes('/') || domain.includes('..')) {
return reply.code(400).send({ success: false, error: 'Invalid domain' })
}
try {
const content = await readFile(`/etc/nginx/sites-available/${domain}.conf`, 'utf8')
return reply.send({ success: true, data: { domain, config: content } })
} catch {
return reply.code(404).send({ success: false, error: 'Vhost not found' })
}
})
// POST /api/nixserver/webserver/nginx/test
fastify.post('/nginx/test', { preHandler: [requireAdmin] }, async (request, reply) => {
const result = await exec('nginx', ['-t'])
return reply.send({
success: result.exitCode === 0,
data: { output: result.stdout + result.stderr },
})
})
// POST /api/nixserver/webserver/nginx/reload
fastify.post('/nginx/reload', { preHandler: [requireAdmin] }, async (request, reply) => {
const test = await exec('nginx', ['-t'])
if (test.exitCode !== 0) {
return reply.code(500).send({ success: false, error: `Config test failed: ${test.stderr}` })
}
const result = await exec('systemctl', ['reload', 'nginx'])
return reply.send({ success: result.exitCode === 0, data: { output: result.stdout } })
})
// GET /api/nixserver/webserver/logs/:type — access or error log (last 200 lines)
fastify.get('/logs/:type', { preHandler: [requireAdmin] }, async (request, reply) => {
const { type } = request.params as { type: string }
const logFile = type === 'error' ? '/var/log/nginx/error.log' : '/var/log/nginx/access.log'
const result = await exec('tail', ['-n', '200', logFile])
return reply.send({ success: true, data: { lines: result.stdout.split('\n').filter(Boolean) } })
})
}