Skip to content

stefan-500/remote-execution-service

Repository files navigation

Remote Shell Command Execution Service

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.

Features

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

Tech Stack

  • Java 21
  • Spring Boot
  • Gradle
  • Flyway
  • Docker
  • PostgreSQL

Project structure

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 handling
  • domain/model: execution entity and execution status enum
  • repository/: Spring Data repository contract
  • service/: execution creation and lookup orchestration

Architecture

Sequence Diagram

This diagram shows the flow of submitting an execution request, provisioning the executor, running the command, updating status, and retrieving results.

Sequence Diagram

Component Diagram

This diagram shows the main system components and their interactions.

Component Diagram

State Diagram

This diagram shows the lifecycle of an execution.
Possible states: QUEUED, PROVISIONING, IN_PROGRESS, FINISHED, FAILED.

State Diagram

PROVISIONING is a internally used state.

Execution Entity

This is the database model/table for storing executions.

Executions Entity Diagram

Getting Started

Prerequisites

  • Java 21
  • Docker
  • Docker Compose

Quick start

1. If Java 21 is not available install it:

Windows (from Powershell):

winget install Oracle.JDK.21

Linux (Debian/Ubuntu):

apt update
apt install openjdk-21-jdk

Mac (Homebrew):

brew install openjdk@21
# Attach to system 
sudo ln -sfn /usr/local/opt/openjdk@21/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-21.jdk

2. 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 -d

4. Run build and tests:
This might take a few minutes.

Linux/Mac:

# /remote-execution-service
./gradlew build

Windows:

# /remote-execution-service
gradlew build

5. Run the Spring Boot application:

Linux/Mac:

# /remote-execution-service
./gradlew bootRun

Windows:

# /remote-execution-service
gradlew bootRun

Wait 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.

REST API

The base URL is http://localhost:8081.

1. POST /executions

Submits a new execution request.
The request returns immediately, while the execution continues in the background.

Parameters:

  • script: the shell script for execution
  • cpuCount: 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

Example (cURL):

Request:

# /remote-execution-service
curl -H "Content-Type: application/json" -X POST http://localhost:8081/executions -d @docs/post_payload_example.json

Contents 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.

2. GET /executions/{id}

Retrieves the current execution details.

Description:

  • Returns the current execution status
  • Returns execution result data if available

Example (cURL):

Request:

curl http://localhost:8081/executions/23d9a0a0-6a61-4061-8955-9424d310b37b

Response:

{
  "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"
}

Future implementation ideas

  • 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.).

Author

Stefan Vujović, 2026.

About

Remote shell command execution service

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages