mirror of
https://github.com/myronblair/jarvis
synced 2026-06-30 17:50:23 -05:00
Add DB schema, agent script, vhost config, deploy cron
- db/schema.sql: full jarvis_db schema (15 tables) - agent/jarvis-agent.py: production agent script - config/vhost/: OpenLiteSpeed vhost configuration - deploy/jarvis-agent.service: systemd unit - deploy/cron-jarvis.txt: JARVIS cron entries - .gitignore: exclude system dirs and logs
This commit is contained in:
@@ -8,3 +8,8 @@ logs/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
.imunify_patch_id
|
||||
.ssh/
|
||||
mail.*/
|
||||
logs/
|
||||
backup/
|
||||
|
||||
Executable
+454
@@ -0,0 +1,454 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
JARVIS Agent — lightweight system monitor for Linux machines.
|
||||
Registers with JARVIS, reports metrics, and executes commands.
|
||||
|
||||
Install: sudo bash /opt/jarvis-agent/install.sh
|
||||
Config: /etc/jarvis-agent/config.json
|
||||
Logs: journalctl -u jarvis-agent -f
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
CONFIG_PATH = "/etc/jarvis-agent/config.json"
|
||||
STATE_PATH = "/var/lib/jarvis-agent/state.json"
|
||||
AGENT_VERSION = "2.3" # bumped on each release
|
||||
|
||||
# ── Config helpers ────────────────────────────────────────────────────────────
|
||||
|
||||
def load_config() -> dict:
|
||||
if not os.path.exists(CONFIG_PATH):
|
||||
print(f"[ERROR] Config not found at {CONFIG_PATH}. Run the installer first.", flush=True)
|
||||
sys.exit(1)
|
||||
with open(CONFIG_PATH) as f:
|
||||
return json.load(f)
|
||||
|
||||
def load_state() -> dict:
|
||||
if os.path.exists(STATE_PATH):
|
||||
with open(STATE_PATH) as f:
|
||||
return json.load(f)
|
||||
return {}
|
||||
|
||||
def save_state(state: dict):
|
||||
Path(STATE_PATH).parent.mkdir(parents=True, exist_ok=True)
|
||||
with open(STATE_PATH, "w") as f:
|
||||
json.dump(state, f, indent=2)
|
||||
|
||||
# ── HTTP helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
import ssl as _ssl
|
||||
|
||||
def _make_ssl_ctx(verify: bool) -> _ssl.SSLContext | None:
|
||||
if not verify:
|
||||
ctx = _ssl.create_default_context()
|
||||
ctx.check_hostname = False
|
||||
ctx.verify_mode = _ssl.CERT_NONE
|
||||
return ctx
|
||||
return None
|
||||
|
||||
_host_header: str = "" # set from config at startup
|
||||
|
||||
def api_post(url: str, payload: dict, headers: dict = {}, timeout: int = 15,
|
||||
ssl_verify: bool = True) -> dict:
|
||||
body = json.dumps(payload).encode()
|
||||
req = urllib.request.Request(url, data=body, method="POST")
|
||||
req.add_header("Content-Type", "application/json")
|
||||
req.add_header("User-Agent", "JARVIS-Agent/1.0")
|
||||
if _host_header:
|
||||
req.add_header("Host", _host_header)
|
||||
for k, v in headers.items():
|
||||
req.add_header(k, v)
|
||||
try:
|
||||
ctx = _make_ssl_ctx(ssl_verify)
|
||||
with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp:
|
||||
return json.loads(resp.read().decode())
|
||||
except urllib.error.HTTPError as e:
|
||||
return {"error": f"HTTP {e.code}: {e.read().decode()[:200]}"}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
def api_get(url: str, headers: dict = {}, timeout: int = 10,
|
||||
ssl_verify: bool = True) -> dict:
|
||||
req = urllib.request.Request(url)
|
||||
req.add_header("User-Agent", "JARVIS-Agent/1.0")
|
||||
if _host_header:
|
||||
req.add_header("Host", _host_header)
|
||||
for k, v in headers.items():
|
||||
req.add_header(k, v)
|
||||
try:
|
||||
ctx = _make_ssl_ctx(ssl_verify)
|
||||
with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp:
|
||||
return json.loads(resp.read().decode())
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
# ── Registration ──────────────────────────────────────────────────────────────
|
||||
|
||||
def get_local_ip() -> str:
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.connect(("8.8.8.8", 80))
|
||||
ip = s.getsockname()[0]
|
||||
s.close()
|
||||
return ip
|
||||
except Exception:
|
||||
return "unknown"
|
||||
|
||||
def detect_capabilities(cfg: dict) -> list:
|
||||
caps = ["metrics", "commands"]
|
||||
# Check for Proxmox
|
||||
if os.path.exists("/usr/bin/pvesh") or os.path.exists("/usr/sbin/pveversion"):
|
||||
caps.append("proxmox")
|
||||
# Check for Docker
|
||||
if os.path.exists("/usr/bin/docker") or os.path.exists("/usr/local/bin/docker"):
|
||||
caps.append("docker")
|
||||
# Check for Ollama
|
||||
if os.path.exists("/usr/local/bin/ollama") or os.path.exists("/usr/bin/ollama"):
|
||||
caps.append("ollama")
|
||||
# Check for Home Assistant
|
||||
if os.path.exists("/etc/homeassistant") or os.path.exists("/config/configuration.yaml"):
|
||||
caps.append("homeassistant")
|
||||
return caps
|
||||
|
||||
def register(cfg: dict, state: dict) -> str:
|
||||
"""Register with JARVIS. Returns api_key."""
|
||||
hostname = cfg.get("hostname", socket.gethostname())
|
||||
agent_type = cfg.get("agent_type", "linux")
|
||||
ip = get_local_ip()
|
||||
capabilities = detect_capabilities(cfg)
|
||||
agent_id = cfg.get("agent_id", f"{hostname}_{socket.gethostname()[:8]}")
|
||||
ssl_verify = bool(cfg.get("ssl_verify", True))
|
||||
|
||||
print(f"[JARVIS] Registering as '{agent_id}' ({agent_type}) from {ip}...", flush=True)
|
||||
|
||||
result = api_post(
|
||||
f"{cfg['jarvis_url']}/api/agent/register",
|
||||
{
|
||||
"hostname": hostname,
|
||||
"agent_type": agent_type,
|
||||
"ip_address": ip,
|
||||
"capabilities": capabilities,
|
||||
"agent_id": agent_id,
|
||||
},
|
||||
headers={"X-Registration-Key": cfg["registration_key"]},
|
||||
ssl_verify=ssl_verify,
|
||||
)
|
||||
|
||||
if "error" in result:
|
||||
print(f"[ERROR] Registration failed: {result['error']}", flush=True)
|
||||
return ""
|
||||
|
||||
api_key = result.get("api_key", "")
|
||||
if api_key:
|
||||
state["api_key"] = api_key
|
||||
state["agent_id"] = result.get("agent_id", agent_id)
|
||||
save_state(state)
|
||||
print(f"[JARVIS] Registered. agent_id={state['agent_id']}", flush=True)
|
||||
return api_key
|
||||
|
||||
# ── Metrics collection ────────────────────────────────────────────────────────
|
||||
|
||||
def read_cpu_percent() -> float:
|
||||
try:
|
||||
with open("/proc/stat") as f:
|
||||
line = f.readline()
|
||||
fields = list(map(int, line.split()[1:]))
|
||||
idle = fields[3]
|
||||
total = sum(fields)
|
||||
return round((1 - idle / total) * 100, 1) if total else 0.0
|
||||
except Exception:
|
||||
return 0.0
|
||||
|
||||
_last_cpu = None
|
||||
|
||||
def get_cpu_percent() -> float:
|
||||
global _last_cpu
|
||||
try:
|
||||
with open("/proc/stat") as f:
|
||||
line = f.readline()
|
||||
fields = list(map(int, line.split()[1:]))
|
||||
idle = fields[3] + fields[4] # idle + iowait
|
||||
total = sum(fields)
|
||||
if _last_cpu:
|
||||
d_idle = idle - _last_cpu[0]
|
||||
d_total = total - _last_cpu[1]
|
||||
result = round((1 - d_idle / d_total) * 100, 1) if d_total else 0.0
|
||||
else:
|
||||
result = 0.0
|
||||
_last_cpu = (idle, total)
|
||||
return result
|
||||
except Exception:
|
||||
return 0.0
|
||||
|
||||
def get_memory() -> dict:
|
||||
mem = {}
|
||||
try:
|
||||
with open("/proc/meminfo") as f:
|
||||
for line in f:
|
||||
parts = line.split()
|
||||
if parts[0] in ("MemTotal:", "MemAvailable:", "MemFree:", "Buffers:", "Cached:"):
|
||||
mem[parts[0].rstrip(":")] = int(parts[1])
|
||||
total = mem.get("MemTotal", 0)
|
||||
available = mem.get("MemAvailable", 0)
|
||||
used = total - available
|
||||
return {
|
||||
"total_mb": round(total / 1024, 1),
|
||||
"used_mb": round(used / 1024, 1),
|
||||
"free_mb": round(available / 1024, 1),
|
||||
"percent": round(used / total * 100, 1) if total else 0,
|
||||
}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
def get_disk() -> list:
|
||||
disks = []
|
||||
try:
|
||||
result = subprocess.run(["df", "-h", "--output=source,fstype,size,used,avail,pcent,target"],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
lines = result.stdout.strip().split("\n")[1:]
|
||||
for line in lines:
|
||||
parts = line.split()
|
||||
if len(parts) >= 7:
|
||||
mount = parts[6]
|
||||
if not any(mount.startswith(x) for x in ["/sys", "/proc", "/dev/pts", "/run", "/snap"]):
|
||||
disks.append({
|
||||
"mount": mount,
|
||||
"size": parts[2],
|
||||
"used": parts[3],
|
||||
"avail": parts[4],
|
||||
"percent": parts[5].rstrip("%"),
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
return disks
|
||||
|
||||
def get_uptime() -> dict:
|
||||
try:
|
||||
with open("/proc/uptime") as f:
|
||||
secs = float(f.read().split()[0])
|
||||
days = int(secs // 86400)
|
||||
hours = int((secs % 86400) // 3600)
|
||||
minutes = int((secs % 3600) // 60)
|
||||
return {"seconds": int(secs), "days": days, "hours": hours, "minutes": minutes,
|
||||
"human": f"{days}d {hours}h {minutes}m"}
|
||||
except Exception:
|
||||
return {}
|
||||
|
||||
def get_services(cfg: dict) -> list:
|
||||
watch = cfg.get("watch_services", ["ollama", "homeassistant", "mysql", "nginx", "apache2"])
|
||||
statuses = []
|
||||
for svc in watch:
|
||||
try:
|
||||
r = subprocess.run(["systemctl", "is-active", svc], capture_output=True, text=True, timeout=3)
|
||||
statuses.append({"service": svc, "status": r.stdout.strip()})
|
||||
except Exception:
|
||||
statuses.append({"service": svc, "status": "unknown"})
|
||||
return statuses
|
||||
|
||||
def get_load() -> list:
|
||||
try:
|
||||
with open("/proc/loadavg") as f:
|
||||
parts = f.read().split()
|
||||
return [float(parts[0]), float(parts[1]), float(parts[2])]
|
||||
except Exception:
|
||||
return [0, 0, 0]
|
||||
|
||||
def collect_metrics(cfg: dict) -> dict:
|
||||
# First reading for CPU delta
|
||||
get_cpu_percent()
|
||||
time.sleep(1)
|
||||
return {
|
||||
"hostname": cfg.get("hostname", socket.gethostname()),
|
||||
"cpu_percent": get_cpu_percent(),
|
||||
"memory": get_memory(),
|
||||
"disk": get_disk(),
|
||||
"uptime": get_uptime(),
|
||||
"load": get_load(),
|
||||
"services": get_services(cfg),
|
||||
"platform": platform.system(),
|
||||
"timestamp": datetime.utcnow().isoformat() + "Z",
|
||||
}
|
||||
|
||||
# ── Proxmox metrics ───────────────────────────────────────────────────────────
|
||||
|
||||
def collect_proxmox_metrics(cfg: dict) -> dict | None:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["pvesh", "get", "/nodes/pve/status", "--output-format", "json"],
|
||||
capture_output=True, text=True, timeout=10
|
||||
)
|
||||
node_status = json.loads(result.stdout)
|
||||
vms_result = subprocess.run(
|
||||
["pvesh", "get", "/nodes/pve/qemu", "--output-format", "json"],
|
||||
capture_output=True, text=True, timeout=10
|
||||
)
|
||||
vms = json.loads(vms_result.stdout)
|
||||
return {"node": node_status, "vms": vms}
|
||||
except Exception as e:
|
||||
return {"error": str(e)}
|
||||
|
||||
# ── Command execution ─────────────────────────────────────────────────────────
|
||||
|
||||
def execute_command(cmd: dict) -> dict:
|
||||
cmd_type = cmd.get("command_type", "")
|
||||
cmd_data = cmd.get("command_data", {})
|
||||
|
||||
try:
|
||||
if cmd_type == "restart_service":
|
||||
svc = cmd_data.get("service", "")
|
||||
if not svc or "/" in svc:
|
||||
return {"success": False, "error": "Invalid service name"}
|
||||
r = subprocess.run(["systemctl", "restart", svc], capture_output=True, text=True, timeout=30)
|
||||
return {"success": r.returncode == 0, "stdout": r.stdout, "stderr": r.stderr}
|
||||
|
||||
elif cmd_type == "get_logs":
|
||||
svc = cmd_data.get("service", "")
|
||||
lines = min(int(cmd_data.get("lines", 50)), 200)
|
||||
if not svc or "/" in svc:
|
||||
return {"success": False, "error": "Invalid service name"}
|
||||
r = subprocess.run(["journalctl", "-u", svc, "-n", str(lines), "--no-pager"],
|
||||
capture_output=True, text=True, timeout=15)
|
||||
return {"success": True, "output": r.stdout}
|
||||
|
||||
elif cmd_type == "ping":
|
||||
host = cmd_data.get("host", "8.8.8.8")
|
||||
r = subprocess.run(["ping", "-c", "3", "-W", "2", host], capture_output=True, text=True, timeout=15)
|
||||
return {"success": r.returncode == 0, "output": r.stdout}
|
||||
|
||||
elif cmd_type == "update":
|
||||
updated = self_update(cfg)
|
||||
return {"success": True, "updated": updated}
|
||||
|
||||
elif cmd_type == "shell":
|
||||
# Only allow if explicitly enabled in config
|
||||
if not cmd_data.get("allowed", False):
|
||||
return {"success": False, "error": "Shell commands not enabled"}
|
||||
cmd_str = cmd_data.get("command", "")
|
||||
r = subprocess.run(cmd_str, shell=True, capture_output=True, text=True, timeout=30)
|
||||
return {"success": True, "stdout": r.stdout[:2000], "stderr": r.stderr[:500]}
|
||||
|
||||
else:
|
||||
return {"success": False, "error": f"Unknown command type: {cmd_type}"}
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
return {"success": False, "error": "Command timed out"}
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
# ── Main loop ─────────────────────────────────────────────────────────────────
|
||||
|
||||
def main():
|
||||
global _host_header
|
||||
cfg = load_config()
|
||||
state = load_state()
|
||||
|
||||
jarvis_url = cfg["jarvis_url"].rstrip("/")
|
||||
ssl_verify = bool(cfg.get("ssl_verify", True))
|
||||
_host_header = cfg.get("host_header", "")
|
||||
poll_interval = int(cfg.get("poll_interval", 30))
|
||||
heartbeat_every = int(cfg.get("heartbeat_every", 10))
|
||||
|
||||
# Register if no API key yet
|
||||
api_key = state.get("api_key", "")
|
||||
if not api_key:
|
||||
api_key = register(cfg, state)
|
||||
if not api_key:
|
||||
print("[ERROR] Could not register with JARVIS. Retrying in 60s...", flush=True)
|
||||
time.sleep(60)
|
||||
main()
|
||||
return
|
||||
|
||||
headers = {"X-Agent-Key": api_key}
|
||||
last_metrics = 0
|
||||
last_update_chk = 0
|
||||
update_interval = int(cfg.get("update_check_hours", 24)) * 3600
|
||||
tick = 0
|
||||
|
||||
print(f"[JARVIS] Agent v{AGENT_VERSION} running. Polling {jarvis_url} every {heartbeat_every}s.", flush=True)
|
||||
|
||||
while True:
|
||||
tick += 1
|
||||
now = time.time()
|
||||
|
||||
try:
|
||||
# Heartbeat + get commands
|
||||
hb = api_post(f"{jarvis_url}/api/agent/heartbeat", {}, headers, ssl_verify=ssl_verify)
|
||||
if "error" in hb:
|
||||
print(f"[WARN] Heartbeat failed: {hb['error']}", flush=True)
|
||||
else:
|
||||
commands = hb.get("commands", [])
|
||||
for cmd in commands:
|
||||
print(f"[CMD] Executing: {cmd['command_type']}", flush=True)
|
||||
result = execute_command(cmd)
|
||||
api_post(f"{jarvis_url}/api/agent/command_result",
|
||||
{"command_id": cmd["id"], "success": result.get("success", False), "result": result},
|
||||
headers, ssl_verify=ssl_verify)
|
||||
|
||||
# Self-update check (every update_interval seconds, default 24h)
|
||||
if now - last_update_chk >= update_interval:
|
||||
last_update_chk = now
|
||||
self_update(cfg) # restarts process if update found
|
||||
|
||||
# Push metrics every poll_interval seconds
|
||||
if now - last_metrics >= poll_interval:
|
||||
metrics = collect_metrics(cfg)
|
||||
api_post(f"{jarvis_url}/api/agent/metrics",
|
||||
{"type": "system", "data": metrics}, headers, ssl_verify=ssl_verify)
|
||||
|
||||
# Proxmox metrics if available
|
||||
if "proxmox" in detect_capabilities(cfg):
|
||||
px = collect_proxmox_metrics(cfg)
|
||||
if px:
|
||||
api_post(f"{jarvis_url}/api/agent/metrics",
|
||||
{"type": "proxmox", "data": px}, headers, ssl_verify=ssl_verify)
|
||||
|
||||
last_metrics = now
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Loop error: {e}", flush=True)
|
||||
|
||||
time.sleep(heartbeat_every)
|
||||
|
||||
|
||||
# ── Self-update ────────────────────────────────────────────────────────────────
|
||||
|
||||
def self_update(cfg: dict) -> bool:
|
||||
"""Check JARVIS server for a newer version of this script. If different, replace and restart."""
|
||||
jarvis_url = cfg.get("jarvis_url", "").rstrip("/")
|
||||
default_update_url = f"{jarvis_url}/agent/jarvis-agent.py" if jarvis_url else ""
|
||||
update_url = cfg.get("update_url", default_update_url)
|
||||
if not update_url:
|
||||
return False
|
||||
script_path = os.path.abspath(__file__)
|
||||
try:
|
||||
req = urllib.request.Request(update_url)
|
||||
req.add_header("User-Agent", "JARVIS-Agent/1.0")
|
||||
with urllib.request.urlopen(req, timeout=30) as resp:
|
||||
new_content = resp.read()
|
||||
with open(script_path, "rb") as f:
|
||||
current = f.read()
|
||||
if new_content != current:
|
||||
print(f"[JARVIS] Update available — replacing {script_path} and restarting...", flush=True)
|
||||
with open(script_path, "wb") as f:
|
||||
f.write(new_content)
|
||||
os.execv(sys.executable, [sys.executable] + sys.argv)
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"[JARVIS] Self-update check failed: {e}", flush=True)
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
docRoot $VH_ROOT/public_html
|
||||
vhDomain $VH_NAME
|
||||
vhAliases www.$VH_NAME
|
||||
adminEmails admin@orbishosting.com
|
||||
enableGzip 1
|
||||
enableIpGeo 1
|
||||
|
||||
index {
|
||||
useServer 0
|
||||
indexFiles index.php, index.html
|
||||
}
|
||||
|
||||
errorlog $VH_ROOT/logs/$VH_NAME.error_log {
|
||||
useServer 0
|
||||
logLevel WARN
|
||||
rollingSize 10M
|
||||
}
|
||||
|
||||
accesslog $VH_ROOT/logs/$VH_NAME.access_log {
|
||||
useServer 0
|
||||
logFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i""
|
||||
logHeaders 5
|
||||
rollingSize 10M
|
||||
keepDays 10
|
||||
compressArchive 1
|
||||
}
|
||||
|
||||
scripthandler {
|
||||
add lsapi:jarvi5150 php
|
||||
}
|
||||
|
||||
extprocessor jarvi5150 {
|
||||
type lsapi
|
||||
address UDS://tmp/lshttpd/jarvi5150.sock
|
||||
maxConns 10
|
||||
env LSAPI_CHILDREN=10
|
||||
initTimeout 600
|
||||
retryTimeout 0
|
||||
persistConn 1
|
||||
pcKeepAliveTimeout 1
|
||||
respBuffer 0
|
||||
autoStart 1
|
||||
path /usr/local/lsws/lsphp85/bin/lsphp
|
||||
extUser jarvi5150
|
||||
extGroup jarvi5150
|
||||
memSoftLimit 1024M
|
||||
memHardLimit 1024M
|
||||
procSoftLimit 400
|
||||
procHardLimit 500
|
||||
}
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
|
||||
module cache {
|
||||
storagePath /usr/local/lsws/cachedata/$VH_NAME
|
||||
}
|
||||
|
||||
rewrite {
|
||||
enable 1
|
||||
autoLoadHtaccess 1
|
||||
rules <<<END_RULES
|
||||
RewriteRule ^/api(/.*)?$ /api.php [QSA,L]
|
||||
END_RULES
|
||||
}
|
||||
|
||||
context /.well-known/acme-challenge {
|
||||
location /usr/local/lsws/Example/html/.well-known/acme-challenge
|
||||
allowBrowse 1
|
||||
|
||||
rewrite {
|
||||
enable 0
|
||||
}
|
||||
addDefaultCharset off
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vhssl {
|
||||
keyFile /etc/letsencrypt/live/jarvis.orbishosting.com/privkey.pem
|
||||
certFile /etc/letsencrypt/live/jarvis.orbishosting.com/fullchain.pem
|
||||
certChain 1
|
||||
sslProtocol 24
|
||||
enableECDHE 1
|
||||
renegProtection 1
|
||||
sslSessionCache 1
|
||||
enableSpdy 15
|
||||
enableStapling 1
|
||||
ocspRespMaxAge 86400
|
||||
}
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
docRoot $VH_ROOT/public_html
|
||||
vhDomain $VH_NAME
|
||||
vhAliases www.$VH_NAME
|
||||
adminEmails admin@orbishosting.com
|
||||
enableGzip 1
|
||||
enableIpGeo 1
|
||||
|
||||
index {
|
||||
useServer 0
|
||||
indexFiles index.php, index.html
|
||||
}
|
||||
|
||||
errorlog $VH_ROOT/logs/$VH_NAME.error_log {
|
||||
useServer 0
|
||||
logLevel WARN
|
||||
rollingSize 10M
|
||||
}
|
||||
|
||||
accesslog $VH_ROOT/logs/$VH_NAME.access_log {
|
||||
useServer 0
|
||||
logFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i""
|
||||
logHeaders 5
|
||||
rollingSize 10M
|
||||
keepDays 10
|
||||
compressArchive 1
|
||||
}
|
||||
|
||||
scripthandler {
|
||||
add lsapi:jarvi5150 php
|
||||
}
|
||||
|
||||
extprocessor jarvi5150 {
|
||||
type lsapi
|
||||
address UDS://tmp/lshttpd/jarvi5150.sock
|
||||
maxConns 10
|
||||
env LSAPI_CHILDREN=10
|
||||
initTimeout 600
|
||||
retryTimeout 0
|
||||
persistConn 1
|
||||
pcKeepAliveTimeout 1
|
||||
respBuffer 0
|
||||
autoStart 1
|
||||
path /usr/local/lsws/lsphp85/bin/lsphp
|
||||
extUser jarvi5150
|
||||
extGroup jarvi5150
|
||||
memSoftLimit 1024M
|
||||
memHardLimit 1024M
|
||||
procSoftLimit 400
|
||||
procHardLimit 500
|
||||
}
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
|
||||
module cache {
|
||||
storagePath /usr/local/lsws/cachedata/$VH_NAME
|
||||
}
|
||||
|
||||
rewrite {
|
||||
enable 1
|
||||
autoLoadHtaccess 1
|
||||
rules <<<END_RULES
|
||||
RewriteRule ^/api(/.*)?$ /api.php [QSA,L]
|
||||
END_RULES
|
||||
}
|
||||
|
||||
context /.well-known/acme-challenge {
|
||||
location /usr/local/lsws/Example/html/.well-known/acme-challenge
|
||||
allowBrowse 1
|
||||
|
||||
rewrite {
|
||||
enable 0
|
||||
}
|
||||
addDefaultCharset off
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vhssl {
|
||||
keyFile /etc/letsencrypt/live/jarvis.orbishosting.com/privkey.pem
|
||||
certFile /etc/letsencrypt/live/jarvis.orbishosting.com/fullchain.pem
|
||||
certChain 1
|
||||
sslProtocol 24
|
||||
enableECDHE 1
|
||||
renegProtection 1
|
||||
sslSessionCache 1
|
||||
enableSpdy 15
|
||||
enableStapling 1
|
||||
ocspRespMaxAge 86400
|
||||
}
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
head 1.3;
|
||||
access;
|
||||
symbols;
|
||||
locks
|
||||
root:1.3; strict;
|
||||
comment @# @;
|
||||
|
||||
|
||||
1.3
|
||||
date 2026.05.23.03.40.46; author root; state Exp;
|
||||
branches;
|
||||
next 1.2;
|
||||
|
||||
1.2
|
||||
date 2026.05.23.03.14.25; author root; state Exp;
|
||||
branches;
|
||||
next 1.1;
|
||||
|
||||
1.1
|
||||
date 2026.05.23.03.12.53; author root; state Exp;
|
||||
branches;
|
||||
next ;
|
||||
|
||||
|
||||
desc
|
||||
@/usr/local/lsws/conf/vhosts/jarvis.orbishosting.com/vhost.conf0
|
||||
@
|
||||
|
||||
|
||||
1.3
|
||||
log
|
||||
@Update
|
||||
@
|
||||
text
|
||||
@docRoot $VH_ROOT/public_html
|
||||
vhDomain $VH_NAME
|
||||
vhAliases www.$VH_NAME
|
||||
adminEmails admin@@orbishosting.com
|
||||
enableGzip 1
|
||||
enableIpGeo 1
|
||||
|
||||
index {
|
||||
useServer 0
|
||||
indexFiles index.php, index.html
|
||||
}
|
||||
|
||||
errorlog $VH_ROOT/logs/$VH_NAME.error_log {
|
||||
useServer 0
|
||||
logLevel WARN
|
||||
rollingSize 10M
|
||||
}
|
||||
|
||||
accesslog $VH_ROOT/logs/$VH_NAME.access_log {
|
||||
useServer 0
|
||||
logFormat "%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i""
|
||||
logHeaders 5
|
||||
rollingSize 10M
|
||||
keepDays 10
|
||||
compressArchive 1
|
||||
}
|
||||
|
||||
scripthandler {
|
||||
add lsapi:jarvi5150 php
|
||||
}
|
||||
|
||||
extprocessor jarvi5150 {
|
||||
type lsapi
|
||||
address UDS://tmp/lshttpd/jarvi5150.sock
|
||||
maxConns 10
|
||||
env LSAPI_CHILDREN=10
|
||||
initTimeout 600
|
||||
retryTimeout 0
|
||||
persistConn 1
|
||||
pcKeepAliveTimeout 1
|
||||
respBuffer 0
|
||||
autoStart 1
|
||||
path /usr/local/lsws/lsphp85/bin/lsphp
|
||||
extUser jarvi5150
|
||||
extGroup jarvi5150
|
||||
memSoftLimit 1024M
|
||||
memHardLimit 1024M
|
||||
procSoftLimit 400
|
||||
procHardLimit 500
|
||||
}
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
|
||||
module cache {
|
||||
storagePath /usr/local/lsws/cachedata/$VH_NAME
|
||||
}
|
||||
|
||||
rewrite {
|
||||
enable 1
|
||||
autoLoadHtaccess 1
|
||||
rules <<<END_RULES
|
||||
RewriteRule ^/api(/.*)?$ /api.php [QSA,L]
|
||||
END_RULES
|
||||
}
|
||||
|
||||
context /.well-known/acme-challenge {
|
||||
location /usr/local/lsws/Example/html/.well-known/acme-challenge
|
||||
allowBrowse 1
|
||||
|
||||
rewrite {
|
||||
enable 0
|
||||
}
|
||||
addDefaultCharset off
|
||||
|
||||
phpIniOverride {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
vhssl {
|
||||
keyFile /etc/letsencrypt/live/jarvis.orbishosting.com/privkey.pem
|
||||
certFile /etc/letsencrypt/live/jarvis.orbishosting.com/fullchain.pem
|
||||
certChain 1
|
||||
sslProtocol 24
|
||||
enableECDHE 1
|
||||
renegProtection 1
|
||||
sslSessionCache 1
|
||||
enableSpdy 15
|
||||
enableStapling 1
|
||||
ocspRespMaxAge 86400
|
||||
}
|
||||
@
|
||||
|
||||
|
||||
1.2
|
||||
log
|
||||
@Update
|
||||
@
|
||||
text
|
||||
@d63 3
|
||||
@
|
||||
|
||||
|
||||
1.1
|
||||
log
|
||||
@Update
|
||||
@
|
||||
text
|
||||
@d79 13
|
||||
@
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
/*M!999999\- enable the sandbox mode */
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
DROP TABLE IF EXISTS `agent_commands`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `agent_commands` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` varchar(128) NOT NULL,
|
||||
`command_type` varchar(64) NOT NULL,
|
||||
`command_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`command_data`)),
|
||||
`status` enum('pending','delivered','executed','failed') NOT NULL DEFAULT 'pending',
|
||||
`created_at` datetime DEFAULT current_timestamp(),
|
||||
`delivered_at` datetime DEFAULT NULL,
|
||||
`executed_at` datetime DEFAULT NULL,
|
||||
`result` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`result`)),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_agent_pending` (`agent_id`,`status`),
|
||||
KEY `idx_created` (`created_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `agent_metrics`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `agent_metrics` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` varchar(128) NOT NULL,
|
||||
`metric_type` varchar(64) NOT NULL,
|
||||
`metric_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`metric_data`)),
|
||||
`recorded_at` datetime DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_agent_time` (`agent_id`,`recorded_at`),
|
||||
KEY `idx_recorded` (`recorded_at`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=28329 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `alerts`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `alerts` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`alert_type` varchar(50) NOT NULL,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`message` text DEFAULT NULL,
|
||||
`severity` enum('info','warning','critical') DEFAULT 'info',
|
||||
`resolved` tinyint(1) DEFAULT 0,
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
`resolved_at` timestamp NULL DEFAULT NULL,
|
||||
`source_key` varchar(100) DEFAULT NULL,
|
||||
`auto_resolve` tinyint(1) DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_source_key` (`source_key`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `api_cache`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `api_cache` (
|
||||
`cache_key` varchar(100) NOT NULL,
|
||||
`data` mediumtext NOT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`cache_key`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `conversations`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `conversations` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`session_id` varchar(64) NOT NULL,
|
||||
`role` enum('user','assistant','system') NOT NULL,
|
||||
`content` text NOT NULL,
|
||||
`tokens_used` int(11) DEFAULT 0,
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_session` (`session_id`),
|
||||
KEY `idx_created` (`created_at`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=325 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `ha_entities`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `ha_entities` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` varchar(128) NOT NULL,
|
||||
`entity_id` varchar(255) NOT NULL,
|
||||
`entity_name` varchar(255) DEFAULT NULL,
|
||||
`domain` varchar(64) DEFAULT NULL,
|
||||
`state` varchar(255) DEFAULT NULL,
|
||||
`attributes` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`attributes`)),
|
||||
`last_changed` datetime DEFAULT NULL,
|
||||
`updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_agent_entity` (`agent_id`,`entity_id`),
|
||||
KEY `idx_domain` (`domain`),
|
||||
KEY `idx_updated` (`updated_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `kb_facts`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `kb_facts` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`category` varchar(64) NOT NULL COMMENT 'e.g. system, network, proxmox, ha, weather',
|
||||
`fact_key` varchar(128) NOT NULL,
|
||||
`fact_value` text NOT NULL,
|
||||
`host` varchar(64) DEFAULT 'local',
|
||||
`expires_at` datetime DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `unique_fact` (`category`,`fact_key`,`host`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=26088 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `kb_intents`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `kb_intents` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`intent_name` varchar(64) NOT NULL,
|
||||
`pattern` varchar(512) NOT NULL COMMENT 'regex pattern to match user input',
|
||||
`response_template` text NOT NULL COMMENT 'template with {fact_key} placeholders',
|
||||
`fact_category` varchar(64) DEFAULT NULL,
|
||||
`action_type` varchar(32) DEFAULT 'response' COMMENT 'response, action, ollama, claude',
|
||||
`priority` int(11) DEFAULT 5,
|
||||
`active` tinyint(1) DEFAULT 1,
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `kb_ollama_models`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `kb_ollama_models` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`model_name` varchar(128) NOT NULL,
|
||||
`size_gb` decimal(6,1) DEFAULT NULL,
|
||||
`context_length` int(11) DEFAULT 4096,
|
||||
`is_active` tinyint(1) DEFAULT 0,
|
||||
`pulled_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `model_name` (`model_name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `kb_preferences`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `kb_preferences` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`pref_key` varchar(128) NOT NULL,
|
||||
`pref_value` text NOT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `pref_key` (`pref_key`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `known_commands`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `known_commands` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`phrase` varchar(255) NOT NULL,
|
||||
`action` varchar(100) NOT NULL,
|
||||
`params` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`params`)),
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `metrics_history`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `metrics_history` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`metric_name` varchar(100) NOT NULL,
|
||||
`metric_value` float NOT NULL,
|
||||
`host` varchar(100) DEFAULT 'jarvis',
|
||||
`recorded_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_metric_time` (`metric_name`,`recorded_at`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=33415 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `network_devices`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `network_devices` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`ip` varchar(45) NOT NULL,
|
||||
`mac` varchar(17) DEFAULT NULL,
|
||||
`hostname` varchar(255) DEFAULT NULL,
|
||||
`alias` varchar(100) DEFAULT NULL,
|
||||
`device_type` varchar(50) DEFAULT NULL,
|
||||
`last_seen` timestamp NULL DEFAULT NULL,
|
||||
`status` enum('online','offline','unknown') DEFAULT 'unknown',
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_ip` (`ip`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=409 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `registered_agents`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `registered_agents` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`agent_id` varchar(128) NOT NULL,
|
||||
`hostname` varchar(255) NOT NULL,
|
||||
`agent_type` enum('linux','homeassistant','proxmox') NOT NULL DEFAULT 'linux',
|
||||
`ip_address` varchar(45) DEFAULT NULL,
|
||||
`api_key` varchar(64) NOT NULL,
|
||||
`capabilities` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`capabilities`)),
|
||||
`last_seen` datetime DEFAULT NULL,
|
||||
`status` enum('online','offline','unknown') NOT NULL DEFAULT 'unknown',
|
||||
`created_at` datetime DEFAULT current_timestamp(),
|
||||
`updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_agent_id` (`agent_id`),
|
||||
KEY `idx_status` (`status`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
DROP TABLE IF EXISTS `users`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8mb4 */;
|
||||
CREATE TABLE `users` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`username` varchar(50) NOT NULL,
|
||||
`password_hash` varchar(255) NOT NULL,
|
||||
`display_name` varchar(100) DEFAULT 'Mr. Blair',
|
||||
`preferences` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`preferences`)),
|
||||
`last_seen` timestamp NULL DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `username` (`username`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
*/3 * * * * /usr/local/lsws/lsphp85/bin/lsphp /home/jarvis.orbishosting.com/api/endpoints/facts_collector.php >> /home/jarvis.orbishosting.com/logs/cron.log 2>&1
|
||||
*/5 * * * * /usr/local/lsws/lsphp85/bin/lsphp /home/jarvis.orbishosting.com/api/endpoints/stats_cache.php >> /home/jarvis.orbishosting.com/logs/cron.log 2>&1
|
||||
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=JARVIS Agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/python3 /usr/local/bin/jarvis-agent.py
|
||||
Restart=always
|
||||
RestartSec=30
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user