Server Configuration

Modified on Tue, 14 Jul at 11:37 AM

The Maltego Transform Server consists of two main modules: a FastAPI based web-server and a Transform Runner.

The web server is used to handle incoming transform execution and discovery requests and handle them accordingly.

Transform execution requests get scheduled to be run as part of a Transform Runner. Currently two types of runners are supported.

  • AsyncTransformRunner: An async based transform runner that runs transforms as part of the same event loop used by FastAPI. This implementation has lower overhead since no threading is required but requires all transforms to use async based primitives and libraries.
  • ThreadedTransformRunner: A threaded based implementation that runs N worker threads, each using their own asyncio loop to execute transforms. This runner has the benefit of not blocking the FastAPI event loop and other transforms when blocking (non-async) code is used.

The generated starter project's project.py is the simplest single-server entrypoint. This article covers the broader configuration surface once you need to customize or combine servers.

Running a single server

To run a single server we recommend using the run_server function implemented in the maltego.server module.

This simple snippet runs a transform server over local HTTP on localhost port 3000:

from maltego.server import MaltegoServerSettings, ServerHTTPSettings, run_server


server_settings = MaltegoServerSettings(
    server_name="Maltego Transform Server",
    http_settings=ServerHTTPSettings(
        http_addr="127.0.0.1",
        http_port=3000,
        protocol="http",
    ),
)
if __name__ == "__main__":
    run_server(settings=server_settings)

The main guard is important if we intend to do hot code reloading later but also is good practice apart of it.

The behavior of the server can be controlled using the MaltegoServerSettings class and using the run_server function. See the "Execution Runner" article for a focused guide to choosing and configuring the execution runner.

Local development, HTTPS, and advertised URLs

Keep these deployment concerns separate:

  • ServerHTTPSettings(protocol="http") starts a local HTTP listener. This is the generated starter's default and is the simplest setup for local SDK development.
  • ServerHTTPSettings(protocol="https", cert_file=..., cert_key=...) starts a direct HTTPS listener. Generate local development certificates yourself and keep private keys out of source control.
  • ServerHTTPSettings.protocol, domain, and root_url control the URL advertised in discovery responses. In reverse-proxy deployments, the Python server can listen on HTTP behind the proxy while root_url points at the public HTTPS URL served by the proxy.

For production, either terminate TLS at a trusted reverse proxy or configure a direct HTTPS listener with a certificate from a trusted certificate authority. Do not reuse local self-signed certificates or commit certificate private keys.

Understanding settings and run_server()

Passing settings to run_server() registers your transforms and entities with those server settings before startup:

from maltego.server import MaltegoServerSettings, ServerHTTPSettings, run_server


server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",           # Namespace for your entities/transforms
    author="dev@mycompany.com",
    http_settings=ServerHTTPSettings(
        http_addr="127.0.0.1",
        http_port=3000,
        protocol="http",
    ),
)


if __name__ == "__main__":
    # Start the local HTTP server
    run_server(settings=server_settings)

Customizing the URL Path (api_prefix)

When your advertised server URL uses HTTPS, the seed URL is https://<host>:<port>/seed. Local generated projects that run over HTTP use http://127.0.0.1:3000/seed instead. Use api_prefix to add a custom path prefix:

server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="dev@mycompany.com",
    api_prefix="/maltego_example",  # Custom URL prefix
)


# HTTPS seed URL becomes: https://127.0.0.1:3000/maltego_example/seed

This is useful when:

  • Running multiple transform servers behind a reverse proxy
  • Organizing different integrations under distinct paths
  • Deploying to a shared infrastructure

Health endpoint

The server exposes a lightweight GET /health endpoint that returns {"status": "ok"}. It is intended for basic liveness checks and does not perform dependency validation.

Seed URLs behind a reverse proxy or ingress

For the full picture of running behind a proxy -- TLS termination patterns, which headers your proxy must forward, and where auth/authorization checks happen relative to the proxy -- see Deploying Behind a Reverse Proxy. This section is the field-level reference for the relevant settings.

By default, the server auto-generates seed response URLs from the request URL seen by FastAPI. When the server is behind a trusted reverse proxy or ingress, enable trust_forwarded_headers to use x-forwarded-proto and x-forwarded-host from allowed proxy IPs:

from maltego.model.server import ServerHTTPSettings


server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="dev@mycompany.com",
    trust_forwarded_headers=True,
    http_settings=ServerHTTPSettings(
        forwarded_allow_ips="10.0.0.1,10.0.0.0/24",
    ),
)

This can also be configured with MALTEGO_SERVER_TRUST_FORWARDED_HEADERS=true and MALTEGO_SERVER_FORWARDED_ALLOW_IPS=10.0.0.1,10.0.0.0/24. The old TRUST_FORWARDED_HEADERS name remains supported for backward compatibility, but is deprecated. The default allowed proxy value is 127.0.0.1. Use * only when every direct client is trusted. Explicit http_settings.root_url and full_host_url settings still take precedence for host and path when configured. If both explicit URLs are configured, http_settings.root_url takes precedence over full_host_url. If either selected explicit URL uses http://, the seed response promotes only the scheme to https:// when the server protocol is configured as https or a trusted forwarded header reports x-forwarded-proto: https. Explicit https:// URLs are never downgraded to http://.

If the proxy terminates HTTPS, the browser validates the proxy certificate. See the "HTTPS, Certificates, and Browser Trust" article for browser trust requirements and how to distinguish certificate failures from SDK, CORS, or auth failures.

OpenAPI and Swagger endpoints

The server exposes OpenAPI and Swagger UI endpoints for API exploration:

  • /openapi.json - Full OpenAPI 3 specification for all active server routes.
  • /swagger - Swagger UI backed by the OpenAPI spec.

Both endpoints are disabled by default. Enable them with the swagger_enabled setting on MaltegoServerSettings:

from maltego.server import MaltegoServerSettings, run_server


settings = MaltegoServerSettings(
    server_name="My Transforms",
    swagger_enabled=True,  # enable /swagger and /openapi.json
)
run_server(settings=settings)

Or via environment variable:

MALTEGO_SERVER_SWAGGER_ENABLED=true

OpenTelemetry tracing

The server supports provider-agnostic OpenTelemetry tracing. Supply a configured TracerProvider to run_server() to enable it:

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from maltego.server import run_server


provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))


run_server(settings=settings, tracer_provider=provider)

When a tracer_provider is given, the SDK:

  • Sets it as the global OTEL tracer provider.
  • Registers W3C TraceContext, W3C Baggage, and B3 propagators.
  • Instruments FastAPI so every HTTP request produces a span.
**Opt-in:** install the ``tracing`` extra to make OTel packages available: ``pip install maltego-transforms[tracing]``. If the extra is not installed, passing ``tracer_provider`` logs a warning and is otherwise a no-op; the server still starts normally.

Excluding URLs from tracing: pass tracing_excluded_urls to skip health-check or metrics paths:

run_server(
    settings=settings,
    tracer_provider=provider,
    tracing_excluded_urls="/health,/metrics",
)

W3C traceparent: every request is guaranteed to carry a W3C traceparent in logs. When OTEL is active the active span's context is used; otherwise the incoming traceparent header is reused; if neither is present a fresh traceparent is generated. No client-side configuration is required.

run_server() function reference

maltego.server.run_server runs a Maltego transform server using uvicorn and FastAPI.

ParameterDescription
settings (optional)A MaltegoServerSettings object. Uses pydantic's BaseSettings, so environment variables or a .env file can override the values.
host (optional)The host uvicorn binds to. Defaults to None, in which case the effective value comes from ServerHTTPSettings.http_addr ("127.0.0.1" unless overridden). Can be overridden by MALTEGO_SERVER_HTTP_ADDR.
port (optional)The host port uvicorn binds to. Defaults to None, in which case the effective value comes from ServerHTTPSettings.http_port (3000 unless overridden). Can be overridden by MALTEGO_SERVER_HTTP_PORT.
ssl (optional)Whether SSL should be used. Converted internally to a protocol (https if True, http if False).
ssl_cert_file (optional)Filesystem path of an SSL certificate for HTTPS. Can be overridden by MALTEGO_SERVER_CERT_FILE.
ssl_key_file (optional)Filesystem path of an SSL private key matching the certificate. Can be overridden by MALTEGO_SERVER_CERT_KEY.
transform_middlewares (optional)Instances of TransformMiddleware used during transform executions, for logic that runs right before/after a transform (rate-limiting, logging, etc). See the "SDK API Reference" article.
log_level (default "INFO")Log level used by the transform server. One of DEBUG, INFO, WARNING, ERROR, CRITICAL.
reload (default False)Hot code reloading (experimental; do not use in production). Requires run_server to be guarded by a main guard and setup() to be called outside of that guard.
hub_item (optional)An instance of MaltegoHubItem, used to announce hub item metadata associated with an integration. See the "SDK API Reference" article.
prefix (optional, deprecated 3.3.0)Optional API prefix for the integration. By default the integration is reachable at http://<host>:<port>/seed; with a prefix it becomes http://<host>:<port>/<api-prefix>/seed. Use the api_prefix field on MaltegoServerSettings instead.
full_host_url (optional, deprecated 3.3.0)Hard-codes the server URL returned in the seed response. Normally this is auto-generated from the seed request. Use MaltegoServerSettings instead.
auth_settings (optional)Optional authentication settings for JWT/OIDC/SAML validation. Can also be configured via MALTEGO_SERVER_AUTH_* environment variables.

MaltegoServerSettings reference

maltego.server.MaltegoServerSettings is a pydantic settings class used to control the behavior of a Maltego transform server. All fields can be configured via environment variables with the MALTEGO_SERVER_ prefix (for example MALTEGO_SERVER_SERVER_NAME, MALTEGO_SERVER_NS). Environment variables take precedence over programmatic values, following the priority: env vars > .env file > code.

FieldDescription
server_name (str, required)Common name for the server. Should be a unique identifier.
http_settings (ServerHTTPSettings)HTTP server configuration (address, port, SSL, CORS, etc). See the "HTTP Server Configuration" section below.
transform_execution_timeout (int, default 3600)Maximum allowed runtime for a single transform, in seconds, before it gets canceled.
middleware_execution_timeout (int, default 600)Maximum allowed runtime for a middleware execution before a transform gets canceled.
ns (str, default "maltego")Namespace of the transform server. Should be a unique string identifying the vendor.
author (str, optional, default "John Doe")Author attribution used in transform discovery.
owner (str, optional)Owner attribution used in transform discovery.
version (str, default "1.0.0")Version of the deployed transform server.
max_concurrent_transforms_per_user (int, optional)If specified, limits transform runs to this many concurrent transforms per user.
transform_prefix (bool, default False)Enables transform name prefixes. When enabled, transform_name_prefix, transform_app_name_prefix and transform_display_name_prefix become effective. Useful for deploying multiple transform servers from the same codebase.
transform_name_prefix (str, optional)Adds a prefix to all transform names in discovery and execution.
transform_app_name_prefix (str, optional)Adds a prefix to the transform server name.
transform_display_name_prefix (str, optional)Adds a prefix to all discovered transforms' display names.
v3_page_size_max (int, default 50)Max supported JSON protocol page size sent in the OPTIONS response during discovery. Not currently implemented in Maltego (as of 4.7.0).
entity_config_overrides (EntityConfigOverrides, optional)Optional per-client entity property overrides applied during JSON entity discovery (e.g. desktop vs. web). See "Entity Config Overrides" below.
full_host_url (str, optional)Hard-codes the server URL returned in the seed response. Normally auto-generated to match the seed request; override for edge cases like pointing to another server.
trust_forwarded_headers (bool, default False)Trusts x-forwarded-proto/x-forwarded-host request headers from allowed proxy IPs when auto-generating seed response URLs. Enable only behind a trusted reverse proxy or ingress.
api_prefix (str, optional)Optional API prefix for the integration (see "Customizing the URL Path" above).
disclaimer (str, optional)Optional URL displayed during discovery as a disclaimer the user must acknowledge.
num_worker (int, default 1)Number of worker threads used by ThreadedTransformRunner.
transform_runner (TransformRunnerType, default TransformRunnerType.THREADED)Transform runner implementation to use. See "Transform Runner" below.
scheduled_cleanup_seconds (int, default 60)Interval used for cleaning up inactive transforms in the runner queue.
log_level (str, default "INFO")Log level for the transform server: DEBUG, INFO, WARNING, ERROR, or CRITICAL.

HTTP Server Configuration

The HTTP server settings can be configured using the ServerHTTPSettings class, which supports configuration via environment variables, .env files, or programmatic configuration. This provides a flexible way to configure your transform server for different deployment environments.

ServerHTTPSettings reference

maltego.server.ServerHTTPSettings holds HTTP server configuration settings that can be overridden via environment variables (prefix MALTEGO_SERVER_, e.g. MALTEGO_SERVER_HTTP_ADDR, MALTEGO_SERVER_HTTP_PORT). Environment variables are optional and fall back to defaults when unset.

FieldDescription
http_addr (str, default "127.0.0.1")HTTP server bind address. Set this to "0.0.0.0" only when the server should listen on all interfaces.
http_port (int, default 3000)HTTP server port.
domain (str, optional)Server domain name (e.g. mysite.com). Used to construct the server URL in discovery responses when root_url is not set.
root_url (str, optional)Full server root URL (e.g. https://subdomain.mysite.com:3000). Takes precedence over domain. Used in discovery responses to tell Maltego where to connect.
cert_key (str, optional)Path to the SSL certificate key file.
cert_file (str, optional)Path to the SSL certificate file.
protocol (str, default "https")Server protocol, http or https.
cors_allowed_origins (list of str, optional)Optional list of browser origins allowed to access the server via CORS. Disabled by default. When provided, app-level CORS middleware is added during setup.
cors_allowed_origin_regex (str, optional)Optional regular expression used to match browser origins for CORS. Disabled by default. Can be used instead of, or together with, cors_allowed_origins.
forwarded_allow_ips (str, default "127.0.0.1")Comma-separated IP addresses, CIDR ranges, or host literals allowed to supply forwarded headers. Use * only when every direct client is trusted.

It also exposes a read-only use_ssl property that is True when protocol is "https" and both cert_file and cert_key are set.

Configuration via Environment Variables

All HTTP server settings can be configured using environment variables with the MALTEGO_SERVER_ prefix. Environment variables are optional and will use default values if not set.

Available Environment Variables:

  • MALTEGO_SERVER_HTTP_ADDR - Server bind address (optional, default: 127.0.0.1)
  • MALTEGO_SERVER_HTTP_PORT - Server port (optional, default: 3000)
  • MALTEGO_SERVER_DOMAIN - Server domain name (optional, default: None)
  • MALTEGO_SERVER_ROOT_URL - Full server root URL (optional, default: None, overrides domain and port)
  • MALTEGO_SERVER_CERT_KEY - Path to SSL certificate key file (optional, default: None, required for HTTPS)
  • MALTEGO_SERVER_CERT_FILE - Path to SSL certificate file (optional, default: None, required for HTTPS)
  • MALTEGO_SERVER_PROTOCOL - Server protocol: http or https (optional, default: https)
  • MALTEGO_SERVER_FORWARDED_ALLOW_IPS - Comma-separated proxy IPs, CIDR ranges, or host literals allowed to supply forwarded headers for seed URL generation (optional, default: 127.0.0.1)
  • MALTEGO_SERVER_HTTP_RESPONSE_COMPRESSION_ENABLED - Enable gzip response compression for clients that request it with Accept-Encoding: gzip (optional, default: False)
  • MALTEGO_SERVER_HTTP_RESPONSE_COMPRESSION_MINIMUM_SIZE - Minimum response size in bytes before gzip compression is applied (optional, default: 500)

MALTEGO_SERVER_PROTOCOL is used when constructing the server URL for discovery responses. The server only listens with TLS when both certificate paths are present and SSL is enabled. For local HTTP development, set MALTEGO_SERVER_PROTOCOL=http or configure ServerHTTPSettings(protocol="http").

Note: If you set an environment variable to an empty string (e.g., MALTEGO_SERVER_DOMAIN=), it will be treated as if the variable was not set, and the default value will be used.

Example production .env file for direct HTTPS:

Create a .env file in your project root:

MALTEGO_SERVER_HTTP_ADDR=0.0.0.0
MALTEGO_SERVER_HTTP_PORT=3000
MALTEGO_SERVER_DOMAIN=mysite.com
MALTEGO_SERVER_ROOT_URL=https://subdomain.mysite.com:3000
MALTEGO_SERVER_CERT_KEY=/etc/myserver/myserver.key
MALTEGO_SERVER_CERT_FILE=/etc/myserver/myserver.crt
MALTEGO_SERVER_PROTOCOL=https

For local starter projects, prefer HTTP until you specifically need HTTPS:

MALTEGO_SERVER_HTTP_ADDR=127.0.0.1
MALTEGO_SERVER_HTTP_PORT=3000
MALTEGO_SERVER_PROTOCOL=http

The server will automatically load these settings when you create a MaltegoServerSettings instance:

from maltego.server import run_server, setup, MaltegoServerSettings


# Settings will be loaded from environment variables or .env file
server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="security@mycompany.com"
)


setup(server_settings)


if __name__ == "__main__":
    run_server()  # Will use HTTP settings from environment

Production Deployment Guidance

The default server settings are kept compatibility-oriented so existing local development and customer deployments continue to start without extra configuration. Before exposing a transform server outside a trusted local environment, explicitly set production values instead of relying on defaults:

  • Bind to a private interface, loopback address, container network, or reverse proxy listener unless the server is intentionally exposed on all interfaces. The default bind address is loopback-only; set 0.0.0.0 explicitly for container deployments that need to receive traffic from outside the container.
  • Terminate TLS at a reverse proxy or configure protocol="https" together with certificate and private-key paths. Do not commit certificate private-key files to the project repository.
  • Enable the authentication mode required by your deployment. For protected deployments, configure AuthSettings(enabled=True, ...) (Maltego ID, OIDC, SAML, or another configured auth backend). require_api_key is a legacy license-mode compatibility flag — leave it at the default (False) for all new deployments.
  • Keep CORS disabled unless a browser application must call the transform server directly. When CORS is required, use exact trusted origins or a tightly scoped regex.
  • Keep secrets such as API keys, OAuth credentials, and certificate private-key files in environment variables, deployment secret stores, or local untracked .env files.

Configuration via Code

You can also configure HTTP settings programmatically by creating a ServerHTTPSettings instance:

from maltego.server import (
    run_server, setup,
    MaltegoServerSettings,
    ServerHTTPSettings
)


# Create custom HTTP settings
http_settings = ServerHTTPSettings(
    http_addr="127.0.0.1",
    http_port=3000,
    protocol="https",
    cert_file="/path/to/server.crt",
    cert_key="/path/to/server.key",
    http_response_compression_enabled=True,
    http_response_compression_minimum_size=500
)


# Use in server settings
server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="security@mycompany.com",
    http_settings=http_settings
)


setup(server_settings)


if __name__ == "__main__":
    run_server()

HTTP Response Compression

HTTP response compression is disabled by default. To enable gzip compression for JSON responses, set http_response_compression_enabled=True on ServerHTTPSettings or use MALTEGO_SERVER_HTTP_RESPONSE_COMPRESSION_ENABLED=true. The server uses FastAPI/Starlette gzip middleware and only compresses responses when the client sends a compatible Accept-Encoding header.

Responses smaller than http_response_compression_minimum_size are left uncompressed. The default minimum is 500 bytes, matching Starlette's default, and can be tuned with MALTEGO_SERVER_HTTP_RESPONSE_COMPRESSION_MINIMUM_SIZE.

If a reverse proxy or load balancer also performs compression, configure only one layer to compress a response. Double compression can waste CPU and confuse client or proxy caches. Brotli is not enabled by the SDK; add it only after confirming dependency, client, HTTPS, and proxy support for your deployment.

CORS Configuration

CORS is disabled by default. The server only adds FastAPI's CORSMiddleware when you explicitly configure cors_allowed_origins or cors_allowed_origin_regex on ServerHTTPSettings. Configure certificate trust first: CORS only applies after the browser accepts the server's HTTPS certificate. See the "HTTPS, Certificates, and Browser Trust" article for the certificate trust checklist.

Use exact origins when possible:

from maltego.server import MaltegoServerSettings
from maltego.model.server import ServerHTTPSettings


server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="security@mycompany.com",
    http_settings=ServerHTTPSettings(
        cors_allowed_origins=["https://app.maltego.com"]
    )
)

Use a constrained regex when you need controlled wildcard-style matching:

from maltego.server import MaltegoServerSettings
from maltego.model.server import ServerHTTPSettings


server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    ns="mycompany",
    author="security@mycompany.com",
    http_settings=ServerHTTPSettings(
        cors_allowed_origin_regex=r"^https://app\.maltego\.com$"
    )
)

If you terminate traffic behind a reverse proxy or ingress, you can configure CORS there instead of in the SDK server. Keep one source of truth to avoid conflicting responses. See "CORS at the proxy" in Deploying Behind a Reverse Proxy for a worked ingress/NGINX example and the full list of Maltego client headers to allowlist.

SSL/HTTPS Configuration

The server supports SSL/HTTPS when you provide certificate files. The use_ssl property automatically determines whether SSL should be enabled based on the protocol and certificate file availability.

SSL is enabled when:

  • MALTEGO_SERVER_PROTOCOL=https
  • Both MALTEGO_SERVER_CERT_FILE and MALTEGO_SERVER_CERT_KEY are provided

Example HTTPS setup:

from maltego.server import (
    run_server, setup,
    MaltegoServerSettings,
    ServerHTTPSettings
)

http_settings = ServerHTTPSettings(
    http_addr="0.0.0.0",
    http_port=443,
    protocol="https",
    cert_file="/etc/letsencrypt/live/example.com/fullchain.pem",
    cert_key="/etc/letsencrypt/live/example.com/privkey.pem"
)

server_settings = MaltegoServerSettings(
    server_name="Secure Transform Server",
    ns="mycompany",
    author="security@mycompany.com",
    http_settings=http_settings
)

setup(server_settings)

if __name__ == "__main__":
    run_server()

Checking SSL status:

http_settings = ServerHTTPSettings(
    protocol="https",
    cert_file="/path/to/cert.crt",
    cert_key="/path/to/cert.key"
)

print(http_settings.use_ssl)  # True

Configuration Priority

When multiple configuration sources are provided, they follow this priority order (highest to lowest):

  1. Environment variables (MALTEGO_SERVER_*)
  2. .env file values
  3. Direct parameters to the run_server() function
  4. Programmatic ServerHTTPSettings instance passed to MaltegoServerSettings
  5. Default values

This ensures that deployment-level configuration (environment variables) always takes precedence over code-defined values.

Domain and URL Configuration

You can configure how your server's URL is constructed using either a domain or a full root URL. ServerHTTPSettings does not expose a method that returns this URL directly; instead, the server derives it internally (the same logic used to build seed response URLs) from root_url, domain, http_port, and protocol, in that order of precedence:

Using Domain:

http_settings = ServerHTTPSettings(
    domain="api.mycompany.com",
    http_port=3000,
    protocol="https"
)

# Effective URL: https://api.mycompany.com:3000
# (protocol + domain + port, since root_url is not set)

Using Root URL (takes precedence):

http_settings = ServerHTTPSettings(
    root_url="https://subdomain.mycompany.com:3000",
    domain="mycompany.com",  # This will be ignored
    http_port=3000  # This will also be ignored
)

# Effective URL: https://subdomain.mycompany.com:3000
# (root_url is used verbatim, taking precedence over domain/http_port)

Running Multiple Servers

This pattern keeps one default module-level server in _server, creates a second MaltegoTransformServer instance, sets both up, and concatenates the second server onto the first before calling run_server():

from maltego.server import (
    _server,
    MaltegoEntity,
    MaltegoServerSettings,
    MaltegoTransformServer,
    run_server,
)


server1_settings = MaltegoServerSettings(server_name="server1", api_prefix="server1")
server2_settings = MaltegoServerSettings(server_name="server2", api_prefix="server2")


server2 = MaltegoTransformServer(server2_settings)


@_server.register_transform
async def transform1(entity: MaltegoEntity) -> None:
    pass


@server2.register_transform
async def transform2(entity: MaltegoEntity) -> None:
    pass


_server.setup(server1_settings)
server2.setup(server2_settings)
_server.concat_server(server2)


if __name__ == "__main__":
    run_server(ssl=False)

This yields separate seed paths under the combined process, such as http://127.0.0.1:3000/server1/seed and http://127.0.0.1:3000/server2/seed.

Entity Config Overrides

Entity config overrides allow you to customize entity properties for different client types (desktop vs web). This is useful when certain entity features are not supported by all clients.

Common use cases:

  • Making entities available in the desktop palette (allowed_root: true) only for desktop clients
  • Providing fallback display values for entities using $coalesce() expressions (not supported by desktop)

Configuration via Code

Use EntityConfigOverrides in your server settings:

from maltego.server import run_server, setup, MaltegoServerSettings
from maltego.model.server import EntityConfigOverride, EntityConfigOverrides


server_settings = MaltegoServerSettings(
    server_name="My Transform Server",
    entity_config_overrides=EntityConfigOverrides(
        rules=[
            # Make entity appear in desktop palette
            EntityConfigOverride(
                entities=["maltego.MyEntity"],
                clients=["desktop"],
                overrides={"allowed_root": True}
            ),
            # Provide fallback for coalesce expression
            EntityConfigOverride(
                entities=["maltego.CoalesceEntity"],
                clients=["desktop"],
                overrides={"fields.display_property.default_value": "$property(name)"}
            ),
        ]
    ),
)

Configuration via Environment Variable

Overrides can also be configured at deployment time using the MALTEGO_SERVER_ENTITY_CONFIG_OVERRIDES environment variable with a JSON array:

export MALTEGO_SERVER_ENTITY_CONFIG_OVERRIDES='[
    {
        "entities": ["maltego.MyEntity"],
        "clients": ["desktop"],
        "overrides": {"allowed_root": true}
    }
]'

Namespace-specific environment variables:

For multi-server deployments, you can use namespace-specific environment variables. The server's ns value (with the maltego. prefix stripped and dots replaced by underscores) is used:

# For ns="maltego.sandbox" -> MALTEGO_SERVER_SANDBOX_ENTITY_CONFIG_OVERRIDES
export MALTEGO_SERVER_SANDBOX_ENTITY_CONFIG_OVERRIDES='[...]'


# For ns="com.mycompany.transforms" -> MALTEGO_SERVER_COM_MYCOMPANY_TRANSFORMS_ENTITY_CONFIG_OVERRIDES
export MALTEGO_SERVER_COM_MYCOMPANY_TRANSFORMS_ENTITY_CONFIG_OVERRIDES='[...]'

Namespace-specific variables take precedence over the generic MALTEGO_SERVER_ENTITY_CONFIG_OVERRIDES.

Field Override Syntax

To override a specific field's property, use dot notation: fields.<field_name>.<property>:

# Override the 'default_value' of a field named 'display_property'
overrides={"fields.display_property.default_value": "$property(name)"}


# Override the 'evaluator' of a field
overrides={"fields.display_property.evaluator": None}

EntityConfigOverride and EntityConfigOverrides reference

maltego.model.server.EntityConfigOverride is a single entity config override rule (a dataclass):

FieldDescription
entities (List[str])List of entity type IDs to override (e.g. ["maltego.Affiliation", "maltego.affiliation.Bebo"]).
clients (List[str])List of client types this rule applies to (e.g. ["desktop", "web"]).
overrides (Dict[str,Any])Dictionary of property names to override values (e.g. {"allowed_root": True}).

maltego.model.server.EntityConfigOverrides is a dataclass wrapping consumer-configurable entity property overrides. It allows SDK consumers to specify per-client property overrides for entities, applied during entity discovery so different property values can be served to different clients (e.g. desktop vs web).

FieldDescription
rules (List[Entity ConfigOverride]List of EntityConfigOverride rules. Defaults to an empty list.

Transform Runner

Transform runners are used to execute the actual transform code. The interface is specified in TransformRunner.

To switch between runners see the transform_runner field on MaltegoServerSettings (see "MaltegoServerSettings reference" above).

TransformRunnerType reference

maltego.server.TransformRunnerType is an enum used to select which transform runner a server should use:

ValueDescription
THREADEDThreaded transform runner with a variable number of worker threads.
ASYNCAsync transform runner, executing all transforms in the main thread's event loop.

AsyncTransformRunner

This implementation uses the main thread's asyncio event loop to execute transforms via the async/await primitives.

This is very fast assuming all transforms are purely async and only use async primitives and libraries for I/O based operations. The main downside is that a single transform executing blocking code can possibly stall the web server, making it unable to accept and respond to other transform requests.

maltego.runner.AsyncTransformRunner takes no constructor parameters of its own beyond the base TransformRunner (middlewares, transform_execution_timeout, middleware_execution_timeout, retention_time); it implements run(), start_transform(), startup() and shutdown() to execute scheduled transforms directly on the current asyncio event loop, with both startup() and shutdown() being no-ops since no dedicated threads or loops need to be managed.

To use AsyncTransformRunner see the following code snippet:

from maltego.server import (
    MaltegoServerSettings,
    ServerHTTPSettings,
    TransformRunnerType,
    run_server,
)


server_settings = MaltegoServerSettings(
    server_name="Maltego Transform Server",
    transform_runner=TransformRunnerType.ASYNC,
    http_settings=ServerHTTPSettings(
        http_addr="127.0.0.1",
        http_port=3000,
        protocol="http",
    ),
)
if __name__ == "__main__":
    run_server(settings=server_settings)

ThreadedTransformRunner

This implementation uses a threaded approach to solve the issues AsyncTransformRunner encounters when running non-async, blocking code. A number of worker threads is spawned, each having its own asyncio event loop, with the main thread running the FastAPI/uvicorn event loop.

Transforms get dispatched to those loops in a round-robin fashion. The default number of workers is 1 and can be changed via the num_worker field on MaltegoServerSettings. This is for safety reasons since some libraries reuse connection pools across different event loops, which does not work across multiple asyncio event loops. Increasing this parameter can speed up non-async execution.

maltego.runner.ThreadedTransformRunner extends TransformRunner with thread-pool based execution:

Constructor paramDescription
middlewares (List[TransformMiddleware])List of TransformMiddleware instances to run around each transform.
transform_execution_timeout (int)Maximum allowed runtime for a single transform, in seconds.
middleware_execution_timeout (int)Maximum allowed runtime for a middleware execution, in seconds.

Key methods: set_worker(worker: int) sets the number of worker threads before startup() is called; startup() spins up a ThreadPoolExecutor with one dedicated asyncio event loop per worker thread; shutdown(wait=True, cancel_futures=False) stops each worker's event loop and shuts down the executor.

To use ThreadedTransformRunner see the following code snippet:

from maltego.server import (
    MaltegoServerSettings,
    ServerHTTPSettings,
    TransformRunnerType,
    run_server,
)


server_settings = MaltegoServerSettings(
    server_name="Maltego Transform Server",
    transform_runner=TransformRunnerType.THREADED,
    num_worker=1,  # Modify carefully when using async libraries with connection pooling
    http_settings=ServerHTTPSettings(
        http_addr="127.0.0.1",
        http_port=3000,
        protocol="http",
    ),
)
if __name__ == "__main__":
    run_server(settings=server_settings)

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article