Hermes is a high-performance, sandboxed code execution engine written in Rust.
It runs untrusted and potentially hostile code inside strictly isolated environments ensuring safety, predictability, and high throughput.
Fully upgraded with cgroups v2 support for enforcing better resource limits.
Designed for judge platforms, coding sandboxes, and auto-eval services, Hermes provides on-demand execution of arbitrary code through a simple REST API. Version 2 introduces native Docker compatibility, eliminating host kernel configuration headaches by utilizing a custom split-cgroup architecture to strictly enforce resource limits.
The easiest and safest way to run Hermes Engine is via Docker.
The provided Dockerfile handles all system dependencies, compilers, and the Isolate sandbox engine.
- Docker installed on the host machine.
git clone https://github.com/Ryuga/Hermes.git
cd HermesCreate a .env file in the root directory:
HOST=0.0.0.0
PORT=8000
ALLOWED_ORIGIN=https://your_frontend_domain_to_allow_cors.com
API_TOKEN=your_api_token_for_allowing_authdocker build -t hermes-engine .Note: Because Hermes manages a strict cgroups v2 hierarchy internally to track memory and CPU limits, you must use the following flags to grant the container a private, unhindered cgroup namespace.
docker run -d \
--name hermes \
--privileged \
--cgroupns=private \
--tmpfs /sys/fs/cgroup \
-p 8000:8000 \
hermes-engineThe application will be live at http://127.0.0.1:8000.
Validate by running curl http://127.0.0.1:8000, which should return UP!.
If you prefer not to use Docker, you can run Hermes directly on a Linux server.
While
isolatestrictly enforces resource limits and prevents file system modifications, it requires read-only bind mounts to system directories (/lib,/usr,/etc) to provide the necessary runtimes for languages like Python and Java. Running Hermes directly on a bare-metal host means untrusted code may be able to read sensitive host system details.For production, deploying via Docker is strongly recommended
- Linux server with
cgroups v2enabled - Rust toolchain installed
- Isolate installed (
apt-get install isolate) - Compilers/Runtimes installed (Python, Node, GCC, OpenJDK, etc.)
- Nginx installed (for production proxying)
git clone https://github.com/Ryuga/Hermes.git
cd Hermes
cargo build --releaseBinary will be output to: target/release/Hermes
HOST=127.0.0.1
PORT=8000
ALLOWED_ORIGIN=https://your_frontend_domain_for_cors.comEnsure your Axum bind address in the Rust code matches the config:
TcpListener::bind("127.0.0.1:8000")Create the service file:
sudo nano /etc/systemd/system/hermes.service[Unit]
Description=Hermes Engine
After=network.target
[Service]
User=root
WorkingDirectory=/path/to/your/project/root
ExecStart=/path/to/your/project/root/target/release/Hermes
Restart=always
Environment=RUST_LOG=info
[Install]
WantedBy=multi-user.target(Note: Isolate generally requires root privileges to initialize sandboxes. If running as a non-root user, ensure Isolate is properly configured with SUID).
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable hermes
sudo systemctl start hermessudo nano /etc/nginx/sites-available/hermesserver {
listen 443 ssl;
server_name api.hermes.domain;
ssl_certificate /etc/nginx/certs/origin.crt;
ssl_certificate_key /etc/nginx/certs/origin.key;
location / {
proxy_pass http://127.0.0.1:8000;
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-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}Enable site and restart Nginx:
sudo ln -s /etc/nginx/sites-available/hermes /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginxExecute user code in a sandboxed environment. Currently supports:
- Python
- C++
- JavaScript
- Java
POST /executeHeaders
Content-Type: application/jsonBody
{
"language": "python",
"code": "print(1+1)"
}{
"code": 0,
"output": "2\n",
"std_log": ""
}Fields
code→ exit code (0= success, non-zero = runtime error / timeout)output→ program stdoutstd_log→ error output / logs (ifDEBUG=trueor compilation fails)
curl -X POST http://127.0.0.1:8000/execute/ \
-H "Content-Type: application/json" \
-d '{"language":"python","code":"print(1+1)"}'To execute single file, send a POST request to the /execute/ endpoint.
Endpoint: POST /execute/
Payload Example:
{
"language": "python",
"code":"print(1+1)"
}To execute multiple files, send a POST request to the /v2/execute/ endpoint. You must define an entry_file to specify which file the interpreter should run first.
Endpoint: POST /v2/execute/
Payload Example:
{
"language": "python",
"files": [
{
"name": "main.py",
"content": "import test\nprint('Running main.py')"
},
{
"name": "test.py",
"content": "print('Imported test.py')"
}
],
"entry_file": "main.py"
}Response:
{
"stdout": "Imported test.py\nRunning main.py",
"stderr": "",
"exit_code": 0
}- Runtime - Discord bot for code execution.
- Tortoise Community - Online Code Execution Tool.
- Tortoise-BOT - Discord code execution functionality.