CoreCP

Tools on a server

A machine carries its roles — web, mail, dns, db, backup, ftp — and beside them it carries tools: the things your customers need in a shell but that none of the roles installs by itself. git to deploy from a repository, Composer to resolve

Written for: Administrator

A machine carries its roles — web, mail, dns, db, backup, ftp — and beside them it carries tools: the things your customers need in a shell but that none of the roles installs by itself. git to deploy from a repository, Composer to resolve PHP dependencies, WP-CLI to drive a WordPress install, imapsync to pull somebody else's mailboxes, a Node or Python series a customer's application was written against, and Redis for sessions and object caching.

Open it in the panel under Servers → the server → Quick actions → Manage tools, or reach the screen directly at /nodes/<server>/tools.

What a tool is

Three things, and nothing else:

  • a package on your own mirror,
  • a name in the server's tools: list in /etc/corecp/node.yaml,
  • and a render, which is corectl reconcile making the machine match the list.

That is why installing one is not a script that downloads something: the list is the truth, a machine rebuilt from its state file comes back with the same tools, and a tool taken off the list is really gone from the disk at the next reconcile.

root@web1:~# corectl tool list
Tools:
  on git              Git — clone and deploy from a repository
  on composer         Composer — PHP dependency manager
  on wp-cli           WP-CLI — manage a WordPress installation from the shell
  on redis            Redis — one shared instance for sessions and object caching
     imapsync         imapsync — the universal IMAP fallback for migrations
     node (22, 24)    Node.js — the two active LTS series
     python (312, 313) Python — extra series beside the distribution's
     docker           Docker — containers, single-tenant nodes only  — this node is not marked single-tenant

`on` is installed, `!` is listed in node.yaml but missing on disk.
This node is shared: docker is refused (corectl tool single-tenant on).

Two columns say two different things. Listed means the name is in node.yaml; present means the binary is on the disk. They differ for as long as one reconcile takes, and when they differ for longer than that, something on the machine needs looking at — which is what the ! marker is for.

Installing and removing

root@web1:~# corectl tool add git
tool git is available (/usr/bin/git)
git installed — /usr/bin/git

root@web1:~# corectl tool remove imapsync
tool imapsync removed
imapsync removed

Removing only removes what CoreCP installed. The machine keeps a ledger in /etc/corecp/rendered/tools.yaml of the tools this engine put there, so a git that was already on the server when CoreCP adopted it is never uninstalled by a reconcile — it was not ours to remove.

What comes with a role

Installing a role writes its own tools into node.yaml, once:

RoleTools
webgit, composer, wp-cli, redis
mailimapsync

They are a starting point, not something that grows back: a tool you remove afterwards stays removed.

Redis is deliberately one instance per server, not one per customer. An account reaches it through the PHP policy — session.save_handler and session.save_path are in the customer set — so there is no second socket to hand out and no per-account daemon to supervise.

Node and Python

These carry more than one version at a time. They install under /opt/corecp/node/<XY> and /opt/corecp/python/<XY>, exactly like the CoreCP PHP builds under /opt/corecp/php/<XY>:

root@web1:~# corectl tool add node@24
installing node@24 (corecp-node24)
tool node@24 is available (/opt/corecp/node/24/bin/node /opt/corecp/node/24/bin/npm)

root@web1:~# su - customer1 -c 'node --version && npm config get prefix'
v24.19.0
/home/customer1/.npm-global

Two Node LTS lines are active at a time. Adding the other one replaces the first: two series on the same PATH would mean node is whichever one sorted last, which is nobody's decision.

npm's global prefix and Python's user base are the customer's own home (~/.npm-global, ~/.local), set by /etc/profile.d/corecp-tools.sh. A shared global prefix on a machine with several customers would mean one account's npm install -g writes a binary every other account then runs.

Reachable inside the cage

Nothing extra is needed. The filesystem cage replaces /home, /etc/corecp and /proc and touches nothing else, so a binary under /usr/bin or /opt/corecp is visible inside a caged session by construction. What it needs is PATH, which the profile snippet above provides — including inside the cage, because the cage does not replace /etc.

Docker

Docker installs only on a server explicitly marked as carrying one customer. Its daemon runs as root and its socket is a root shell for whoever can open it, so it does not belong beside shared accounts and it is never given to an account in the cage.

root@single1:~# corectl tool add docker
error: docker may only be installed on a node marked single-tenant …

root@single1:~# corectl tool single-tenant on
node single-tenant

root@single1:~# corectl tool add docker
docker installed — /usr/bin/docker

The mark is an assertion about the machine, and the machine can contradict it: a server with more than one hosting account refuses it and names them. Taking the mark off again removes what it unlocked.

A package that is not there

On a server with the CoreCP OS mirror on (corectl update --os-mirror on), a tool whose package nobody put on a mirror list simply is not installable. The refusal says which list to add it to:

error: git could not be installed: … — check that git is on this node's mirror
(infra/build-server/packages/tools.list, then bash infra/build-server/mirror-upstream.sh)

The two runtimes are built by us rather than mirrored: infra/build-server/build-node.sh 24 --publish and infra/build-server/build-python.sh 313 --publish.

Not here

No Supervisor. Every hosting account already runs inside its own systemd slice with its own limits, and a second process manager beside it would be two places to look for one crashed worker.

No per-customer tool list. What a machine carries is an operator decision. A customer who needs a runtime the server does not have asks for it; a reseller narrows what their customers get through a package, never through the machine.