Troubleshooting
In case you're experiencing problems with using ShellHub Self-Hosted, you can troubleshoot and trace possible errors by using the methods given below.
ShellHub is made of several docker containers, each one being a potential cause for failure. Having an even basic overview of ShellHub's technical architecture can help you understand what is going on. You can refer to the technical architecture for that.
View Docker containers log
Viewing the Docker containers log is the very first approach when troubleshooting issues. The critical information in the log can quickly help you find the root causes of most issues.
To view all logs from all ShellHub containers, run the following command:
./bin/docker-compose logs
You can also see the logs of each service by running:
docker-compose logs <SERVICE>
Refer to the official docker-compose logs command documentation.
Frequently Encountered Issues
Here is a list of solutions to some frequently encountered issues. If this page doesn't help you solve your problem, try doing a search on GitHub Issues.
Cannot start service ssh
Cannot start service ssh: driver failed programming external connectivity on endpoint shellhub_ssh_1: Error starting userland proxy: listen tcp 0.0.0.0:22: bind: address already in use
If you have getting the error message above when starting up the server using docker-compose you have two options to solve this issue:
- Change the OpenSSH daemon port from 22 to whatever on your host machine;
- Change the default SSH gateway port of ShellHub by setting
SHELLHUB_SSH_PORTvariable inside the configuration file.
Cannot start gateway
Cannot start service gateway: driver failed programming external connectivity on endpoint shellhub_gateway_1: Error starting userland proxy: listen tcp 0.0.0.0:80: listen: address already in use
If you get the error message above, then check you have no other running process using the port 80 with the following command:
sudo lsof -i -P -n | grep :80
If so, kill the service, for example, if apache2 is running:
sudo systemctl stop apache2
And disable it from autostart:
sudo update-rc.d apache2 disable
SSH session disconnects immediately in a Proxmox unprivileged LXC
ssh-1 | ... "error":"failed to read the message from socket ... use of closed network connection" ...
On the agent side you may also see:
inappropriate ioctl for device
nsenter: reassociate to namespace 'ns/time' failed: Operation not permitted
If the SSH connection drops the moment authentication completes — and the agent
runs inside an unprivileged LXC container on Proxmox VE — the agent can't
allocate a pseudo-terminal (PTY) for the interactive shell. Unprivileged LXC maps
the container's root to an unprivileged host user, which restricts both PTY
allocation (/dev/ptmx, devpts) and joining the host's namespaces. There are two
cases, depending on how you run the agent.
Not sure which agent you're running? If you installed with the one-line
install.sh script you're on the standalone agent — start with the standalone
steps below. The Docker agent is the one you deploy as a container with
--pid=host.
Standalone (native) agent
The native agent only needs a working PTY inside its own container. Most of the
time the blocker is a leftover devpts or /dev/shm entry in the container's
/etc/fstab (common in older container templates), which breaks /dev/pts on
modern LXC.
- Inside the container, remove any stale
devpts/tmpfs /dev/shmlines from/etc/fstab. - Confirm
/dev/ptmxis openable —ls -l /dev/ptmxshould not show000permissions, and/dev/ptsshould be mounted withgid=5,mode=620. - Restart the container and reconnect.
If sessions still report PTY allocation request failed, raise the PTY limit in the
container config at /etc/pve/lxc/<id>.conf on the Proxmox host:
lxc.pty.max: 1024
lxc.tty.max: 4
The time namespace only affects CLOCK_MONOTONIC/uptime — not wall-clock time — so
the nsenter: ... ns/time ... Operation not permitted line on its own does not
break a standalone shell. It only matters for the Docker agent below.
Docker agent
The Docker agent enters the host's namespaces (via nsenter against PID 1) so the
shell lands on the host rather than inside the agent container. An unprivileged LXC
can't grant the capabilities this needs — joining the host's time namespace
fails with Operation not permitted, and Docker-in-LXC also requires extra
features to run at all.
On the Proxmox host, edit /etc/pve/lxc/<id>.conf:
features: nesting=1,keyctl=1
nesting=1 exposes the procfs/sysfs that Docker needs; keyctl=1 allows the
keyctl() syscall used by containerd. These are required for any Docker
workload in an unprivileged container.
That gets Docker running, but entering the host's namespaces from an unprivileged
container hits a hard capability ceiling that no features flag lifts. If you need
the Docker agent, run it in a privileged LXC container or a VM instead:
# Make the container privileged (Proxmox host)
pct set <id> --unprivileged 0
A privileged LXC container is not a security boundary — Proxmox treats it as roughly equivalent to host access. For untrusted workloads, prefer a VM, where the agent (standalone or Docker) works without any of these tweaks.