How To Install Cockpit on Ubuntu 26.04 LTS

Install Cockpit on Ubuntu 26.04

Anyone who has managed a handful of servers knows the moment. A monitoring alert fires, and the quickest answer is buried in a terminal session on a box that was set up two years ago by someone who has since left. SSH is fine for that, and it always will be. But there are plenty of times when a clean browser view of services, logs, disks, network interfaces and storage saves ten minutes of command-line digging. Cockpit exists for exactly that.

Cockpit is a lightweight, web-based administration console that ships in the Ubuntu archive. It is not a control panel that takes over your server. It reads the same systemd, journald, NetworkManager or netplan, and storage APIs you already use, and it shows them in a browser. Close the tab and nothing is left running, because the service is socket-activated and only wakes up when someone connects.

Ubuntu 26.04 LTS, codename Resolute Raccoon, was released by Canonical on April 23, 2026. That makes it the LTS most new deployments will target for the next several years. This guide shows how to install Cockpit on Ubuntu 26.04 LTS properly: the package install, the firewall, certificates, reverse proxying, access control and the odd failures that show up in production. It also covers a version quirk specific to 26.04 that is worth knowing before you commit to a setup.

What Cockpit Is and When It Makes Sense

Cockpit is a server manager with a browser front end. Behind the interface, cockpit-ws handles web sessions and cockpit-bridge talks to the system on your behalf. When you log in, you are logging in as a real system user. There is no separate Cockpit account database, which is a big part of why it is easy to reason about from a security standpoint.

Where it fits well

Cockpit is a good match in a few situations:

  • Small to mid-sized fleets where a full configuration management or monitoring stack would be overkill.
  • Teammates who are comfortable with Linux but do not want to memorise journalctl flags, nmcli syntax or lvm incantations.
  • Quick triage on a misbehaving production server: check failed units, tail logs, look at disk usage and see which process is eating memory.
  • Lab and homelab setups with KVM virtual machines or Podman containers.
  • Training environments, where seeing what the system does helps people learn what the CLI does.

Where it does not fit

It will not replace Ansible, Terraform or a proper observability platform. Do not use it as a deployment tool. Treat it as a window into one machine, or a handful of machines, and it will earn its place.

Prerequisites Before You Start

Check a few things first. It saves time later.

  • A working Ubuntu 26.04 LTS installation, server or desktop. Cockpit behaves the same either way.
  • A non-root user with sudo rights. Cockpit lets you log in as root only if you deliberately allow it, and you should not.
  • Network access to the Ubuntu mirrors for apt.
  • Port 9090/TCP reachable from wherever you will manage the box, or a plan to proxy it.
  • Decent hygiene on the host: current packages, a working clock (NTP), and a hostname that actually resolves.

Confirm the release you are on:

lsb_release -a
cat /etc/os-release
uname -r

You should see Ubuntu 26.04 and the codename resolute. That codename matters later if you use backports.

Step 1: Update the System

Start from a clean base. Pulling Cockpit on top of stale package indexes is how people end up with held-back dependencies and confusing errors.

sudo apt update
sudo apt full-upgrade -y

If the kernel or systemd was upgraded, reboot before continuing. It is tempting to skip, but on a fresh server it costs thirty seconds and removes a whole category of “was it the upgrade?” doubt.

sudo reboot

Step 2: Install Cockpit on Ubuntu 26.04 LTS

Cockpit lives in the Ubuntu universe repository. On most server images that component is already enabled. If it is not, enable it first:

sudo add-apt-repository universe
sudo apt update

Now install the base package:

sudo apt install cockpit -y

Before pressing Enter, check what apt would pull in and what it would leave out:

apt policy cockpit

At the time of writing, the 26.04 archive carries Cockpit version 360. This is a point to understand. A discussion on the Cockpit project’s GitHub from late August 2026 notes that the Resolute archive was still on 360 (the April release), while Debian’s Trixie-Backports had 365 and Ubuntu’s Noble had a 362 backport. Cockpit’s own maintainers said they did not know who handles the Ubuntu backports and could not help with that. The upstream installation page says Ubuntu LTS releases get updated Cockpit through official backports, but for Resolute that was not available when that discussion happened. Check apt policy on your own system to see whether things have changed since.

Does that matter? For most people, no. Version 360 is a perfectly capable console. It only becomes a concern if you need a specific newer module or a bug fix that landed later.

Enable the socket

Cockpit uses systemd socket activation. You enable the socket, not the service:

sudo systemctl enable --now cockpit.socket

Verify:

systemctl status cockpit.socket
ss -tlnp | grep 9090

The socket listens on port 9090 and starts cockpit.service only when a client connects. That is why systemctl status cockpit.service often shows “inactive (dead)” on a healthy system. It is not broken. Nobody has knocked yet.

Step 3: Open the Firewall

Ubuntu ships with UFW installed but disabled by default. On a production machine it should be on. Do things in the right order here, because enabling UFW without allowing SSH first is a reliable way to lock yourself out of a remote server.

sudo ufw allow OpenSSH
sudo ufw allow 9090/tcp
sudo ufw enable
sudo ufw status verbose

The 9090/tcp rule is the plain approach. Cockpit also installs a UFW application profile on some releases, so sudo ufw allow cockpit can work, but check with sudo ufw app list. The numeric rule works everywhere.

Restrict by source

Opening 9090 to the whole internet is a poor idea. If you have a fixed office IP or a VPN range, restrict it:

sudo ufw delete allow 9090/tcp
sudo ufw allow from 203.0.113.0/24 to any port 9090 proto tcp

Replace the example range with your own. On AlmaLinux, Rocky or other RHEL-family systems, the equivalent is:

sudo dnf install cockpit -y
sudo systemctl enable --now cockpit.socket
sudo firewall-cmd --permanent --add-service=cockpit
sudo firewall-cmd --reload

On Debian, the install is sudo apt install cockpit, with the backports option when you want a newer build.

Step 4: Log In to the Web Console

Open a browser and visit:

https://your-server-ip:9090

Note the https. Cockpit generates a self-signed certificate on first start, so every browser will warn you about it. For a first look that is fine. Accept the warning, then sign in with an existing system user.

After login, you will see a limited-access banner. Click Turn on administrative access and re-enter your sudo password. Cockpit uses this model deliberately. You browse as a normal user and elevate only when you need to change something, which mirrors how sudo works at the shell.

If you are working from Yogyakarta, Jakarta or anywhere with a higher-latency path to a cloud region, expect the first page load to feel slower than SSH. The console is JavaScript-heavy at startup. Once loaded, interaction is quick.

Step 5: Install the Add-On Modules

The base package gives you system overview, logs, services, networking, accounts, terminal and software updates. Extra modules add depth. Install only what you will actually use.

sudo apt install -y cockpit-storaged cockpit-networkmanager cockpit-packagekit cockpit-sosreport

Optional extras:

sudo apt install -y cockpit-podman cockpit-machines cockpit-pcp

What each one does:

Module Purpose Typical use
cockpit-storaged Disks, LVM, RAID, NFS, partitions Adding a data disk, checking SMART status
cockpit-networkmanager Network interface management Bonding, VLANs, static addresses
cockpit-packagekit Software updates from the UI Applying security patches
cockpit-podman Container management Running and inspecting Podman containers
cockpit-machines KVM/libvirt virtual machines Lab VMs, test environments
cockpit-pcp Historical performance metrics Looking back at a CPU spike
cockpit-sosreport Diagnostic report generation Support tickets

Do not install everything out of habit. Each module is more code, more attack surface and more to patch.

A note on networking on Ubuntu Server

Ubuntu Server uses netplan with systemd-networkd by default, while Cockpit’s network page works best with NetworkManager. This is the most common source of confusion. If the Networking page shows interfaces as “unmanaged” or refuses to edit them, that is why.

Switching the renderer on a remote production server is risky. A typo can drop the machine off the network. For a remote host, leave netplan alone and use Cockpit only to view network state. If you are on a local VM or console-accessible machine, you can switch the renderer in /etc/netplan/*.yaml:

network:
  version: 2
  renderer: NetworkManager

Test with sudo netplan try, which rolls back automatically if you lose connectivity.

Step 6: Replace the Self-Signed Certificate

A permanent browser warning teaches people to click through warnings. That is a bad habit on a server console. Fix it.

Cockpit loads certificates from /etc/cockpit/ws-certs.d/. It uses the file that sorts last alphabetically with a .cert extension. The default self-signed one is 0-self-signed.cert, so any file with a higher-sorting name wins.

Using Let’s Encrypt

This assumes a public DNS name pointing at the server, and port 80 temporarily reachable.

sudo apt install certbot -y
sudo certbot certonly --standalone -d cockpit.example.com

Then copy the certificate chain and the key into the Cockpit directory as separate files with the same base name:

sudo cp /etc/letsencrypt/live/cockpit.example.com/fullchain.pem /etc/cockpit/ws-certs.d/50-letsencrypt.cert
sudo cp /etc/letsencrypt/live/cockpit.example.com/privkey.pem /etc/cockpit/ws-certs.d/50-letsencrypt.key
sudo chgrp cockpit-ws /etc/cockpit/ws-certs.d/50-letsencrypt.key
sudo chmod 640 /etc/cockpit/ws-certs.d/50-letsencrypt.key
sudo systemctl restart cockpit

Check which one is active:

openssl s_client -connect cockpit.example.com:9090 -servername cockpit.example.com </dev/null 2>/dev/null | openssl x509 -noout -issuer -dates

Renewal hook

Let’s Encrypt certificates last 90 days. Copying files manually once and forgetting is how a Cockpit login page starts showing an expired certificate three months later. Add a deploy hook:

sudo tee /etc/letsencrypt/renewal-hooks/deploy/cockpit.sh > /dev/null <<'EOF'
#!/bin/bash
D=/etc/letsencrypt/live/cockpit.example.com
cp "$D/fullchain.pem" /etc/cockpit/ws-certs.d/50-letsencrypt.cert
cp "$D/privkey.pem"  /etc/cockpit/ws-certs.d/50-letsencrypt.key
chgrp cockpit-ws /etc/cockpit/ws-certs.d/50-letsencrypt.key
chmod 640 /etc/cockpit/ws-certs.d/50-letsencrypt.key
systemctl restart cockpit
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/cockpit.sh

Test it with sudo certbot renew --dry-run.

Internal servers without public DNS can use a private CA or a DNS-01 challenge. The principle stays the same: drop a matching .cert and .key pair into the directory and restart.

Step 7: Configure Cockpit Behaviour

Settings live in /etc/cockpit/cockpit.conf. The file does not exist by default. Create it.

[WebService]
Origins = https://cockpit.example.com:9090 wss://cockpit.example.com:9090
ProtocolHeader = X-Forwarded-Proto
AllowUnencrypted = false
LoginTitle = Production Web Node 03

[Session]
IdleTimeout = 15
Banner = /etc/cockpit/issue.cockpit

[Log]
Fatal = criticals warnings

What matters here:

  • IdleTimeout is in minutes. Fifteen is reasonable. An open admin console on an unattended laptop is a real risk.
  • LoginTitle is more useful than it sounds. When you have six tabs open to six different servers, a custom title keeps you from running a restart on the wrong one.
  • Origins is required when you proxy Cockpit or use a hostname different from what the server sees. Omitting it produces a blank page or WebSocket errors.
  • Banner shows a legal notice before login, useful for compliance.

Apply changes:

sudo systemctl restart cockpit

Changing the listening port

Port 9090 is well known, and scanners probe it. Changing it is not security, but it does cut noise in your logs. Override the socket unit:

sudo systemctl edit cockpit.socket

Add:

[Socket]
ListenStream=
ListenStream=9443

The empty ListenStream= line clears the default. Without it you end up listening on both ports. Then:

sudo systemctl daemon-reload
sudo systemctl restart cockpit.socket
sudo ufw allow 9443/tcp
sudo ufw delete allow 9090/tcp

Binding only to a private interface is better still:

[Socket]
ListenStream=
ListenStream=10.0.0.5:9090

If the machine has a WireGuard or private network address, this makes Cockpit unreachable from the public interface entirely. For internet-facing servers, this is the pattern worth using.

Running Cockpit Behind Nginx

Plenty of teams already terminate TLS at Nginx. Proxying Cockpit is possible, but the WebSocket handling trips people up.

First tell Cockpit that plain HTTP is acceptable from the proxy and which origin to expect:

[WebService]
Origins = https://cockpit.example.com
ProtocolHeader = X-Forwarded-Proto
AllowUnencrypted = true

Only use AllowUnencrypted = true when Cockpit is bound to localhost, so the plain HTTP leg never leaves the machine. Bind the socket to 127.0.0.1:9090 with the override from the previous section.

Then the Nginx server block:

server {
    listen 443 ssl http2;
    server_name cockpit.example.com;

    ssl_certificate     /etc/letsencrypt/live/cockpit.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cockpit.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_buffering off;
        gzip off;
    }
}

Test and reload:

sudo nginx -t && sudo systemctl reload nginx

The Upgrade and Connection headers are not optional. Without them the login page loads, then the terminal and live graphs fail silently. Also set proxy_read_timeout 3600s; if people leave terminal sessions open. The default 60 seconds will drop idle WebSocket connections.

A bonus of proxying: Nginx can add IP allowlists, basic auth as a second gate, rate limiting and extra logging in front of the console.

Security Hardening

A web-based root-capable console is a high-value target. Treat it that way from day one.

Limit who can log in

Cockpit honours /etc/cockpit/disallowed-users. The default already blocks root. Verify:

cat /etc/cockpit/disallowed-users

For finer control, use PAM. Create a group and restrict access:

sudo groupadd cockpit-admins
sudo usermod -aG cockpit-admins alice

Then add a line to /etc/pam.d/cockpit above the existing auth lines:

auth required pam_succeed_if.so user ingroup cockpit-admins

Test with a second session open before you log out of the first, because a mistake here is easy to make and annoying to undo.

Use two-factor authentication

Cockpit authenticates through PAM, so a TOTP module works. Install libpam-google-authenticator, have each user run google-authenticator, then add to /etc/pam.d/cockpit:

auth required pam_google_authenticator.so

Be careful with this on shared accounts, and keep a recovery path (console or SSH key access) that does not depend on the web login.

Protect against brute force

Install fail2ban and give it a Cockpit jail. Failed logins are written to the journal with the identifier cockpit-ws.

sudo apt install fail2ban -y

Create /etc/fail2ban/filter.d/cockpit.conf:

[Definition]
failregex = pam_unix\(cockpit:auth\): authentication failure.* rhost=<HOST>
            cockpit-ws.*: couldn't authenticate.* from <HOST>
ignoreregex =

And /etc/fail2ban/jail.d/cockpit.local:

[cockpit]
enabled  = true
port     = 9090
filter   = cockpit
backend  = systemd
journalmatch = _SYSTEMD_UNIT=cockpit.service
maxretry = 4
findtime = 10m
bantime  = 1h
sudo systemctl restart fail2ban
sudo fail2ban-client status cockpit

Log formats can differ between Cockpit versions. Trigger a failed login on purpose and look at journalctl -u cockpit.service -n 20 to confirm your regex matches what is really written. Never assume.

Keep it patched

Cockpit is a network service. Turn on unattended security upgrades:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

Prefer a VPN or SSH tunnel

The safest exposure for Cockpit is none. Reach it through WireGuard, Tailscale or an SSH tunnel:

ssh -L 9090:127.0.0.1:9090 user@server

Then browse to https://localhost:9090. No firewall hole, no public listener.

Managing Multiple Servers

Cockpit can connect to other hosts over SSH from a single dashboard. On the primary server, add a host through the user menu > Add new host option. Cockpit uses SSH, so every remote machine needs cockpit-bridge available. The cockpit-system package covers that on most installs.

Use SSH keys rather than passwords. Verify host key fingerprints when prompted. And keep the number of machines sensible. Ten servers in one dashboard is convenient. A hundred is a monitoring problem that deserves a real tool.

Troubleshooting Common Problems

This is where experience pays off. Most Cockpit problems fall into a few familiar buckets.

Connection refused on port 9090

Check the basics in order:

systemctl is-enabled cockpit.socket
systemctl status cockpit.socket
ss -tlnp | grep 9090
sudo ufw status

If the socket is inactive, start it. If it is listening but unreachable remotely, the firewall or a cloud security group is blocking it. Cloud providers often have a separate network firewall in front of the instance. UFW alone will not open it.

Login fails with the correct password

Possible causes:

  • The user is listed in /etc/cockpit/disallowed-users.
  • A PAM restriction (group or 2FA) is rejecting the account.
  • The account is locked or expired. Check with sudo passwd -S username and sudo chage -l username.
  • Root login is being attempted. Use a sudo user.

Read the journal for the actual reason:

sudo journalctl -u cockpit.service -u cockpit.socket --since "10 minutes ago"

Blank page or “Disconnected” behind a proxy

Almost always the WebSocket upgrade headers or the Origins setting. Confirm both the Nginx headers and /etc/cockpit/cockpit.conf. Restart Cockpit after editing. The browser developer console will usually show a rejected WebSocket handshake.

“Your browser is not supported” or a stale interface

Hard refresh the page, or clear site data. Cockpit caches static assets aggressively, and after an upgrade the browser can mix old and new files.

Network page says interfaces are unmanaged

As covered earlier, this is the netplan and systemd-networkd versus NetworkManager mismatch. Decide deliberately whether to switch the renderer, and never do it blind on a remote machine.

Software updates page is empty or errors

The Software Updates page relies on PackageKit. Make sure it is installed and the daemon is healthy:

sudo apt install packagekit cockpit-packagekit -y
sudo systemctl restart packagekit

If apt is locked by another process (such as unattended-upgrades), PackageKit will wait or fail. Check with ps aux | grep -E 'apt|dpkg'.

Certificate not being picked up

Check file names and permissions. The .cert and .key need the same base name, and the key must be readable by the cockpit-ws group. Remember that the last alphabetical match wins. A leftover file named 99-old.cert will beat your new one.

Package version older than expected

If you see version 360 on Ubuntu 26.04 while documentation mentions newer features, you are not misconfigured. The archive version simply lags, as discussed in the Cockpit project’s GitHub thread. Check apt policy cockpit and apt-cache madison cockpit. If you truly need something newer, the options are waiting for a backport, building from upstream source in a test environment, or running a newer release in a container or VM. For production, stick with the packaged build. A slightly older, patched, supported package beats a hand-built one nobody remembers how to update.

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.

Related Posts