Ollama GNOME System Tray Panel 260401
Adding an Ollama System Tray Control to GNOME (Ubuntu)
Overview
When using Ollama locally, large language models (LLMs) are loaded directly into your GPU's VRAM for fast processing. However, Ollama keeps these models "hot" in memory for a period of time after you finish chatting. If you are running heavy models (like a 7B or 8B parameter model), this can easily consume 5GB+ of VRAM, leaving little room for gaming, video editing, or other GPU-intensive tasks.
Instead of repeatedly opening a terminal to run systemctl commands to kill the service, you can create a lightweight GNOME panel application (system tray icon). This utility provides a simple, two-click visual interface to start and stop the Ollama background service, immediately freeing up your VRAM when needed.
Features
- One-Click Controls: Start or stop the Ollama systemd service directly from the top panel.
- Visual Status: The icon dynamically changes to show whether Ollama is currently running (
▶) or stopped (⏸). - Asynchronous Execution: Uses background threading so password prompts (
pkexec) do not freeze your desktop environment. - Auto-Polling: Detects if Ollama was started or stopped from a terminal and updates the panel icon automatically.
Installation
Step 1: Install Prerequisites
You will need the Python bindings for GTK3 and AppIndicator to allow the script to integrate with the GNOME top panel.
Open your terminal and run:
sudo apt update
sudo apt install python3-gi python3-gi-cairo gir1.2-appindicator3-0.1
Step 2: Create the Python Script
Create a new Python file in a permanent location, such as your home directory or a dedicated scripts folder.
nano ~/ollama-panel.py
Paste the following code into the file:
#!/usr/bin/env python3
import gi
import subprocess
import threading
# Require the necessary GTK and AppIndicator versions
gi.require_version('Gtk', '3.0')
gi.require_version('AppIndicator3', '0.1')
from gi.repository import Gtk, AppIndicator3, GLib
class OllamaIndicator:
def __init__(self):
# Initialize with a placeholder icon; it will update immediately
self.indicator = AppIndicator3.Indicator.new(
"ollama_indicator",
"system-run",
AppIndicator3.IndicatorCategory.APPLICATION_STATUS
)
self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
self.menu = Gtk.Menu()
# Start Button
self.start_item = Gtk.MenuItem(label='▶ Start Ollama')
self.start_item.connect('activate', lambda _: self.run_systemctl('start'))
self.menu.append(self.start_item)
# Stop Button
self.stop_item = Gtk.MenuItem(label='⏹ Stop Ollama')
self.stop_item.connect('activate', lambda _: self.run_systemctl('stop'))
self.menu.append(self.stop_item)
self.menu.append(Gtk.SeparatorMenuItem())
# Quit Button
quit_item = Gtk.MenuItem(label='Quit Panel App')
quit_item.connect('activate', Gtk.main_quit)
self.menu.append(quit_item)
self.menu.show_all()
self.indicator.set_menu(self.menu)
# Run an initial status check
self.update_status()
# Poll systemctl every 3 seconds to catch external changes
GLib.timeout_add_seconds(3, self.update_status)
def get_ollama_status(self):
# Suppress errors/output so it fails gracefully if cancelled
result = subprocess.run(
["systemctl", "is-active", "ollama"],
capture_output=True, text=True
)
return result.stdout.strip() == "active"
def update_status(self):
active = self.get_ollama_status()
if active:
self.indicator.set_icon_full("media-playback-start", "Ollama is running")
self.start_item.set_sensitive(False)
self.stop_item.set_sensitive(True)
else:
self.indicator.set_icon_full("media-playback-pause", "Ollama is stopped")
self.start_item.set_sensitive(True)
self.stop_item.set_sensitive(False)
return True # Returning True keeps the GLib timer running
def run_systemctl(self, command):
def execute():
# Run the command and wait for it to finish (or be cancelled)
subprocess.run(["pkexec", "systemctl", command, "ollama"])
# Schedule a UI update on the main GTK thread once done
GLib.idle_add(self.update_status)
# Fire in a background thread so the polkit prompt doesn't freeze the panel
threading.Thread(target=execute, daemon=True).start()
def main():
app = OllamaIndicator()
Gtk.main()
if __name__ == "__main__":
main()
Save the file and exit your text editor.
Step 3: Make the Script Executable
Grant the script permission to run as an executable program:
chmod +x ~/ollama-panel.py
You can test it immediately by running python3 ~/ollama-panel.py. An icon should appear in your top-right system tray.
Optional: Configure Passwordless Toggling
By default, clicking "Start" or "Stop" will bring up a graphical prompt asking for your sudo password. If you want to bypass this for convenience:
- Open the sudoers editor safely:
sudo visudo
- Add this line to the very bottom of the file (replace
your_usernamewith your actual Ubuntu username):
your_username ALL=(ALL) NOPASSWD: /bin/systemctl start ollama, /bin/systemctl stop ollama
- Save and exit.
- Open
~/ollama-panel.pyand change thesubprocess.runline inside theexecute()function from"pkexec"to"sudo":
subprocess.run(["sudo", "systemctl", command, "ollama"])
Setting Up Autostart (Run on Boot)
To ensure the control panel is always available when you log in:
- Open the Startup Applications tool from your Ubuntu application menu.
- Click Add.
- Fill in the fields:
- Name: Ollama Control Panel
- Command:
/usr/bin/python3 /home/YOUR_USERNAME/ollama-panel.py— ensure you use the absolute path to your script - Comment: System tray toggle for the Ollama service.
- Click Save.