AuthonAuthon Blog
debugging7 min read

How to Fix the Headless Server Debugging Nightmare with Cockpit

Fix the fragmented SSH debugging workflow on headless Linux servers by setting up Cockpit, a lightweight web-based management interface.

AW
Alan West
Authon Team
How to Fix the Headless Server Debugging Nightmare with Cockpit

If you've ever SSH'd into a production server at 2 AM, frantically switching between htop, journalctl, df -h, and systemctl status across four terminal panes trying to figure out why everything is on fire — yeah, me too. Last month I had a server that kept running out of disk space, OOM-killing random processes, and dropping network connections, all at the same time. Trying to correlate those issues through pure CLI was like debugging with a blindfold on.

That experience finally pushed me to set up Cockpit, and I genuinely wish I'd done it years ago.

The actual problem: fragmented server visibility

Here's what typically happens when something goes wrong on a headless Linux box:

  • You SSH in and run top or htop to check CPU/memory
  • You open another session for journalctl -f to watch logs
  • Another tab for df -h and du to hunt disk usage
  • Maybe another for ss -tulnp or systemctl commands
  • You lose track of which tab has what, miss a critical log line, and start over
  • The root cause isn't that these tools are bad — they're great. The problem is context switching. When you're troubleshooting a cascading failure, you need to see CPU, memory, disk, network, and logs at the same time. Terminal multiplexers like tmux help, but they don't give you the correlated, real-time view you actually need.

    What Cockpit actually is (and isn't)

    Cockpit is a lightweight, web-based interface for Linux servers that uses your system's existing APIs. It's not some bloated monitoring platform that needs its own database. It runs as a systemd service, authenticates against your system's PAM stack, and shows you what's happening in real time through a browser.

    The key thing that sold me: it doesn't replace your existing tools or configs. Changes you make in Cockpit are the same changes you'd make via CLI. Edit a network config in Cockpit, and the underlying NetworkManager files update. It's a UI layer on top of the real thing, not a parallel universe.

    Step-by-step: getting Cockpit running

    Installation is almost suspiciously easy. On most modern distros, it's already in the default repos.

    On Debian/Ubuntu:

    bash
    # Install the base package and a few useful modules
    sudo apt update
    sudo apt install cockpit cockpit-storaged cockpit-networkmanager
    
    # Start and enable the socket (not the service — Cockpit is socket-activated)
    sudo systemctl enable --now cockpit.socket

    On Fedora/RHEL/CentOS:

    bash
    # Usually pre-installed on Fedora Server, but just in case
    sudo dnf install cockpit cockpit-storaged
    
    sudo systemctl enable --now cockpit.socket
    
    # Open the firewall port
    sudo firewall-cmd --permanent --add-service=cockpit
    sudo firewall-cmd --reload

    Now hit https://your-server-ip:9090 in a browser and log in with your regular system credentials.

    The gotcha that trips everyone up: firewall and port issues

    If you install Cockpit and can't reach the web UI, nine times out of ten it's one of these:

    Problem 1: Firewall blocking port 9090
    bash
    # Check if the port is actually listening
    sudo ss -tulnp | grep 9090
    
    # If it's listening but unreachable, check your firewall
    sudo iptables -L -n | grep 9090
    # Or for firewalld:
    sudo firewall-cmd --list-all
    
    # For UFW (Ubuntu):
    sudo ufw allow 9090/tcp
    sudo ufw reload
    Problem 2: cockpit.socket not actually running

    A common mistake is starting cockpit.service instead of cockpit.socket. Cockpit uses socket activation — it only spins up when someone connects. If the socket isn't active, nothing listens on 9090.

    bash
    # This is what you want to see
    sudo systemctl status cockpit.socket
    # Should show: Active: active (listening)
    
    # If it's not running:
    sudo systemctl restart cockpit.socket
    
    # Check the journal for errors if it fails
    journalctl -u cockpit.socket -u cockpit.service --since "10 min ago"
    Problem 3: Self-signed certificate warnings

    Cockpit generates a self-signed cert on first run. Your browser will scream about it. For a server on your local network, you can accept the risk. For anything internet-facing, you'll want to drop a real certificate in:

    bash
    # Cockpit looks for certs in /etc/cockpit/ws-certs.d/
    # Place your cert and key in a single combined .cert file
    sudo cat /path/to/fullchain.pem /path/to/privkey.pem > \
      /etc/cockpit/ws-certs.d/my-server.cert
    
    # Restart the service to pick up the new cert
    sudo systemctl restart cockpit.socket

    Using Cockpit to actually debug things

    Once you're in, here's the workflow that replaced my four-terminal chaos:

    • Overview page: CPU, memory, disk I/O, and network graphs all on one screen. I spotted my disk space issue immediately because I could see the I/O spike correlated with a runaway log rotation.
    • Logs section: Filters by priority, service, and time range. Way faster than piping journalctl through grep when you're panicking.
    • Services panel: Start, stop, restart, and read the status of any systemd unit. You can see which services are in a failed state at a glance instead of running systemctl --failed.
    • Terminal: Yes, there's a built-in terminal. So when you do need to drop to CLI, you don't have to leave the browser.

    The multi-server trick

    This is the feature that really levels things up. Cockpit can manage multiple servers from a single dashboard:

    bash
    # On the secondary server, install cockpit normally
    sudo apt install cockpit
    sudo systemctl enable --now cockpit.socket
    
    # On your primary Cockpit server, install the machines module
    sudo apt install cockpit-machines

    Then in the Cockpit UI, click your username in the top right and "Add new host." It uses SSH under the hood, so as long as you can SSH between the boxes, it works. No special agent software, no tokens to manage.

    When Cockpit isn't the answer

    I want to be honest about the tradeoffs. Cockpit is great for interactive debugging and day-to-day management of a handful of servers. It's not a replacement for:

    • Proper monitoring and alerting — You still need something like Prometheus and Grafana for historical data, dashboards, and alert rules. Cockpit shows you what's happening now, not what happened at 3 AM last Tuesday.
    • Configuration management at scale — If you're managing 50+ servers, you need Ansible or similar, not a web UI.
    • Centralized logging — Cockpit shows logs per-machine. For a fleet, you'll want a log aggregation setup.

    Cockpit fills the gap between "I need to SSH in and poke around" and "I need a full observability stack." For small to medium setups — a few servers, a home lab, a small team's infrastructure — it's the sweet spot.

    Prevention: making this setup stick

    A few things I do on every new server now:

    • Install Cockpit as part of my base provisioning script, right alongside fail2ban and unattended-upgrades
    • Set up the real TLS certificate from the start so I'm not clicking through warnings
    • Add all my servers to one primary Cockpit dashboard so I have a single pane of glass
    • Keep Cockpit updated — the project ships new releases frequently and the changelog is worth reading

    The 2 AM debugging session that pushed me to set this up? With Cockpit running, it would've taken five minutes instead of forty. I would have seen the disk usage graph climbing, the OOM kills in the log stream, and the failing network service all on one screen. Instead I was grep-ing through journals like it was 2009.

    Sometimes the boring solution is the right one. Cockpit isn't flashy, but it solves a real problem that most of us have been putting up with for way too long.

    How to Fix the Headless Server Debugging Nightmare with Cockpit | Authon Blog