# Web terminal

VPS console in the browser that stays alive when you disconnect: tmux inside the server, with per-user permissions.

Source: https://ardumaker.com/en/docs/terminal-web/

- Category: Servers and infrastructure
- Status: Available
- Requirements: An active company VPS; Being a company member with access to that VPS
- MCP tools (Read only): `ver_historial_comandos_vps`, `leer_archivo_vps`
- MCP tools (Write or modify): `instalar_app`, `controlar_app`
- MCP tools (Destructive): `ejecutar_comando_vps`, `guardar_archivo_vps`

## What can you do with it?

The web terminal opens a VPS console in the browser. It is not a short-lived SSH session: it is a `tmux` server living inside the VPS, so work keeps running even if you close the tab, the network drops or the backend restarts.

- Up to 5 live terminals per person and per VPS; someone else's do not use your quota.
- Reattach to the same terminal as many times as needed.
- An admin picks the Linux user (`root` by default) and sees every terminal of the VPS; a member works with their own user and sees only theirs.
- Select and copy with the mouse like on any page, with a colored prompt and tab completion.

## When should you use it?

- Long tasks (a build, a migration, a download) you do not want to lose if the connection drops.
- Check or fix something by hand without installing an SSH client or opening port 22.
- Give console access to a member with their own Linux user, without sharing `root`.

## How does it work in ArduMaker?

When a terminal is created, the backend sends the VPS agent a script that:

1. installs `tmux` and `ncurses-term` if missing;
2. writes `/etc/ardumaker/tmux.conf` (no status bar and mouse off, so selection is done by the browser);
3. writes `/etc/ardumaker/terminal.sh` with the colored prompt and hooks it once at the end of the user's `.bashrc`;
4. creates `/run/ardumaker/tmux/<id>/` with 700 permissions for the Linux user;
5. writes the `ardu-tmux-<id>.service` unit in `/run/systemd/system/` and starts it.

The dedicated unit is what makes the terminal persistent: the VPS agent updates itself and, when it restarts, kills everything hanging from it. With its own unit (`Type=oneshot`, `RemainAfterExit=yes`, `KillMode=process`) `tmux` does not depend on the agent.

To attach, the dashboard requests a credential valid for 12 hours and opens a WebSocket with it. The credential is the key to the WebSocket, not the session: when it expires a new one is requested and you return to the same terminal.

Every time terminals are listed they are reconciled with the VPS: `tmux` is asked whether the session exists and the system `boot_id` is compared. A missing session with a different `boot_id` is `perdida_por_reinicio` (you are warned); a missing session with the same `boot_id` is a closed terminal. If the VPS does not answer, nothing is changed.

## What actually changes?

| File or unit | Purpose |
| --- | --- |
| `/etc/ardumaker/tmux.conf` | Shared tmux configuration |
| `/etc/ardumaker/terminal.sh` | Colored prompt, hooked to `.bashrc` |
| `/run/ardumaker/tmux/<id>/` | Terminal socket, only for its user |
| `ardu-tmux-<id>.service` | Unit in `/run/systemd/system/`: gone after a reboot |

Nothing closes a terminal by itself: neither disconnecting nor inactivity. Only closing it from the dashboard (or `controlar_app` with `close`) kills `tmux` and frees the slot.

## Who sees and uses each terminal

The terminal belongs to whoever created it. An admin's usually runs as `root`; if a member could attach to it they would get an administrator shell they cannot open any other way. That is why a member sees and attaches only to their own, and someone else's terminal does not exist for them (404).

| Action | Admin | Member |
| --- | --- | --- |
| Pick the Linux user | Yes (`root` by default) | No: their own |
| See terminals | All on the VPS | Only their own |
| Close | Any | Only their own |

## Diagram

**A web terminal**

```text
Browser (xterm.js in the dashboard)
  ↓
WebSocket (12-hour credential)
  ↓
ArduMaker backend (checks permissions and owner)
  ↓
VPS agent (attaches the pty)
  ↓
ardu-tmux-<id>.service (tmux server as the Linux user)
```

## Expected result

The terminal shows as `viva` in the list, with its Linux user, its owner and the last time someone attached. A `perdida_por_reinicio` terminal is still shown on purpose, to warn that work was lost; it is removed by closing it.

## Errors and troubleshooting

| Symptom | Cause |
| --- | --- |
| 409 on create | You reached the limit of 5 terminals on that VPS |
| 403 on create | A member tried to pick another Linux user: only an admin can |
| 500 on create | The VPS could not start tmux; details come in the message |
| Prompt without colors, `ls` without colors or Tab not completing | The `TERM` does not exist in the VPS terminfo database or the shell is not bash |
| A configuration change has no effect | Terminals already open keep the old one: close it and create another |

To diagnose a terminal that looks wrong, paste this inside it:

```sh
echo "TERM=$TERM"; echo "bash=${BASH_VERSION:-NO}"; echo "tmux=${TMUX:-NO}"
infocmp "$TERM" >/dev/null 2>&1 && echo "terminfo OK" || echo "terminfo FALTA"
grep -c ardumaker/terminal.sh ~/.bashrc; ls -l /etc/ardumaker/
```

> **INFO:** If you type `exit`, tmux ends even though the systemd unit still shows as active: that is why the state is asked to tmux and not to systemd.

## MCP access

An MCP agent does not attach to terminals: they belong to the people using the dashboard and nothing that runs over MCP shares state with them. It can open a terminal as an app (`instalar_app` with `app_type: terminal`, under its owner's rules) and close one (`controlar_app` with `close`; someone else's only if its owner is an admin).

To run commands, the agent uses `ejecutar_comando_vps`: one command per call, waiting 10 to 300 seconds, output trimmed to 20000 characters and the working directory remembered between calls. Commands that look destructive (`rm -rf`, `mkfs`, `shutdown`, `DROP DATABASE`…) are refused with 409 unless `confirmado=true`. Limit: 10 commands per second per VPS.

- Read: `ver_historial_comandos_vps` (what ran, who ran it and the result; kept for 30 days, with labelled secrets redacted) and `leer_archivo_vps`.
- Risky writes: `ejecutar_comando_vps` and `guardar_archivo_vps`, marked as destructive.

> **PRECAUCION:** A long job is not left in the background with `nohup … &`: it dies when the agent updates. Launch it in its own transient unit, for example `systemd-run --unit=trabajo-x --collect /bin/sh -c '…'`.

Reference at [/mcp/docs](https://ardumaker.com/en/mcp/docs) and [/mcp/vps](https://ardumaker.com/en/mcp/vps).

## Related features

- [VPS servers](https://ardumaker.com/en/docs/vps/)
- [Linux users](https://ardumaker.com/en/docs/usuarios-linux/)
- [systemd services](https://ardumaker.com/en/docs/systemd/)
- [SSH tunnels](https://ardumaker.com/en/docs/tuneles-ssh/)
- [MCP server](https://ardumaker.com/en/docs/servidor-mcp/)
