Files
server-manager/database/migrations/001_initial_schema.sql
2026-06-06 17:58:34 -04:00

272 lines
11 KiB
SQL
Executable File

-- ============================================================================
-- ServerManager Database Schema
-- MySQL/MariaDB 10.5+
-- ============================================================================
CREATE DATABASE IF NOT EXISTS `servermanager`
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
USE `servermanager`;
-- ============================================================================
-- Users Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `users` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`email` VARCHAR(255) NOT NULL,
`password_hash` VARCHAR(255) NOT NULL,
`role` ENUM('super_admin', 'admin', 'operator') NOT NULL DEFAULT 'operator',
`api_token` VARCHAR(64) DEFAULT NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`last_login_at` DATETIME DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_email` (`email`),
UNIQUE KEY `uk_api_token` (`api_token`),
KEY `idx_role` (`role`),
KEY `idx_is_active` (`is_active`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Servers Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `servers` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`description` TEXT DEFAULT NULL,
`ip_address` VARCHAR(255) NOT NULL,
`ssh_port` INT UNSIGNED NOT NULL DEFAULT 22,
`ssh_user` VARCHAR(50) NOT NULL,
`ssh_password` TEXT DEFAULT NULL COMMENT 'AES-256-CBC encrypted',
`ssh_key` TEXT DEFAULT NULL COMMENT 'AES-256-CBC encrypted',
`group_name` VARCHAR(50) DEFAULT NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`current_status` ENUM('online', 'offline', 'unknown') NOT NULL DEFAULT 'unknown',
`cpu_usage` DECIMAL(5,2) DEFAULT NULL,
`ram_usage` DECIMAL(5,2) DEFAULT NULL,
`disk_usage` DECIMAL(5,2) DEFAULT NULL,
`load_average` DECIMAL(8,4) DEFAULT NULL,
`uptime` VARCHAR(50) DEFAULT NULL,
`last_check_at` DATETIME DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_ip_address` (`ip_address`),
KEY `idx_group_name` (`group_name`),
KEY `idx_is_active` (`is_active`),
KEY `idx_current_status` (`current_status`),
KEY `idx_last_check_at` (`last_check_at`),
KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Command History Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `command_history` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`server_id` INT UNSIGNED NOT NULL,
`user_id` INT UNSIGNED NOT NULL,
`command` TEXT NOT NULL,
`output` MEDIUMTEXT DEFAULT NULL,
`exit_status` INT NOT NULL DEFAULT 0,
`executed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_server_id` (`server_id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_executed_at` (`executed_at`),
CONSTRAINT `fk_command_history_server` FOREIGN KEY (`server_id`)
REFERENCES `servers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_command_history_user` FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Audit Logs Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `audit_logs` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED DEFAULT NULL,
`username` VARCHAR(50) DEFAULT NULL,
`action` VARCHAR(100) NOT NULL,
`entity_type` VARCHAR(50) DEFAULT NULL,
`entity_id` INT UNSIGNED DEFAULT NULL,
`details` JSON DEFAULT NULL,
`ip_address` VARCHAR(45) DEFAULT NULL,
`user_agent` VARCHAR(500) DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_action` (`action`),
KEY `idx_entity_type` (`entity_type`),
KEY `idx_entity_id` (`entity_id`),
KEY `idx_created_at` (`created_at`),
KEY `idx_action_entity` (`action`, `entity_type`),
CONSTRAINT `fk_audit_logs_user` FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Monitoring History Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `monitoring_history` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`server_id` INT UNSIGNED NOT NULL,
`status` ENUM('online', 'offline') NOT NULL DEFAULT 'offline',
`cpu_usage` DECIMAL(5,2) NOT NULL DEFAULT 0,
`ram_usage` DECIMAL(5,2) NOT NULL DEFAULT 0,
`disk_usage` DECIMAL(5,2) NOT NULL DEFAULT 0,
`load_average` DECIMAL(8,4) NOT NULL DEFAULT 0,
`uptime` VARCHAR(50) DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_server_id` (`server_id`),
KEY `idx_created_at` (`created_at`),
KEY `idx_server_created` (`server_id`, `created_at`),
CONSTRAINT `fk_monitoring_history_server` FOREIGN KEY (`server_id`)
REFERENCES `servers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- API Tokens Table (for rate limiting and token management)
-- ============================================================================
CREATE TABLE IF NOT EXISTS `api_tokens` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`name` VARCHAR(100) NOT NULL,
`token` VARCHAR(64) NOT NULL,
`last_used_at` DATETIME DEFAULT NULL,
`expires_at` DATETIME DEFAULT NULL,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_token` (`token`),
KEY `idx_user_id` (`user_id`),
KEY `idx_expires_at` (`expires_at`),
CONSTRAINT `fk_api_tokens_user` FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Rate Limiting Table
-- ============================================================================
CREATE TABLE IF NOT EXISTS `rate_limits` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`identifier` VARCHAR(255) NOT NULL,
`action` VARCHAR(100) NOT NULL,
`attempts` INT UNSIGNED NOT NULL DEFAULT 1,
`first_attempt_at` DATETIME NOT NULL,
`last_attempt_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_identifier_action` (`identifier`, `action`),
KEY `idx_last_attempt_at` (`last_attempt_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Session Table (for server-side session storage)
-- ============================================================================
CREATE TABLE IF NOT EXISTS `sessions` (
`id` VARCHAR(128) NOT NULL,
`user_id` INT UNSIGNED DEFAULT NULL,
`ip_address` VARCHAR(45) DEFAULT NULL,
`user_agent` TEXT DEFAULT NULL,
`payload` LONGTEXT NOT NULL,
`last_activity` INT UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_last_activity` (`last_activity`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Events table for scheduled tasks and cron jobs tracking
-- ============================================================================
CREATE TABLE IF NOT EXISTS `scheduled_tasks` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`description` VARCHAR(255) DEFAULT NULL,
`command` VARCHAR(500) NOT NULL,
`interval_seconds` INT UNSIGNED NOT NULL DEFAULT 3600,
`last_run_at` DATETIME DEFAULT NULL,
`next_run_at` DATETIME DEFAULT NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_next_run_at` (`next_run_at`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================================
-- Seed Data: Default Super Admin User
-- Password: Admin@123 (change immediately after first login)
-- Argon2id hash for 'Admin@123'
-- ============================================================================
INSERT INTO `users` (`username`, `email`, `password_hash`, `role`, `is_active`, `api_token`, `created_at`)
VALUES (
'admin',
'admin@localhost',
'$argon2id$v=19$m=65536,t=4,p=3$Y0hBM2QxZ1R4V1pLY2xPTw$iT3DnBqG8pGkOZ7j6QFUwL5XhR0sMvW3a2eX4bN1c8Y',
'super_admin',
1,
'sample_token_replace_in_production_please_change_me_1234567890ab',
NOW()
);
-- ============================================================================
-- Seed Data: Sample Scheduled Task (Monitoring)
-- ============================================================================
INSERT INTO `scheduled_tasks` (`name`, `description`, `command`, `interval_seconds`, `next_run_at`, `is_active`)
VALUES (
'collect_metrics',
'Collect monitoring metrics from all active servers',
'php bin/monitor.php',
30,
NOW(),
1
);
-- ============================================================================
-- Cleanup: Create event to auto-clean old monitoring data
-- ============================================================================
DELIMITER //
CREATE EVENT IF NOT EXISTS `cleanup_monitoring_history`
ON SCHEDULE EVERY 1 DAY
STARTS CURRENT_TIMESTAMP
DO
BEGIN
DELETE FROM `monitoring_history`
WHERE `created_at` < DATE_SUB(NOW(), INTERVAL 30 DAY);
DELETE FROM `rate_limits`
WHERE `last_attempt_at` < DATE_SUB(NOW(), INTERVAL 24 HOUR);
DELETE FROM `sessions`
WHERE `last_activity` < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 24 HOUR));
END//
DELIMITER ;
-- ============================================================================
-- Verify setup
-- ============================================================================
SELECT 'ServerManager database created successfully!' AS status;
SELECT 'Default admin user: admin / Admin@123 (CHANGE IMMEDIATELY)' AS note;
SELECT 'IMPORTANT: Generate master encryption key before use!' AS warning;