Merge pull request 'chore: drop unused tables (scheduled_tasks, api_tokens, rate_limits, sessions)' (#72) from feat/fcm-apk-v1.8.2 into master
Reviewed-on: #72
This commit was merged in pull request #72.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@ android/.gradle/
|
|||||||
android/build/
|
android/build/
|
||||||
android/app/build/
|
android/app/build/
|
||||||
android/local.properties
|
android/local.properties
|
||||||
|
config/firebase-service-account.json
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ Repo-specific guidance for OpenCode sessions. Verified against code.
|
|||||||
## Commands
|
## Commands
|
||||||
- `composer install` — install deps (no dev deps in `composer.json`)
|
- `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/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)
|
- `sudo bash install.sh` — full Ubuntu 22.04+/24.04+ install (needs sudo)
|
||||||
- `mysql servermanager < database/migrations/001_initial_schema.sql` — db setup
|
- `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`
|
- `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
|
- `api_token` column on users for Bearer token auth
|
||||||
- `server_permissions` table stores required SSH permissions per server (FK to `servers.id` CASCADE)
|
- `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
|
## Testing / CI
|
||||||
- **No tests, no CI, no linter, no formatter, no typechecker** exist in this repo
|
- **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
|
### 5. Start Services
|
||||||
|
|
||||||
```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
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo systemctl restart php8.3-fpm nginx mysql
|
sudo systemctl restart php8.3-fpm nginx mysql
|
||||||
@@ -171,7 +161,6 @@ All credential accesses are logged:
|
|||||||
```
|
```
|
||||||
ServerManager/
|
ServerManager/
|
||||||
├── bin/
|
├── bin/
|
||||||
│ ├── monitor.php # CLI: collect metrics
|
|
||||||
│ └── generate-key.php # CLI: generate master key
|
│ └── generate-key.php # CLI: generate master key
|
||||||
├── config/
|
├── config/
|
||||||
│ └── config.php # App configuration
|
│ └── 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"
|
log_step "Configuring Cron Jobs"
|
||||||
|
|
||||||
cat > /etc/cron.d/servermanager << CRONEOF
|
cat > /etc/cron.d/servermanager << CRONEOF
|
||||||
# ServerManager Monitoring Cron
|
# ServerManager Cron Jobs
|
||||||
# Collect metrics every minute
|
# Logs cleanup — weekly
|
||||||
* * * * * www-data /usr/bin/php ${APP_DIR}/bin/monitor.php >> ${APP_DIR}/logs/cron.log 2>&1
|
|
||||||
|
|
||||||
# Cleanup old logs weekly
|
|
||||||
0 3 * * 0 www-data find ${APP_DIR}/logs/ -name "*.log" -mtime +30 -delete
|
0 3 * * 0 www-data find ${APP_DIR}/logs/ -name "*.log" -mtime +30 -delete
|
||||||
CRONEOF
|
CRONEOF
|
||||||
|
|
||||||
@@ -259,32 +256,6 @@ create_binaries() {
|
|||||||
|
|
||||||
mkdir -p "${APP_DIR}/bin"
|
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'
|
cat > "${APP_DIR}/bin/generate-key.php" << 'PHPEOF'
|
||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@@ -307,7 +278,6 @@ echo "Master key generated: {$keyFile}\n";
|
|||||||
echo "IMPORTANT: Store this key securely!\n";
|
echo "IMPORTANT: Store this key securely!\n";
|
||||||
PHPEOF
|
PHPEOF
|
||||||
|
|
||||||
chmod +x "${APP_DIR}/bin/monitor.php"
|
|
||||||
chmod +x "${APP_DIR}/bin/generate-key.php"
|
chmod +x "${APP_DIR}/bin/generate-key.php"
|
||||||
chown -R rafael:rafael "${APP_DIR}/bin"
|
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;
|
$serverUrl = $scheme . $host;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scriptPath = $this->basePath . '/install/agent-install.sh';
|
$scriptPath = $this->basePath . '/bin/agent-install.sh';
|
||||||
|
|
||||||
if (!file_exists($scriptPath)) {
|
if (!file_exists($scriptPath)) {
|
||||||
return ['success' => false, 'error' => 'Agent install script not found'];
|
return ['success' => false, 'error' => 'Agent install script not found'];
|
||||||
@@ -114,7 +114,7 @@ class AgentService
|
|||||||
|
|
||||||
$server = App::getEncryption()->decryptArray($server, ['ssh_password', 'ssh_key']);
|
$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)) {
|
if (!file_exists($scriptPath)) {
|
||||||
return ['success' => false, 'error' => 'Agent uninstall script not found'];
|
return ['success' => false, 'error' => 'Agent uninstall script not found'];
|
||||||
|
|||||||
Reference in New Issue
Block a user