Shellbox

Shellbox is a library for remote command execution, and a server for secure command execution. It was primarily implemented to sandbox lilypond (used by the Score extension) and provide a way for MediaWiki to utilize external binaries without needing them to be in the same container. Shellbox relies on Kubernetes (and Linux containers/namespaces) to provide isolation and resource limits for external commands.
Documentation for integration in MediaWiki is available at mw:Shellbox, operational aspects are here on Wikitech.
Note: As of early 2025, production Shellbox is in the process of migrating to PHP 8.1. More details and current status can be found in .
== Architecture ==
Requests come into an Apache httpd container, which contains the Shellbox secret key as a configmap. The request is passed onto a php-fpm container, which contains the Shellbox code and necessary binaries. Once the request is authenticated, Shellbox executes the command as the www-data user. The response is then sent back. Yeah.
MediaWiki talks to Shellbox over a local envoyproxy.
== Shellboxes ==
We currently have five Shellboxes in active use:
* shellbox: for Score, with lilypond, ghostscript, fluidsynth, lame and noto fonts installed
**Available internally at https://shellbox.discovery.wmnet:4008 and http://localhost:6024 on appservers
**T281423: New Service Request Shellbox
* shellbox-constraints: for Wikidata constraint regex checking, with only PHP installed using the RPC interface
**Available internally at https://shellbox-constraints.discovery.wmnet:4010 and http://localhost:6025 on appservers
**T285104: Deploy Shellbox instance (shellbox-constraints) for Wikidata constraint regexes
*shellbox-media: for DjVU (in core), PdfHandler, and PagedTiffHandler
**Available internally at https://shellbox-media.discovery.wmnet:4015 and http://localhost:6026 on appservers
**T289228: Convert media handling code (PdfHandler, PagedTiffHandler) to use Shellbox
*shellbox-syntaxhighlight: for SyntaxHighlight, with pygments installed
**Available internally at https://shellbox-syntaxhighlight.discovery.wmnet:4014 and http://localhost:6027 on appservers
**T289227: Convert SyntaxHighlight to use Shellbox
*shellbox-timeline: for EasyTimeline, with librsvg, perl, ploticus and various fonts installed
**Available internally at https://shellbox-timeline.discovery.wmnet:4012 and http://localhost:6028 on appservers
**T289226: Convert EasyTimeline extension to use Shellbox
*shellbox-video: for transcoding video - used by mw-videoscaler
**T356241: Move video transcoding to use Shellbox
== Monitoring ==
* Primary Shellbox dashboard, supports all deployed Shellboxes.
* MediaWiki Shellouts dashboard, metrics recorded by MediaWiki
Shellbox provides a /healthz endpoint that can be used to quickly check if the service is up, e.g.:
user@host$ curl https://shellbox.discovery.wmnet:4008/healthz
{
 "__": "Shellbox running",
 "pid": 10782
}
All other requests are harder to externally construct since they need to be signed with the Shellbox secret key.
Bugs should be reported/tracked in #Shellbox on Phabricator.
=== Logs ===
All logs from httpd and php-fpm should end up in logstash. You can filter for a specific Shellbox deployment with kubernetes.namespace_name:"shellbox-constraints". The actual log text is under the field log (not message like MediaWiki). The httpd access logs that are HTTP 200 are dropped because of the volume and minimal likelihood they'll be useful. 
All Shellbox invocations should still be logged under MediaWiki's exec log channel too.
== Deploying a new version ==
After a patch to Shellbox is merged, new image versions are automatically built via the postmerge jobs (trigger-)shellbox-pipeline-publish;
the new image versions should show up in the Wikimedia Docker registry within ca. 30 minutes.
To deploy the new image version to production:
# Change the value of shellbox.version in helmfile.d/services/shellbox/global.yaml in the deployment-charts repository
# Deploy each version of shellbox following the general deployment guidelines. If you want a quick way to cycle through them, once you've tested how they perform on staging:
cd /srv/deployment-charts/helmfile.d/services
# Change the DC according to your needs
DC=codfw
for deployment in shellbox*; do
 echo "#### Doing $deployment"
 sleep 5
 pushd $deployment
 helmfile -e $DC -i apply --context 5
 popd
done
Note: While the production migration to PHP 8.1 is in progress, you may see two helmfile releases per Shellbox deployment: main and migration. The latter is temporary and will be turned down when the migration completes. More details can be found in .
== Smoke test ==
Quick verification that the containers are at least running:
cd /srv/deployment-charts/helmfile.d/services
# Change the DC according to your needs
DC=staging
for deployment in shellbox*; do
 echo "#### Checking $deployment in $DC"
 kube_env $deployment $DC
 curl https://staging.svc.eqiad.wmnet:$(kubectl get service shellbox-main-tls-service -o jsonpath='{.spec.ports[0].nodePort}')
done
This curl call is expected to return a JSON payload describing an error processing the request because no action was encoded in the URL.
{
 "__": "Shellbox server error",
 "class": "Shellbox\\ShellboxError",
 "message": "No action was specified",
 "log": [
 {
 "level": 400,
 "message": "Exception of class Shellbox\\ShellboxError: No action was specified",
 "context": {
 "trace": "#0 /srv/app/src/Server.php(72): Shellbox\\Server->guardedExecute('/srv/app/config...')\n#1 /srv/app/src/Server.php(61): Shellbox\\Server->execute('/srv/app/config...')\n#2 /srv/app/index.php(3): Shellbox\\Server::main('/srv/app/config...')\n#3 {main}"
 }
 }
 ]
}
== Source code ==
* mediawiki/libs/Shellbox
* Helm chart
Category:SRE Service Operations
Category:Services