This is a simple service for executing shell commands on a remote executor.
The service accepts a command script, provisions a remote executor with requested resources (e.g., CPU count), executes the script, and returns the execution status.
Quick links: Architecture | Startup guide | API docs | Some ideas
Implemented functionalities:
- submit a shell script for execution
- specify executor resources, such as CPU count
- retrieve the execution status
- provision a new remote executor for each request
- wait for executor initialization
- execute the script remotely
- persist execution metadata and results
- Java 21
- Spring Boot
- Gradle
- Flyway
- Docker
- PostgreSQL
remote-execution-service/
├── gradle/
│ └── wrapper/
├── docs/
│ └── diagrams/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── io/
│ │ │ └── github/
│ │ │ └── stefan500/
│ │ │ └── remoteexecutionservice/
│ │ │ ├── api/
│ │ │ ├── domain/
│ │ │ │ └── model/
│ │ │ ├── exception/
│ │ │ ├── repository/
│ │ │ └── service/
│ │ └── resources/
│ │ └── db/
│ │ └── migration/
│ └── test/
│ └── java/
│ └── io/
│ └── github/
│ └── stefan500/
│ └── remoteexecutionservice/
│ ├── api/
│ │ ├── controller/
│ │ └── dto/
│ ├── service/
│ └── manager/
└── README.md
api/: controllers, DTOs, and web error handlingdomain/model: execution entity and execution status enumrepository/: Spring Data repository contractservice/: execution creation and lookup orchestration
This diagram shows the flow of submitting an execution request, provisioning the executor, running the command, updating status, and retrieving results.
This diagram shows the main system components and their interactions.
This diagram shows the lifecycle of an execution.
Possible states: QUEUED, PROVISIONING, IN_PROGRESS, FINISHED, FAILED.
PROVISIONING is a internally used state.
This is the database model/table for storing executions.
- Java 21
- Docker
- Docker Compose
1. If Java 21 is not available install it:
Windows (from Powershell):
winget install Oracle.JDK.21Linux (Debian/Ubuntu):
apt update
apt install openjdk-21-jdkMac (Homebrew):
brew install openjdk@21
# Attach to system
sudo ln -sfn /usr/local/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-21.jdk2. Copy .env.example to .env.
Define the prefered docker remote executor container image in .env (REMOTE_EXECUTION_DOCKER_IMAGE).
The default fallback docker image is debian:bookworm-slim, as defined in src/main/resources/application.yml.
3. Run Docker containers:
# /remote-execution-service
docker compose up -d4. Run build and tests:
This might take a few minutes.
Linux/Mac:
# /remote-execution-service
./gradlew buildWindows:
# /remote-execution-service
gradlew build5. Run the Spring Boot application:
Linux/Mac:
# /remote-execution-service
./gradlew bootRunWindows:
# /remote-execution-service
gradlew bootRunWait two minutes for the service to initialize.
6. Using cURL/Postman or similar, run the create and retrieve execution commands, as shown in next REST API examples.
The base URL is http://localhost:8081.
Submits a new execution request.
The request returns immediately, while the execution continues in the background.
Parameters:
script: the shell script for executioncpuCount: the number of CPUs that the remote executor allocates.
Minimum cpuCount is 1, maximum is 8.
Description:
- Creates a new execution
- Stores the execution request in the database
- Starts asynchronous processing
- Returns the generated execution ID and status
Request:
# /remote-execution-service
curl -H "Content-Type: application/json" -X POST http://localhost:8081/executions -d @docs/post_payload_example.jsonContents of docs/post_payload_example.json:
{
// The request parameters
"script": "uname -a",
"cpuCount": 8
}Response:
{
"executionId": "23d9a0a0-6a61-4061-8955-9424d310b37b",
"status": "QUEUED"
}Use GET /executions/{id} to poll the execution status.
Retrieves the current execution details.
Description:
- Returns the current execution status
- Returns execution result data if available
Request:
curl http://localhost:8081/executions/23d9a0a0-6a61-4061-8955-9424d310b37bResponse:
{
"executionId":"23d9a0a0-6a61-4061-8955-9424d310b37b",
"status":"FINISHED",
"exitCode":0,
"stdout":"Linux cd6157165589 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64 GNU/Linux\n",
"stderr":"",
"createdAt":"2026-03-14T12:00:47.130902Z",
"startedAt":"2026-03-14T12:00:47.578276Z",
"finishedAt":"2026-03-14T12:00:47.756597Z"
}- Implement API user authorization.
- Create new API endpoints, e. g. for listing the user's previous executed commands.
- Implement comprehensive logs for remote executor statistics, user statistics, environment management, etc.
- Add a Cloud based remote executor provider (AWS, GCP, Azure, etc.).
Stefan Vujović, 2026.



