Skip to main content
This guide covers developing OASM from source: cloning the monorepo, initializing the environment, running the Console, Core API, and workers locally, managing database migrations, and the environment variables each service expects. For a production deployment, see Deployment.

Prerequisites

Before you begin, ensure you have the following installed:

Clone the repository

The repository is a monorepo with pnpm workspaces combining the Node-based services — console and core-api — alongside the Go worker.

Project Structure

  • console/ — React 19 + TanStack Router + Vite.
  • core-api/ — NestJS 11 (REST on port 6276, gRPC on port 16276).
  • worker/ — Go scanning workers (CLI and app entry points).

Initialize Developer Environment

To set up your local development environment, run the following command:
This command will:
  • Copy example environment files (.env) for core-api, console, and worker
  • Install project dependencies using npm (managed by the task for each workspace)
  • Install Go dependencies for the worker
  • Install worker security tools (nuclei, subfinder, httpx, naabu, dnsx) into worker/oasm-tools/
After running task init, you can start all services using task dev or run them individually as described below.

Running Services

All Services with Task

To start the API and Console development servers simultaneously:
This starts:
  • Core API at http://localhost:6276
  • Console at http://localhost:5173 (Vite dev server)

Core API

Or directly:
The API runs on port 6276 (base path http://localhost:6276/api) with the gRPC server on port 16276.

Console (Web Interface)

Or directly:

Workers

To run workers locally in CLI mode:
With custom parameters:
To run workers in app mode (env-driven):
See Worker for the environment variables workers consume.

Database Setup

task init does not automatically start PostgreSQL. You can either:
  1. Use Docker Compose to start PostgreSQL and Redis (both are required for local development):
  2. Use your own PostgreSQL instance and update core-api/.env accordingly.
The database uses PostgreSQL 17 with the pgvector extension for vector operations. For the full stack (including workers, geo-ip, and rustfs), run task docker-compose instead — see Using Docker Compose.

Database Migration

Database migrations are managed using TypeORM. The migration scripts are defined in core-api/taskfile.yml and can be executed using the task commands.

Run All Pending Migrations

This command executes all pending database migrations:
This will:
  • Connect to the PostgreSQL database
  • Check for pending migrations in the migrations table
  • Run all new migrations that haven’t been applied yet

Generate a New Migration

To generate a new migration with a custom name:
For example:
This will create a new migration file in core-api/src/database/migrations/.

Revert the Last Migration

To rollback the most recently executed migration:
Note: This will only revert one migration at a time. Repeat if needed.

Migration with Docker Compose

If you prefer to run migrations using Docker (useful when not running PostgreSQL locally):
This starts the PostgreSQL container (if not running), runs the migration service, applies all pending migrations, removes the migration container, and starts core-api once migrations complete. To keep the container for debugging:
The --rm flag ensures the container is removed after it stops.

Development Conventions

Code Style

  • Core API (NestJS): Uses ESLint and Prettier.
  • Console (React): Uses ESLint and Prettier.
  • Workers (Go): Uses go fmt and go vet.

Testing

  • Core API: Uses Jest for testing.
  • Console: Uses Vitest for unit tests and Playwright for e2e tests.
  • Workers: Uses Go testing.

Build

API Client Generation

After making changes to the API contract, regenerate the console API client:
This uses orval to generate TanStack Query hooks from the OpenAPI spec. The source spec lives at .open-api in core-api (the docs site mirrors it at api-reference/openapi.json).

gRPC Stub Generation

After modifying proto files, regenerate gRPC stubs:
This generates Go and TypeScript stubs into grpc-client/.

Environment variables

Each service reads its configuration from its own .env file, copied from the example templates by task init. The table below lists the variables used in local development with their defaults.
Never commit .env files — they are gitignored. The worker’s WORKER_API_KEY must match the workspace key the Core API expects; a mismatch prevents workers from registering, see Worker.

Using Docker Compose

To run the entire stack using Docker Compose:
This starts:
  • Console (port 3000)
  • Core API (port 6276, gRPC port 16276)
  • 3 Worker instances
  • PostgreSQL with pgvector (port 5432)
  • Redis (port 6379)
  • Geo-IP proxy (port 4360)
  • Rustfs S3 storage (port 9000)

Local CI Testing

Before pushing changes, you can run GitHub Actions workflows locally using act to catch issues early.

Prerequisites

  • Docker Desktop must be installed and running
  • Install act:

Usage

Local Test Equivalents

Notes

  • Workflows using docker/build-push-action with multi-platform builds (build-release.yml, build-nightly.yml) need QEMU and native CI runners — they cannot run locally.
  • dorny/paths-filter may not detect file changes correctly in shallow clones. Use --full-history or test specific jobs.
  • Docker layer caching (type=gha) is not available locally, but builds will still work.

Contributing

We welcome contributions! Please follow these steps:
  1. Fork the repository.
  2. Create a feature branch: git checkout -b feature/amazing-feature.
  3. Make your changes and commit them following Conventional Commits:
  4. Test CI workflows locally: bash .github/scripts/test-local.sh <workflow>
  5. Push to the branch: git push origin feature/amazing-feature.
  6. Open a Pull Request.
Please ensure your code adheres to the project’s coding standards and passes all tests before submitting a PR.