chore: drop unused tables (scheduled_tasks, api_tokens, rate_limits, sessions) #72
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ android/.gradle/
|
||||
android/build/
|
||||
android/app/build/
|
||||
android/local.properties
|
||||
config/firebase-service-account.json
|
||||
|
||||
@@ -13,7 +13,6 @@ Repo-specific guidance for OpenCode sessions. Verified against code.
|
||||
## Commands
|
||||
- `composer install` — install deps (no dev deps in `composer.json`)
|
||||
- `php bin/generate-key.php` — generate master key at `/etc/servermanager/master.key`
|
||||
- `php bin/monitor.php` — collect server metrics (runs via cron every minute)
|
||||
- `sudo bash install.sh` — full Ubuntu 22.04+/24.04+ install (needs sudo)
|
||||
- `mysql servermanager < database/migrations/001_initial_schema.sql` — db setup
|
||||
- `export ANDROID_HOME=/opt/android-sdk && cd android && ./gradlew assembleDebug` — build APK → `public/sysadmin.apk`
|
||||
@@ -55,6 +54,11 @@ Repo-specific guidance for OpenCode sessions. Verified against code.
|
||||
- `api_token` column on users for Bearer token auth
|
||||
- `server_permissions` table stores required SSH permissions per server (FK to `servers.id` CASCADE)
|
||||
|
||||
## PR creation workflow
|
||||
- If the current branch **exists on remote** (`git ls-remote --heads origin <branch>`), create a new PR from it via API: `POST /api/v1/repos/devlab/server-manager/pulls` with `head=<branch>`, `base=master`.
|
||||
- If the current branch **does not exist on remote**, create a new one from master first: `git checkout -b <name> master`, push it, then create the PR.
|
||||
- The API token for `git.devlab.lat` is embedded in the remote URL (`agent:<token>@git.devlab.lat`). Use `-u "agent:<token>"` for basic auth. The token is accessible via `git remote get-url origin`.
|
||||
|
||||
## Testing / CI
|
||||
- **No tests, no CI, no linter, no formatter, no typechecker** exist in this repo
|
||||
|
||||
|
||||
13
README.md
13
README.md
@@ -116,17 +116,7 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Cron Job for Monitoring
|
||||
|
||||
```bash
|
||||
# Add to crontab (runs every minute)
|
||||
sudo crontab -u www-data -e
|
||||
|
||||
# Add line:
|
||||
* * * * * php /var/www/servermanager/bin/monitor.php >> /var/www/servermanager/logs/cron.log 2>&1
|
||||
```
|
||||
|
||||
### 6. Start Services
|
||||
### 5. Start Services
|
||||
|
||||
```bash
|
||||
sudo systemctl restart php8.3-fpm nginx mysql
|
||||
@@ -171,7 +161,6 @@ All credential accesses are logged:
|
||||
```
|
||||
ServerManager/
|
||||
├── bin/
|
||||
│ ├── monitor.php # CLI: collect metrics
|
||||
│ └── generate-key.php # CLI: generate master key
|
||||
├── config/
|
||||
│ └── config.php # App configuration
|
||||
|
||||
83
bin/agent.sh
83
bin/agent.sh
@@ -1,83 +0,0 @@
|
||||
#!/bin/bash
|
||||
# ServerManager Monitoring Agent
|
||||
# This script runs as a systemd service on monitored servers.
|
||||
set -e
|
||||
|
||||
CONFIG_FILE="/etc/servermanager/agent.conf"
|
||||
|
||||
load_config() {
|
||||
if [ -f "$CONFIG_FILE" ]; then
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
SERVER_URL="${SERVER_URL:-}"
|
||||
AGENT_KEY="${AGENT_KEY:-}"
|
||||
INTERVAL="${INTERVAL:-60}"
|
||||
}
|
||||
|
||||
collect_metrics() {
|
||||
CPU=$(top -bn1 2>/dev/null | grep 'Cpu(s)' | awk '{print $2}' | cut -d'%' -f1)
|
||||
[ -z "$CPU" ] && CPU=0
|
||||
|
||||
RAM=$(free 2>/dev/null | grep Mem | awk '{printf "%.1f", $3/$2 * 100}')
|
||||
[ -z "$RAM" ] && RAM=0
|
||||
|
||||
DISK=$(df / 2>/dev/null | tail -1 | awk '{print $5}' | sed 's/%//')
|
||||
[ -z "$DISK" ] && DISK=0
|
||||
|
||||
LOAD=$(cat /proc/loadavg 2>/dev/null | awk '{print $1}')
|
||||
[ -z "$LOAD" ] && LOAD=0
|
||||
|
||||
UPTIME=$(uptime -p 2>/dev/null | sed 's/^up //')
|
||||
[ -z "$UPTIME" ] && UPTIME=""
|
||||
}
|
||||
|
||||
push_metrics() {
|
||||
local payload
|
||||
payload=$(cat <<EOF
|
||||
{
|
||||
"agent_key": "$AGENT_KEY",
|
||||
"cpu": $CPU,
|
||||
"ram": $RAM,
|
||||
"disk": $DISK,
|
||||
"load": $LOAD,
|
||||
"uptime": "$UPTIME"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
curl -s -X POST "$SERVER_URL/api/metrics/push" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$payload" \
|
||||
--connect-timeout 10 \
|
||||
--max-time 30 \
|
||||
-o /dev/null -w "%{http_code}" 2>/dev/null || echo "000"
|
||||
}
|
||||
|
||||
main() {
|
||||
load_config
|
||||
|
||||
if [ -z "$SERVER_URL" ] || [ -z "$AGENT_KEY" ]; then
|
||||
echo "ERROR: SERVER_URL and AGENT_KEY must be set in $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "ServerManager Agent started"
|
||||
echo "Server: $SERVER_URL"
|
||||
echo "Interval: ${INTERVAL}s"
|
||||
|
||||
sleep 5
|
||||
|
||||
while true; do
|
||||
collect_metrics
|
||||
http_code=$(push_metrics)
|
||||
|
||||
if [ "$http_code" = "200" ]; then
|
||||
echo "[$(date)] Metrics pushed successfully"
|
||||
else
|
||||
echo "[$(date)] Failed to push metrics (HTTP $http_code)"
|
||||
fi
|
||||
|
||||
sleep "$INTERVAL"
|
||||
done
|
||||
}
|
||||
|
||||
main
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Services\MonitoringService;
|
||||
|
||||
try {
|
||||
$app = App::getInstance();
|
||||
$app->boot(dirname(__DIR__));
|
||||
|
||||
$monitoring = new MonitoringService();
|
||||
$results = $monitoring->collectAllMetrics();
|
||||
|
||||
$online = count(array_filter($results, fn($r) => $r && ($r['status'] ?? '') === 'online'));
|
||||
$offline = count($results) - $online;
|
||||
|
||||
echo sprintf("[%s] Metrics collected: %d servers (%d online, %d offline)\n",
|
||||
date('Y-m-d H:i:s'), count($results), $online, $offline);
|
||||
} catch (\Throwable $e) {
|
||||
echo sprintf("[%s] ERROR: %s\n", date('Y-m-d H:i:s'), $e->getMessage());
|
||||
exit(1);
|
||||
}
|
||||
4
database/migrations/011_cleanup_unused_tables.sql
Normal file
4
database/migrations/011_cleanup_unused_tables.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
DROP TABLE IF EXISTS `scheduled_tasks`;
|
||||
DROP TABLE IF EXISTS `api_tokens`;
|
||||
DROP TABLE IF EXISTS `rate_limits`;
|
||||
DROP TABLE IF EXISTS `sessions`;
|
||||
34
install.sh
34
install.sh
@@ -241,11 +241,8 @@ configure_cron() {
|
||||
log_step "Configuring Cron Jobs"
|
||||
|
||||
cat > /etc/cron.d/servermanager << CRONEOF
|
||||
# ServerManager Monitoring Cron
|
||||
# Collect metrics every minute
|
||||
* * * * * www-data /usr/bin/php ${APP_DIR}/bin/monitor.php >> ${APP_DIR}/logs/cron.log 2>&1
|
||||
|
||||
# Cleanup old logs weekly
|
||||
# ServerManager Cron Jobs
|
||||
# Logs cleanup — weekly
|
||||
0 3 * * 0 www-data find ${APP_DIR}/logs/ -name "*.log" -mtime +30 -delete
|
||||
CRONEOF
|
||||
|
||||
@@ -259,32 +256,6 @@ create_binaries() {
|
||||
|
||||
mkdir -p "${APP_DIR}/bin"
|
||||
|
||||
cat > "${APP_DIR}/bin/monitor.php" << 'PHPEOF'
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use ServerManager\Core\App;
|
||||
use ServerManager\Services\MonitoringService;
|
||||
|
||||
try {
|
||||
$app = App::getInstance();
|
||||
$app->boot(dirname(__DIR__));
|
||||
|
||||
$monitoring = new MonitoringService();
|
||||
$results = $monitoring->collectAllMetrics();
|
||||
|
||||
$online = count(array_filter($results, fn($r) => $r && ($r['status'] ?? '') === 'online'));
|
||||
$offline = count($results) - $online;
|
||||
|
||||
echo sprintf("[%s] Metrics collected: %d servers (%d online, %d offline)\n",
|
||||
date('Y-m-d H:i:s'), count($results), $online, $offline);
|
||||
} catch (\Throwable $e) {
|
||||
echo sprintf("[%s] ERROR: %s\n", date('Y-m-d H:i:s'), $e->getMessage());
|
||||
exit(1);
|
||||
}
|
||||
PHPEOF
|
||||
|
||||
cat > "${APP_DIR}/bin/generate-key.php" << 'PHPEOF'
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@@ -307,7 +278,6 @@ echo "Master key generated: {$keyFile}\n";
|
||||
echo "IMPORTANT: Store this key securely!\n";
|
||||
PHPEOF
|
||||
|
||||
chmod +x "${APP_DIR}/bin/monitor.php"
|
||||
chmod +x "${APP_DIR}/bin/generate-key.php"
|
||||
chown -R rafael:rafael "${APP_DIR}/bin"
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Firebase Cloud Messaging setup script
|
||||
# =======================================
|
||||
#
|
||||
# This script creates placeholder files for FCM integration.
|
||||
# You must replace them with real values from your Firebase project.
|
||||
#
|
||||
# Steps to set up Firebase:
|
||||
#
|
||||
# 1. Go to https://console.firebase.google.com/ and create a project
|
||||
# (or use an existing one)
|
||||
#
|
||||
# 2. Add an Android app to your Firebase project with package name:
|
||||
# com.devlab.app
|
||||
#
|
||||
# 3. Download google-services.json and place it at:
|
||||
# android/app/google-services.json
|
||||
#
|
||||
# 4. Go to Project Settings > Cloud Messaging and copy the
|
||||
# Server key (legacy) or Cloud Messaging API key
|
||||
#
|
||||
# 5. Set the server key in .env:
|
||||
# FCM_SERVER_KEY=your_server_key_here
|
||||
#
|
||||
# 6. OR place your Firebase Admin service account key at:
|
||||
# config/firebase-service-account.json
|
||||
# (for the OAuth-based API - more secure)
|
||||
#
|
||||
# The app will work without FCM configured; push notifications
|
||||
# simply won't be sent until Firebase is set up.
|
||||
#
|
||||
# ---
|
||||
|
||||
echo "Firebase setup script"
|
||||
echo "====================="
|
||||
echo ""
|
||||
echo "To enable push notifications:"
|
||||
echo ""
|
||||
echo "1. Create a Firebase project: https://console.firebase.google.com"
|
||||
echo "2. Add Android app with package: com.devlab.app"
|
||||
echo "3. Download google-services.json → android/app/google-services.json"
|
||||
echo "4. Get Server Key from Cloud Messaging settings"
|
||||
echo "5. Add to .env: FCM_SERVER_KEY=your_key_here"
|
||||
echo ""
|
||||
echo "Without these steps, push notifications are disabled."
|
||||
echo "The app will continue to work using polling as fallback."
|
||||
@@ -1,21 +0,0 @@
|
||||
[Unit]
|
||||
Description=ServerManager Monitoring Agent
|
||||
Documentation=https://github.com/servermanager
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/servermanager-agent
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StartLimitIntervalSec=60
|
||||
StartLimitBurst=5
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=yes
|
||||
PrivateDevices=yes
|
||||
PrivateTmp=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -43,7 +43,7 @@ class AgentService
|
||||
$serverUrl = $scheme . $host;
|
||||
}
|
||||
|
||||
$scriptPath = $this->basePath . '/install/agent-install.sh';
|
||||
$scriptPath = $this->basePath . '/bin/agent-install.sh';
|
||||
|
||||
if (!file_exists($scriptPath)) {
|
||||
return ['success' => false, 'error' => 'Agent install script not found'];
|
||||
@@ -114,7 +114,7 @@ class AgentService
|
||||
|
||||
$server = App::getEncryption()->decryptArray($server, ['ssh_password', 'ssh_key']);
|
||||
|
||||
$scriptPath = $this->basePath . '/install/agent-uninstall.sh';
|
||||
$scriptPath = $this->basePath . '/bin/agent-uninstall.sh';
|
||||
|
||||
if (!file_exists($scriptPath)) {
|
||||
return ['success' => false, 'error' => 'Agent uninstall script not found'];
|
||||
|
||||
Reference in New Issue
Block a user