can we run a multi agent puthon script in Kali Linux GNOME in OS headless mode after booting into desktop? Will this free up memory for agents to run?
Gemini said
The short answer is yes, you can absolutely do this, but there is a slight nuance in how "headless" works once a desktop environment like GNOME has already started.
If your goal is to squeeze every drop of RAM out of your Kali machine for a resource-heavy multi-agent Python script, you have a few ways to approach this.
1. Understanding "Headless" vs. "No-GUI"
Technically, if you have already booted into the GNOME desktop, the OS is no longer in a headless state—it is actively rendering a graphical user interface (GUI).
Simply closing the lid or turning off the monitor does not free up memory; the GNOME Shell and X11/Wayland processes remain active in the background.
True Headless Mode means the system boots to a Command Line Interface (CLI) without ever starting the display server.
Does it free up memory?
Yes, significantly. GNOME is a "heavy" desktop environment. By stopping the GUI and running your script in a TTY (terminal) or via SSH, you can typically reclaim 800MB to 1.5GB of RAM, depending on your configuration. For multi-agent systems (which often use local LLMs or heavy libraries like LangChain/AutoGPT), this is often the difference between the script running smoothly or crashing due to "Out of Memory" (OOM) errors.
2. How to "Go Headless" After Booting
If you are already at the desktop and want to kill the GUI to free up RAM for your agents, follow these steps:
Option A: Temporary Switch (The "Quick Kill")
You can switch the system to a multi-user target (CLI) without rebooting. Open your terminal and run:
sudo systemctl isolate multi-user.target
Result: Your screen will go black and return to a login prompt. All GNOME processes are terminated, freeing up memory immediately.
To get the GUI back: Run
sudo systemctl isolate graphical.target.
Option B: The SSH Approach (Best for Multi-Agent Monitoring)
If you want to run the agents and leave the machine alone:
Enable SSH:
sudo systemctl enable --now sshIdentify IP:
ip aFrom another computer: Connect via
ssh user@kali-ip.Use a Terminal Multiplexer: Run
tmuxorscreen. This allows your Python script to keep running even if your SSH connection drops.
3. Optimizing Python Agent Performance
Since you are looking to maximize resources, consider these three tips for your script:
Summary Checklist
Boot to CLI: Use
sudo systemctl set-default multi-user.targetto make the "headless" mode permanent on reboot.Memory Check: Use the
htoporfree -mcommand before and after killing GNOME to see exactly how much RAM you've recovered.Python Execution: Run your script using
nohup python3 your_script.py &or within atmuxsession to ensure it doesn't die when you log out.
Would you like me to help you write a bash script that automates the transition from GUI to Headless while launching your Python environment?
yes
Gemini said
Excellent. Let's build a robust automation script. This bash script will gracefully shut down the GNOME display manager, clear the memory cache, and launch your multi-agent Python environment inside a tmux session so it stays alive even if you disconnect.
The Automation Script (headless_launch.sh)
Copy this into a file named headless_launch.sh:
#!/bin/bash
# 1. Define your script path
AGENT_SCRIPT="/path/to/your/agent_script.py"
VENV_PATH="/path/to/your/venv/bin/activate"
echo "--- Initializing Headless Agent Environment ---"
# 2. Switch to CLI mode (Kills GNOME/X11)
echo "[*] Terminating Graphical Desktop to free RAM..."
sudo systemctl isolate multi-user.target
# 3. Clear RAM Caches (Optional but helpful)
echo "[*] Dropping system caches..."
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
# 4. Launch in a TMUX session
echo "[*] Launching Python Agents in tmux session 'agent_room'..."
tmux new-session -d -s agent_room "source $VENV_PATH && python3 $AGENT_SCRIPT"
echo "--- Success ---"
echo "GNOME is down. RAM is freed."
echo "To monitor your agents, use: tmux attach -t agent_room"
Why this works for Multi-Agent Systems
Multi-agent frameworks (like CrewAI, AutoGen, or custom LangChain setups) often suffer from context switching overhead and memory fragmentation.
By isolating the system to the multi-user.target, you remove the following memory-hogging components:
Xorg/Wayland: The display server.
GNOME Shell: The actual UI you see.
Evolution/Tracker: Background indexing services that Kali often runs.
GPU Overhead: If your agents use local models (Ollama/PyTorch), freeing the GUI often frees up VRAM as well, which is crucial for model performance.
How to use it
Make it executable:
chmod +x headless_launch.shRun it:
./headless_launch.shCheck your gains: Run
free -hto see your newly available memory.
Important Note on Networking
Since you are killing the GUI, you will lose your Wi-Fi if you were managing it through the GNOME taskbar. To ensure your agents stay connected, make sure your NetworkManager is configured to keep connections active in CLI mode:
sudo nmcli device set wlan0 autoconnect yes
Would you like me to add a section to the script that logs the memory usage of each Python agent to a CSV file while it runs?
yes
Gemini said
Adding a logging component is a smart move. When running multi-agent systems (like CrewAI, AutoGen, or LangChain), memory leaks or "runaway" agents can quietly crash your headless session. Monitoring the RAM per-process helps you identify which specific agent is the resource hog.
Here is the updated script. I’ve added a background monitor that captures the PID, CPU%, and Memory usage of your agents every 30 seconds.
The Enhanced headless_monitor.sh
#!/bin/bash
# --- Configuration ---
AGENT_SCRIPT="your_script.py" # Name of your main python file
VENV_PATH="./venv/bin/activate"
LOG_FILE="agent_perf_log.csv"
# 1. Prepare the CSV Header
echo "Timestamp,PID,CPU_Percent,Memory_MB,Command" > $LOG_FILE
# 2. Kill GNOME to free RAM
echo "[*] Switching to Headless (multi-user.target)..."
sudo systemctl isolate multi-user.target
sleep 2
# 3. Clear Caches
echo "[*] Dropping RAM caches..."
sudo sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
# 4. Launch Agents in Tmux
echo "[*] Starting Agents in tmux session 'agent_room'..."
tmux new-session -d -s agent_room "source $VENV_PATH && python3 $AGENT_SCRIPT"
# 5. Background Monitoring Loop
echo "[*] Monitoring started. Logging to $LOG_FILE..."
(
while true; do
# Capture all python processes related to your script
ps -C python3 -o lstart,pid,pcpu,rss,args --sort=-rss | grep "$AGENT_SCRIPT" | while read -r line; do
if [ ! -z "$line" ]; then
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
# Convert RSS (KB) to MB
PID=$(echo $line | awk '{print $6}')
CPU=$(echo $line | awk '{print $7}')
MEM_KB=$(echo $line | awk '{print $8}')
MEM_MB=$(echo "scale=2; $MEM_KB / 1024" | bc)
echo "$TIMESTAMP,$PID,$CPU,$MEM_MB,$AGENT_SCRIPT" >> $LOG_FILE
fi
done
sleep 30
done
) &
echo "--- System is now Headless ---"
echo "Check logs with: tail -f $LOG_FILE"
echo "Reattach to agents with: tmux attach -t agent_room"
Understanding the Resource Gains
When you run this, you'll notice a massive drop in "Resident Set Size" (RSS). In a GUI environment, the OS has to keep the frame buffer and window manager high in the priority list. In headless mode, the Linux kernel's OOM Killer is less likely to target your Python processes because they are the primary consumers of the system's resources.
How to analyze the results
After your agents finish their task, you can open the agent_perf_log.csv in any spreadsheet tool. Look for:
Memory Spikes: If
Memory_MBclimbs steadily without dropping, your agents have a memory leak.CPU Bottlenecks: If
CPU_Percentstays at 100% per agent, you may need to implementtime.sleep()intervals to prevent thermal throttling.
Pro-Tip: Re-enabling the GUI
When your work is done and you want your Kali desktop back, simply run:
sudo systemctl isolate graphical.target
Would you like me to help you set up a "Watchdog" feature that automatically restarts an agent if the log shows it has crashed or hung?
yes
Gemini said
A "Watchdog" is essential for long-running multi-agent systems because Python scripts can sometimes hang due to network timeouts, API rate limits, or deadlocks between agents.
By adding this, your headless Kali instance becomes a self-healing "agent server."
The Ultimate Headless Watchdog Script
This version combines the headless transition, resource logging, and a restart loop. Save this as agent_watchdog.sh:
#!/bin/bash
# --- Configuration ---
AGENT_COMMAND="python3 your_script.py"
VENV_PATH="./venv/bin/activate"
LOG_FILE="agent_watchdog.log"
MAX_RESTARTS=5
RESTART_COUNT=0
# 1. Transition to Headless
echo "[*] Shifting to Headless Mode..."
sudo systemctl isolate multi-user.target
sleep 5
# 2. The Watchdog Loop
echo "[*] Watchdog active. Starting agents..."
while [ $RESTART_COUNT -lt $MAX_RESTARTS ]; do
echo "[$(date)] Launching Agent Session (Attempt $((RESTART_COUNT+1)))" >> $LOG_FILE
# Run inside a tmux session and WAIT for it to exit
tmux new-session -d -s agent_room "source $VENV_PATH && $AGENT_COMMAND"
# Monitor if the tmux session is still alive
while tmux has-session -t agent_room 2>/dev/null; do
sleep 10
# Optional: Add memory check logic here to kill session if it exceeds RAM limits
done
# If we reach here, the script crashed or finished
RESTART_COUNT=$((RESTART_COUNT+1))
echo "[$(date)] Agent session exited. Restarting in 10s..." >> $LOG_FILE
sleep 10
done
echo "[!] Max restarts reached. Manual intervention required." >> $LOG_FILE
How the Watchdog Protects Your RAM
In a standard GUI environment, if a Python script leaks memory, the OOM (Out of Memory) Killer might kill the entire Desktop Environment to save the system. In headless mode, the kernel has a much clearer "line of sight" to your specific process.
Best Practices for Your Agents
To make this setup even more stable, ensure your Python code includes:
Checkpoints: Save the state of your agents to a JSON or SQLite file every few minutes.
Try/Except Blocks: Wrap your main agent loop in a
try...exceptso that minor API errors don't crash the entire script.Graceful Exit: Use the
signallibrary in Python to catchSIGTERMso your agents can save their work before the watchdog restarts them.
Managing the Headless Server
Since you are now running without a screen, these three commands will be your "control center":
View Live Output:
tmux attach -t agent_room(PressCtrl+BthenDto detach)Check Resource Logs:
tail -f agent_watchdog.logReboot to GUI:
sudo systemctl isolate graphical.target
Would you like me to show you how to set this script to run automatically as soon as Kali boots up, so you don't even have to log in?
yes
Gemini said
To make this setup "hands-free," we will use systemd. This allows your Kali machine to boot directly into a resource-optimized CLI state, launch your agents, and start the watchdog without you ever needing to log in or touch a keyboard.
Step 1: Set Kali to Boot into CLI Mode (Headless)
First, tell the system to stop loading the GNOME desktop by default. This ensures you start with the maximum available RAM.
sudo systemctl set-default multi-user.target
(To reverse this later, use sudo systemctl set-default graphical.target)
Step 2: Create the systemd Service File
We will create a service unit that manages your watchdog script. This makes the script behave like a professional background daemon.
Create the file:
sudo nano /etc/systemd/system/agent-server.servicePaste the following configuration:
[Unit]
Description=Multi-Agent Python Watchdog Service
After=network.target
[Service]
# Replace 'kali' with your actual username
User=kali
WorkingDirectory=/home/kali/your_project_folder
# Path to your watchdog script
ExecStart=/bin/bash /home/kali/your_project_folder/agent_watchdog.sh
Restart=always
# Optional: wait 10 seconds before restarting if the watchdog itself fails
RestartSec=10
[Install]
WantedBy=multi-user.target
Step 3: Enable and Start
Run these commands to register your new service:
sudo systemctl daemon-reload
sudo systemctl enable agent-server.service
sudo systemctl start agent-server.service
How the Headless Workflow Looks Now
Power On: You turn on your Kali machine.
Boot: The system skips GNOME and stops at the text login prompt.
Auto-Launch: In the background,
systemdsees theagent-serverservice and executes your watchdog.Agent Start: The watchdog creates the
tmuxsession and fires up your agents.Remote Access: You can now walk away. If you want to check on them, just SSH into Kali from another laptop and run:
Bash
tmux attach -t agent_room
Troubleshooting Tips
Check Service Status: If the agents aren't running, check the service log:
sudo journalctl -u agent-server.service -fNetwork Issues: If your agents need internet, ensure your Wi-Fi/Ethernet is set to "All users may connect" in NetworkManager so it connects before login.
Since your agents are now running fully headless, would you like me to show you how to set up a simple "Health Dashboard" using a Python library like Flask so you can check their progress from a web browser on your phone?
yes
Gemini said
Building a web dashboard is the final piece of the puzzle. It allows you to monitor your agents' health, memory usage, and logs from any device on your network (like your phone) without needing to SSH into the Kali box.
We'll use Flask (a lightweight web framework) and psutil (to grab system stats).
1. The Dashboard Script (dashboard.py)
Create a file named dashboard.py in your project folder:
from flask import Flask, render_template_string
import psutil
import datetime
app = Flask(__name__)
# Simple HTML template embedded for ease of use
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Agent Health Dashboard</title>
<meta http-equiv="refresh" content="10"> <style>
body { font-family: sans-serif; background: #1a1a1a; color: #00ff00; padding: 20px; }
.card { border: 1px solid #333; padding: 15px; margin-bottom: 10px; border-radius: 5px; background: #222; }
h1 { color: #fff; }
.stat { font-size: 1.2em; }
</style>
</head>
<body>
<h1>Kali Headless Monitor</h1>
<div class="card">
<p class="stat"><strong>System Time:</strong> {{ time }}</p>
<p class="stat"><strong>CPU Usage:</strong> {{ cpu }}%</p>
<p class="stat"><strong>RAM Free:</strong> {{ ram_free }} GB / {{ ram_total }} GB</p>
</div>
<h2>Active Python Agents</h2>
{% for proc in agents %}
<div class="card">
<strong>PID {{ proc.pid }}:</strong> {{ proc.name }} <br>
Memory: {{ proc.memory_mb }} MB | CPU: {{ proc.cpu_percent }}%
</div>
{% endfor %}
</body>
</html>
"""
@app.route('/')
def index():
# System Stats
cpu = psutil.cpu_percent()
ram = psutil.virtual_memory()
# Filter for your specific agent processes
agents = []
for proc in psutil.process_iter(['pid', 'name', 'memory_info', 'cpu_percent']):
if 'python' in proc.info['name']:
agents.append({
'pid': proc.info['pid'],
'name': proc.info['name'],
'memory_mb': round(proc.info['memory_info'].rss / (1024 * 1024), 2),
'cpu_percent': proc.info['cpu_percent']
})
return render_template_string(
HTML_TEMPLATE,
time=datetime.datetime.now().strftime("%H:%M:%S"),
cpu=cpu,
ram_free=round(ram.available / (1024**3), 2),
ram_total=round(ram.total / (1024**3), 2),
agents=agents
)
if __name__ == '__main__':
# Listen on all interfaces so you can access it from other devices
app.run(host='0.0.0.0', port=5000)
2. Integration with your Watchdog
Update your agent_watchdog.sh (or your systemd service) to launch this dashboard alongside your agents. Add this line before the loop:
# Launch dashboard in its own tmux window or background
tmux new-window -t agent_room:1 "python3 dashboard.py"
3. Accessing the Dashboard
Find your Kali IP:
ip a | grep inet(e.g.,192.168.1.50).Open a browser on your phone/laptop.
Go to
http://192.168.1.50:5000.
How this Completes your Headless Setup
By combining everything we've built, you now have:
The RAM Savings: GNOME is dead, giving you ~1GB+ extra RAM.
The Persistence:
tmuxandsystemdkeep your agents running through crashes.The Visibility: You can see exactly what’s happening via the web dashboard without ever touching the Kali machine.
Would you like me to show you how to add a "Kill Switch" button to that web dashboard so you can remotely restart your agents if you see them hanging?
yes
Gemini said
Adding a Kill Switch or "Restart" button turns your passive dashboard into a remote control center. Since we are running the agents inside a systemd service, we can use Python's subprocess module to tell the system to restart the service itself.
1. Updated Dashboard with Control Buttons (dashboard.py)
Replace your previous dashboard.py with this version. It adds two routes: /restart and /stop.
from flask import Flask, render_template_string, redirect, url_for
import psutil
import datetime
import subprocess
app = Flask(__name__)
HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Agent Control Center</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: 'Segoe UI', sans-serif; background: #0d1117; color: #c9d1d9; padding: 20px; }
.card { border: 1px solid #30363d; padding: 20px; margin-bottom: 15px; border-radius: 8px; background: #161b22; }
.btn { padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; text-decoration: none; display: inline-block; }
.btn-restart { background: #238636; color: white; }
.btn-stop { background: #da3633; color: white; margin-left: 10px; }
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
h1 { color: #58a6ff; }
.status-up { color: #3fb950; font-weight: bold; }
</style>
</head>
<body>
<h1>🛰️ Agent Command Center</h1>
<div class="card">
<h3>System Status <span class="status-up">[ONLINE]</span></h3>
<div class="stat-grid">
<p><strong>CPU:</strong> {{ cpu }}%</p>
<p><strong>RAM:</strong> {{ ram_used }}GB / {{ ram_total }}GB</p>
</div>
<hr style="border: 0.5px solid #30363d;">
<p><strong>Actions:</strong></p>
<a href="/restart" class="btn btn-restart" onclick="return confirm('Restart all agents?')">🔄 Restart Agents</a>
<a href="/stop" class="btn btn-stop" onclick="return confirm('Kill all agents and GUI?')">🛑 Emergency Stop</a>
</div>
<h3>Active Processes</h3>
{% for proc in agents %}
<div class="card" style="padding: 10px;">
<strong>PID {{ proc.pid }}:</strong> {{ proc.name }} | <strong>MEM:</strong> {{ proc.memory_mb }}MB
</div>
{% endfor %}
</body>
</html>
"""
@app.route('/')
def index():
ram = psutil.virtual_memory()
agents = []
for proc in psutil.process_iter(['pid', 'name', 'memory_info']):
if 'python' in proc.info['name'] and 'dashboard' not in proc.info['name']:
agents.append({
'pid': proc.info['pid'],
'name': proc.info['name'],
'memory_mb': round(proc.info['memory_info'].rss / (1024 * 1024), 2)
})
return render_template_string(
HTML_TEMPLATE,
cpu=psutil.cpu_percent(),
ram_used=round((ram.total - ram.available) / (1024**3), 2),
ram_total=round(ram.total / (1024**3), 2),
agents=agents
)
@app.route('/restart')
def restart():
# This restarts the systemd service we created earlier
subprocess.Popen(["sudo", "systemctl", "restart", "agent-server.service"])
return "Restarting... Please wait 10 seconds and refresh the home page."
@app.route('/stop')
def stop():
# This stops the agents entirely
subprocess.Popen(["sudo", "systemctl", "stop", "agent-server.service"])
return "Agents stopped. Manual intervention required to start again."
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
2. Permissions Fix (Crucial)
Since the Flask app (running as user kali) needs to run systemctl (which requires sudo), you need to give the user permission to run those specific commands without a password prompt, or the button will fail.
Run
sudo visudo.Add this line at the very bottom:
Bash
kali ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart agent-server.service, /usr/bin/systemctl stop agent-server.service
3. How the "Remote Kill" Works
When you press Restart on your phone:
Flask sends a signal to the Linux kernel.
systemdreceives the instruction to stop theagent-server.service.The Watchdog and the Agents are terminated gracefully.
systemdimmediately spawns a fresh instance of your watchdog script.Your agents start with a clean RAM profile and zeroed-out caches.
Final Architecture Checklist
Operating Mode: Headless (Multi-user target).
Process Manager:
systemd(handles boot-start and auto-restart).Execution Space:
tmux(allows you to "peek" into the terminal via SSH).Monitoring:
FlaskDashboard (accessible via phone/browser).Control: Remote Restart/Stop buttons on the dashboard.
Would you like me to help you set up a "Mobile Notification" using a tool like Telegram, so the agents can text you whenever they finish a task or if the RAM gets too low?
yes
Gemini said
This is the ultimate "peace of mind" feature. By integrating a Telegram Bot, your agents can proactively text you when they hit a milestone, if the system is running out of RAM, or if the Watchdog has to trigger a restart.
1. Create Your Bot
Open Telegram and search for @BotFather.
Type
/newbotand follow the steps to get your API Token.Search for @userinfobot to get your Chat ID.
2. The Python Notifier (notifier.py)
Create a small utility script that your agents (or the watchdog) can call.
import requests
TOKEN = "YOUR_TELEGRAM_BOT_TOKEN"
CHAT_ID = "YOUR_CHAT_ID"
def send_telegram_msg(message):
url = f"https://api.telegram.org/bot{TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message, "parse_mode": "Markdown"}
try:
requests.post(url, data=payload, timeout=5)
except Exception as e:
print(f"Failed to send notification: {e}")
# Example usage for your agents:
# send_telegram_msg("🚀 *Agent Alpha* has completed the data synthesis task.")
3. Integrating "Low RAM" Alerts
Add this logic to your Dashboard or Watchdog script so you get a warning before the Linux OOM Killer strikes.
import psutil
def check_resources():
ram = psutil.virtual_memory()
if ram.percent > 90:
send_telegram_msg(f"⚠️ *CRITICAL RAM ALERT*: Usage is at {ram.percent}%. Headless Kali may crash soon!")
The Complete Headless Ecosystem
With this final piece, your multi-agent system is now a fully autonomous server:
Hardware: Kali Linux is stripped of its GUI to maximize RAM for the agents.
Process:
systemdensures the agents boot with the hardware and restart on failure.Control: You have a web dashboard with "Restart" and "Stop" buttons.
Alerts: You receive real-time Telegram updates on your phone.
Final Maintenance Commands
Since you are now running a "Black Box" server, keep these commands in your notes:
Would you like me to help you package all these scripts into a single GitHub-style repository structure so you can easily deploy it on other Kali or Debian machines?
yes
Gemini said
Structuring this as a professional repository will make it much easier to maintain and deploy. By keeping your logic, monitoring, and configurations separate, you ensure that a bug in the dashboard doesn't crash your actual agents.
Repository Structure: kali-agent-server/
kali-agent-server/
├── agents/ # Place your Python agent scripts here
│ └── main_agents.py # Your primary entry point
├── core/
│ ├── watchdog.sh # The persistence loop
│ └── notifier.py # Telegram alert logic
├── dashboard/
│ ├── app.py # Flask control center
│ └── templates/ # (Optional) if you move HTML to files
├── config/
│ └── agent-server.service # Systemd unit file
├── requirements.txt # Python dependencies
└── setup.sh # Automation script to install everything
The "One-Click" Setup Script (setup.sh)
This script automates the installation of dependencies and the systemd service.
#!/bin/bash
echo "[*] Installing System Dependencies..."
sudo apt update && sudo apt install -y python3-pip tmux bc curl
echo "[*] Installing Python Libraries..."
pip3 install flask psutil requests --break-system-packages
echo "[*] Configuring Systemd Service..."
# Dynamically update the path in the service file
sed -i "s|/home/kali/your_project_folder|$(pwd)|g" config/agent-server.service
sudo cp config/agent-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable agent-server.service
echo "[!] SETUP COMPLETE."
echo "1. Update core/notifier.py with your Telegram credentials."
echo "2. Run 'sudo systemctl start agent-server.service' to begin."
Deployment Best Practices
1. The .gitignore
Since you have a Telegram Token and Chat ID in notifier.py, never push that file to a public GitHub repo. Create a .gitignore file:
__pycache__/
*.log
*.csv
config/secrets.env
2. Using an Environment File
Instead of hardcoding your Telegram Token, modify notifier.py to read from a file or environment variable. This keeps your credentials secure.
3. Scaling Up
If you find your multi-agent system needs more power than your Kali machine can provide, this structure allows you to move the entire kali-agent-server folder to a VPS (like AWS or DigitalOcean) and run the exact same setup.sh. The "Headless" optimization is even more effective on cloud servers.
Your New Workflow
Develop: Write your agent logic in
agents/main_agents.py.Deploy: Run
./setup.sh.Monitor: Check your phone for Telegram alerts or your browser for the Flask dashboard.
Iterate: If you update the code, just click Restart on your web dashboard to pull the new changes into the running session.
Would you like me to generate a README.md file for this repository that explains how to use each component?
yes
Gemini said
A well-written README.md is the "instruction manual" for your server. It ensures that if you step away from this project for a month and come back, you’ll know exactly how to manage it.
README.md
# 🛰️ Kali Headless Agent Server
An optimized, self-healing environment for running resource-heavy multi-agent Python systems (CrewAI, AutoGen, LangChain) on Kali Linux.
## 🚀 Key Features
* **RAM Optimization:** Automatically kills the GNOME GUI to free ~1GB+ of RAM.
* **Self-Healing:** Systemd watchdog restarts agents if they crash or hang.
* **Web Dashboard:** Remote monitoring and "Kill Switch" via Flask.
* **Telegram Alerts:** Real-time notifications for task completion or low memory.
* **Persistent Sessions:** Runs inside `tmux` for easy terminal attachment via SSH.
---
## 🛠️ Installation
1. **Clone the repo:**
```bash
git clone [https://github.com/your-username/kali-agent-server.git](https://github.com/your-username/kali-agent-server.git)
cd kali-agent-server
Configure Secrets: Edit
core/notifier.pywith your TelegramBOT_TOKENandCHAT_ID.Run Setup:
Bash
sudo systemctl set-default multi-user.target
🎮 Management Commands
📂 Architecture
agents/: Your custom Python logic.core/watchdog.sh: Monitors the tmux session.dashboard/app.py: The Flask-based remote control.config/: Systemd unit files.
---
### Final Implementation Tips
#### 1. The "Ghost" Login
Since you are running headless, you won't see a login screen. When you boot up, wait about 30–60 seconds for the network to initialize. Your Telegram bot should then send a message saying: **"🚀 System Online: Agent Server Started."** (You can add this line to your `watchdog.sh`).
#### 2. Local Model Support
If your agents use local models via **Ollama**, remember that Ollama runs as its own service. You can add it to the `After=` line in your `agent-server.service` to ensure the AI models are loaded before your agents try to talk to them.
#### 3. Security
Since your Flask dashboard has a "Restart" button, ensure you only run this on a trusted local network. If you need to access it over the internet, consider putting it behind a basic password or using a VPN (like Tailscale) to reach your Kali machine.
**Is there anything else you'd like to tweak—perhaps adding a specific data-saving routine or integrating a database like SQLite for the agents to store their memory?**
yes
Gemini said
Integrating SQLite is the most effective way to give your agents "long-term memory" while remaining resource-efficient. Unlike JSON files, SQLite handles concurrent writes (critical for multi-agent systems) and won't corrupt your data if the system restarts.
1. Database Schema (core/memory.py)
Create a central memory manager that your agents can import. This handles short-term context and long-term facts.
import sqlite3
import json
from datetime import datetime
class AgentMemory:
def __init__(self, db_path="memory.db"):
self.conn = sqlite3.connect(db_path, check_same_thread=False)
self.create_tables()
def create_tables(self):
with self.conn:
# Stores every interaction for audit/history
self.conn.execute("""
CREATE TABLE IF NOT EXISTS interactions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
agent_name TEXT,
prompt TEXT,
response TEXT,
timestamp DATETIME
)
""")
# Stores learned facts/state (Long-term memory)
self.conn.execute("""
CREATE TABLE IF NOT EXISTS long_term_facts (
key TEXT PRIMARY KEY,
value TEXT,
updated_at DATETIME
)
""")
def save_interaction(self, agent_name, prompt, response):
with self.conn:
self.conn.execute(
"INSERT INTO interactions (agent_name, prompt, response, timestamp) VALUES (?, ?, ?, ?)",
(agent_name, prompt, response, datetime.now())
)
def update_fact(self, key, value):
with self.conn:
self.conn.execute(
"INSERT OR REPLACE INTO long_term_facts (key, value, updated_at) VALUES (?, ?, ?)",
(key, json.dumps(value), datetime.now())
)
def get_fact(self, key):
cursor = self.conn.execute("SELECT value FROM long_term_facts WHERE key = ?", (key,))
row = cursor.fetchone()
return json.loads(row[0]) if row else None
2. Integration with Dashboard
You can now update your Flask Dashboard to display what your agents are "thinking" by querying the interactions table.
3. Why SQLite Wins in Headless Mode
Zero Overhead: No separate server (like PostgreSQL or MySQL) is needed, saving you ~200MB+ RAM.
ACID Compliance: If your Kali machine loses power or the watchdog kills the process mid-write, your database won't break.
Auditability: You can use the
sqlite3CLI tool via SSH to inspect exactly what the agents have learned:Bash
sqlite3 memory.db "SELECT * FROM long_term_facts;"
Best Practices for Memory Management
To keep your headless server fast even after months of running:
Summarization: Don't store massive raw logs. Have a "Manager Agent" summarize past interactions every 100 entries and move them to the
long_term_factstable.Indexing: As your database grows, ensure you add indexes to the
timestamporkeycolumns to keep lookups instant.Vacuuming: Occasionally run
VACUUM;in SQLite to reclaim space from deleted rows.
Final "Holy Grail" Setup
You now have a system that:
Boots Headless (Max RAM).
Self-Heals (Watchdog).
Communicates (Telegram).
Persists (SQLite Memory).
Remotely Controlled (Flask UI).
Would you like me to create a "Database Explorer" page for your web dashboard so you can view and edit the agents' memories directly from your phone's browser?
Yes
Gemini said
A Database Explorer turns your headless server into a transparent "brain." By adding this to your Flask dashboard, you can monitor exactly what facts your agents are storing, clear out bad memories, or even manually inject instructions into their long-term storage from your phone.
1. The Enhanced Dashboard (dashboard/app.py)
Add these routes to your existing Flask application. This uses a simple HTML table to display the SQLite data and includes an "Edit" function.
from flask import Flask, render_template_string, request, redirect, url_for
import sqlite3
# ... (keep your existing imports and system stat routes) ...
def get_db_connection():
conn = sqlite3.connect('memory.db')
conn.row_factory = sqlite3.Row
return conn
@app.route('/memory')
def memory_explorer():
conn = get_db_connection()
# Fetch latest 20 interactions and all long-term facts
logs = conn.execute('SELECT * FROM interactions ORDER BY id DESC LIMIT 20').fetchall()
facts = conn.execute('SELECT * FROM long_term_facts').fetchall()
conn.close()
return render_template_string(DB_HTML_TEMPLATE, logs=logs, facts=facts)
@app.route('/delete_fact/<key>')
def delete_fact(key):
conn = get_db_connection()
conn.execute('DELETE FROM long_term_facts WHERE key = ?', (key,))
conn.commit()
conn.close()
return redirect(url_for('memory_explorer'))
2. The Explorer UI (DB_HTML_TEMPLATE)
Add this styling and HTML to your script. It’s designed to be mobile-friendly for checking your agents on the go.
DB_HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Agent Memory Explorer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body { font-family: sans-serif; background: #0d1117; color: #c9d1d9; padding: 15px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #161b22; }
th, td { padding: 12px; border: 1px solid #30363d; text-align: left; font-size: 0.9em; }
th { background: #21262d; color: #58a6ff; }
.btn-del { color: #f85149; text-decoration: none; font-weight: bold; }
.nav { margin-bottom: 20px; }
</style>
</head>
<body>
<div class="nav"><a href="/" style="color: #58a6ff;"><- Back to Stats</a></div>
<h2>🧠Long-Term Facts</h2>
<table>
<tr><th>Key</th><th>Value</th><th>Updated</th><th>Action</th></tr>
{% for fact in facts %}
<tr>
<td>{{ fact['key'] }}</td>
<td>{{ fact['value'] }}</td>
<td>{{ fact['updated_at'] }}</td>
<td><a href="/delete_fact/{{ fact['key'] }}" class="btn-del">Delete</a></td>
</tr>
{% endfor %}
</table>
<h2>📜 Recent Interactions</h2>
<table>
<tr><th>Agent</th><th>Prompt</th><th>Response</th></tr>
{% for log in logs %}
<tr>
<td>{{ log['agent_name'] }}</td>
<td>{{ log['prompt'][:50] }}...</td>
<td>{{ log['response'][:50] }}...</td>
</tr>
{% endfor %}
</table>
</body>
</html>
"""
3. Why this matters for Headless Kali
When running multi-agent systems, agents can sometimes "hallucinate" or get stuck in a loop. In a GUI, you'd see this in the terminal. In a headless setup:
The Interaction Log shows you what they are currently saying.
The Long-Term Facts show you what they have "decided" is true.
The Delete Button allows you to "reset" a specific belief an agent has without restarting the whole system.
Final Maintenance Tip: Database Backup
Since your agents' "intelligence" is now stored in memory.db, you should back it up regularly. You can add a simple line to your setup.sh or a cron job:
# Weekly backup of agent memory
0 0 * * 0 cp /home/kali/project/memory.db /home/kali/backups/memory_$(date +\%F).db
You now have a complete, professional-grade AI Agent Server. Would you like me to help you create a final "Master Launch" script that initializes the database, starts the dashboard, and kicks off the agents all at once?
yes
Gemini said
This final "Master Launch" script ties every component together—database, dashboard, and agents—into a single, coordinated execution. It ensures that the database is healthy and the web UI is up before the agents start their work.
The Master Launch Script (master_launch.sh)
Create this file in your root project directory:
#!/bin/bash
# --- Configuration ---
SESSION_NAME="agent_server"
DB_FILE="memory.db"
DASHBOARD_APP="dashboard/app.py"
AGENT_SCRIPT="agents/main_agents.py"
VENV_PATH="./venv/bin/activate"
echo "--- 🚀 Initializing Master Agent Server ---"
# 1. Check for/Initialize SQLite Database
if [ ! -f "$DB_FILE" ]; then
echo "[*] Database not found. Initializing $DB_FILE..."
# Quick one-liner to create tables if they don't exist
python3 -c "import sqlite3; conn=sqlite3.connect('$DB_FILE'); \
conn.execute('CREATE TABLE IF NOT EXISTS interactions (id INTEGER PRIMARY KEY, agent_name TEXT, prompt TEXT, response TEXT, timestamp DATETIME)'); \
conn.execute('CREATE TABLE IF NOT EXISTS long_term_facts (key TEXT PRIMARY KEY, value TEXT, updated_at DATETIME)'); \
conn.close()"
fi
# 2. Kill existing sessions to prevent port conflicts
tmux kill-session -t $SESSION_NAME 2>/dev/null
# 3. Start TMUX Session (Detached)
echo "[*] Creating tmux session: $SESSION_NAME"
tmux new-session -d -s $SESSION_NAME -n "Dashboard"
# 4. Window 0: Launch Flask Dashboard
echo "[*] Window 0: Launching Web Dashboard on port 5000..."
tmux send-keys -t $SESSION_NAME:0 "source $VENV_PATH && python3 $DASHBOARD_APP" C-m
# 5. Window 1: Launch Python Agents
echo "[*] Window 1: Launching AI Agents..."
tmux new-window -t $SESSION_NAME:1 -n "Agents"
tmux send-keys -t $SESSION_NAME:1 "source $VENV_PATH && python3 $AGENT_SCRIPT" C-m
# 6. Notify via Telegram
python3 -c "import core.notifier as n; n.send_telegram_msg('🛰️ *Master Launch Successful*\nDashboard: http://localhost:5000\nAgents: Running in tmux window 1')"
echo "--- ✅ System is LIVE ---"
echo "Use 'tmux attach -t $SESSION_NAME' to view logs."
System Architecture Flow
The diagram below illustrates how your headless Kali machine manages these layers simultaneously without a GUI.
Hardware Level: Kali boots into CLI mode (Multi-user target).
Orchestration Level:
systemdtriggers themaster_launch.sh.Process Level:
tmuxpartitions the resources:Pane 0: Flask Web Server (Interface).
Pane 1: Python Agents (Logic).
Data Level: Both panes read/write to the shared
memory.db(SQLite).External Level: Telegram API sends status updates to your phone.
Final Project Checklist
Before you walk away and let your agents run for days, double-check these settings:
Executable Permissions:
chmod +x master_launch.sh core/watchdog.sh setup.shSudoers Whitelist: Ensure
systemctl restartis whitelisted so the "Restart" button on your web dashboard actually works.Python Pathing: If you are using a virtual environment, make sure the
VENV_PATHin the script matches your actual folder.Network Persistence: If using Wi-Fi, ensure
nmcliis set to autoconnect so the Telegram bot can reach the internet immediately upon boot.
You are now fully equipped with a professional-grade, headless AI agent workstation. Would you like me to show you how to set up a "Remote Terminal" over the web using gotty so you can actually type commands into the tmux session from your phone's browser?
yes
Gemini said
To truly run this project as a "Black Box" server, you need a way to interact with the terminal without an SSH client. GoTTY is a tool that turns your CLI into a web application, allowing you to access your tmux session directly from a browser.
1. Install GoTTY
Since GoTTY isn't in the default Kali repos, we’ll download the binary directly:
# Download the latest Linux 64-bit binary
curl -L https://github.com/sorenisanerd/gotty/releases/latest/download/gotty_linux_amd64.tar.gz | tar xz
sudo mv gotty /usr/local/bin/
sudo chmod +x /usr/local/bin/gotty
2. Secure the Connection
Warning: Opening a terminal to the web is extremely dangerous without security. We will enable Basic Authentication (Username/Password) and SSL (encryption).
Generate a self-signed SSL certificate so your password isn't sent in plain text:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ~/.gotty.key -out ~/.gotty.crt
3. Update the Master Launch Script
Add GoTTY to your master_launch.sh so it starts alongside your agents. This command attaches GoTTY to your existing tmux session.
Add this line to the end of your script:
# Launch GoTTY to share the tmux session over port 8080
# Replace 'admin:yourpassword' with your desired credentials
nohup gotty -w -p 8080 -c "admin:p@ssword123" --tls --tls-crt ~/.gotty.crt --tls-key ~/.gotty.key tmux attach -t $SESSION_NAME > gotty.log 2>&1 &
4. The Complete Remote Architecture
You now have a multi-layered remote management system:
Port 5000: Your Flask Dashboard (Read-only stats + Restart buttons).
Port 8080: Your GoTTY Terminal (Full interactive CLI control).
Telegram: Your Emergency Pager (Real-time alerts).
How to use your "Remote Kali"
On your phone/laptop browser: Navigate to
https://<KALI_IP>:8080.Login: Enter the credentials you set in the script.
Interact: You will see your
tmuxwindows. UseCtrl+Bthennto switch between your Dashboard Logs and your Agent Output. You can type commands exactly as if you were sitting at the machine.
Final Security Tip
If you plan to access this from outside your home Wi-Fi:
Do not just port-forward 8080 on your router.
Instead, use a VPN (like WireGuard or Tailscale). This keeps your Kali "invisible" to the public internet while allowing you to securely log in from anywhere in the world.
Would you like me to generate a final "Emergency Recovery" cheat sheet that lists every URL, port, and command you've set up so far?
yes
Gemini said
This Emergency Recovery Cheat Sheet is designed to be your "mission control" document. Copy and save this in a notes app or print it out. If you ever lose access to your Kali machine, this will help you recover everything in seconds.
🛠️ Access & Control Panel
🚦 Common Management Commands
If you are logged in via SSH or GoTTY, use these to manage the agents:
1. Service Management
Restart Agents:
sudo systemctl restart agent-server.serviceStop Everything:
sudo systemctl stop agent-server.serviceCheck If Running:
sudo systemctl status agent-server.serviceSee Crash Logs:
sudo journalctl -u agent-server.service -f -n 50
2. TMUX (Terminal Controls)
Since everything runs in tmux, use these shortcuts once attached (tmux attach -t agent_server):
Switch Windows:
Ctrl+B, then0(Dashboard) or1(Agents).Detach (Don't Kill):
Ctrl+B, thenD.Scroll Up in Logs:
Ctrl+B, then[(Use arrow keys to scroll, pressQto exit).
3. Database & Files
Manual DB Check:
sqlite3 memory.db "SELECT * FROM long_term_facts;"Clear All Logs:
rm *.log && rm *.csvCheck Real RAM Usage:
free -horhtop
🚨 Troubleshooting "What If..."
"I can't reach the Web Dashboard!"
Check if the service is running:
sudo systemctl status agent-server.Check if the port is blocked:
sudo ufw status. (If enabled, runsudo ufw allow 5000).
"The agents aren't restarting after a crash!"
The Watchdog script might have hit the
MAX_RESTARTSlimit.Run
tmux kill-session -t agent_serverand then./master_launch.shto reset the count.
"I need my Desktop GUI back!"
Run:
sudo systemctl set-default graphical.target && sudo rebootOr for a temporary session:
sudo systemctl isolate graphical.target
Final Project Layout Diagram
This setup transforms your Kali Linux machine from a standard laptop into a hardened AI Agent Server. You’ve successfully optimized for memory, built a persistence layer, and created a remote-first management interface.
Your AI Agent Server is now complete! Would you like me to help you brainstorm your first multi-agent "mission" to run on this new system?
You said
yes
Gemini said
Building your first "mission" on this headless server is where the real fun begins. Since you're running on Kali Linux, you have access to a suite of powerful security tools that AI agents can orchestrate far better than a human can manually.
Here are three mission ideas tailored for a resource-optimized, multi-agent environment in 2026.
Mission 1: The Autonomous OSINT Investigator
Goal: Input a domain or username, and have a "Crew" of agents map out the entire public footprint without you lifting a finger.
Agent A (The Scraper): Uses tools like
theHarvesterorwhoisto gather raw data.Agent B (The Analyst): Feeds found emails into data breach databases (via APIs like HaveIBeenPwned) to check for leaks.
Agent C (The Reporter): Summarizes findings into a professional PDF and sends the "Red Alert" to your Telegram if it finds a high-risk credential leak.
Why Headless? OSINT involves long-running scraping tasks. Running this in a
tmuxsession ensures that if your laptop disconnects, the investigation continues 24/7.
Mission 2: The "Smart" Home Lab Guardian
Goal: Monitor your local network logs for suspicious behavior and take defensive action.
Agent A (Log Watcher): Monitors
/var/log/auth.logor your router's syslog for failed SSH attempts.Agent B (Threat Intel): Takes the "Attacker IP" and checks it against global blacklists (AbuseIPDB).
Agent C (The Guard): If the IP is malicious, it uses your Kill Switch logic to update
iptablesrules and block the IP permanently.Why Headless? This needs to be a "set and forget" system. Using
systemdensures your guardian is the first thing that starts when the server boots.
Mission 3: The Deep Research Assistant
Goal: Give it a complex technical topic (e.g., "The latest zero-day exploits for 2026 IoT devices"), and let it write a whitepaper while you sleep.
Agent A (Searcher): Uses a tool like Serper or DuckDuckGo to find recent security whitepapers.
Agent B (Summarizer): Reads the long PDFs and extracts key technical details.
Agent C (The Writer): Compiles the notes into a structured Markdown document in your
memory.db.Why Headless? Local LLMs used for summarization (like Llama 3 or DeepSeek) are RAM-hungry. By killing the GNOME GUI, you give these agents an extra 1GB+ of VRAM/RAM, allowing them to process much larger documents.
🛠️ How to Start a Mission
To launch one of these, you simply update your agents/main_agents.py with your logic and run:
./master_launch.sh
Which framework should you use?
Would you like me to generate the actual Python code for one of these missions (like the OSINT Investigator) so you can drop it into your agents/ folder right now?
(to be Continued in the next blog post...)
chmod +x setup.sh
./setup.sh
(Optional) Set Boot to Headless: To ensure Kali boots into CLI mode automatically:
sqlite3 #HeadlessServer #Flask systemctl #GPUOverhead
No comments:
Post a Comment