Skip to main content

Command-line interface

Aastro ships as two binaries:

  • aastro — the gateway daemon. Starts the HTTP server, tests configuration, prints version information.
  • aastroctl — companion tool for developers and DevOps. Generates plugin scaffolding and (in future versions) communicates with a running daemon.

Both follow standard Unix conventions: short and long flags (-c / --config), grouped short flags (-tq is -t -q), -- as a positional argument terminator, and KEY=VALUE for long flag values.

aastro

The daemon. Running aastro without flags loads the configuration and starts the gateway. All other operations are flags rather than subcommands, following the convention used by nginx, haproxy, and other long-lived system services.

Usage

aastro [options]

Options

ShortLongDescription
-c--configConfiguration file path (env: AASTRO_CONFIG)
-t--testTest configuration and exit
-T--test-dumpTest configuration, dump effective config to stdout, exit
-q--quietSuppress non-error output (useful in CI alongside -t)
-v--versionPrint version and exit
-V--version-verbosePrint version with build details (commit, build date, Go version)
-h--helpPrint help and exit

Configuration path resolution

When --config is not specified, Aastro looks for the configuration file in this order:

  1. The AASTRO_CONFIG environment variable
  2. The default path /etc/aastro/config.yaml

If neither is set or the file is missing, Aastro exits with an error.

Exit codes

CodeMeaning
0Success
1Generic runtime error
2Configuration error (parse, validation, missing)

The configuration error code is distinct so that CI pipelines can react differently to a bad config versus a runtime failure.

Testing configuration

aastro -t parses the configuration file, applies defaults, resolves environment substitutions, and validates the result. It does not start the server, bind ports, or connect to upstreams.

$ aastro -t -c config.yaml
aastro: configuration file config.yaml test is successful
$ echo $?
0

In CI you typically want silence on success and noise only on failure:

$ aastro -tq -c config.yaml || exit $?

On failure, the error is printed to stderr regardless of -q:

$ aastro -t -c broken.yaml
aastro: configuration file broken.yaml test failed
aastro: yaml: line 5: did not find expected key
$ echo $?
2

Dumping the effective configuration

aastro -T performs the same validation as -t, then writes the effective configuration to stdout — the configuration as Aastro actually sees it after defaults are applied, environment variables are substituted, and includes are resolved.

This is useful for:

  • Diffing the effective config between deploys
  • Verifying that environment substitution produced the expected values
  • Snapshot-testing the configuration in a repository
$ aastro -T -c config.yaml > effective.yaml
aastro: configuration file config.yaml test is successful

$ head -3 effective.yaml
# configuration file config.yaml test is successful
# aastro/v1.2.3 at 2026-05-26T14:30:00Z
#

Diagnostic output goes to stderr; the dump goes to stdout. This makes redirection clean:

$ aastro -T -c config.yaml | yq '.gateway.flows[].path'
info

The dumped configuration is valid input for Aastro — you can feed it back via -c. Round-tripping is supported.

Version information

aastro -v prints a single-line product/version string:

$ aastro -v
aastro/v1.2.3

aastro -V prints the full build manifest, including the commit hash, build date, and Go runtime:

$ aastro -V
aastro version: aastro/v1.2.3
built with: go1.25.4 (linux/amd64)
built at: 2026-05-26T14:30:00Z
commit: abc1234

Use -V when reporting bugs — the commit hash uniquely identifies the source revision the binary was built from.

Running in Docker

The official image runs aastro as the entrypoint, so flags pass through directly:

# Start the daemon with a mounted config
docker run -v $(pwd)/config.yaml:/etc/aastro/config.yaml starwalkn/aastro:1.2.3

# Test a config without starting the daemon
docker run -v $(pwd)/config.yaml:/etc/aastro/config.yaml starwalkn/aastro:1.2.3 -t

# Check the installed version
docker run --rm starwalkn/aastro:1.2.3 -V

Signals

Aastro responds to standard process signals:

SignalBehaviour
SIGINTGraceful shutdown (drain in-flight requests, exit)
SIGTERMGraceful shutdown

The graceful shutdown timeout is 10 seconds. After that, in-flight requests are abandoned and the process exits.

aastroctl

The companion tool. Unlike aastro, it uses a subcommand-based CLI similar to kubectl or git, because it bundles unrelated operations (plugin scaffolding today; daemon administration in future releases).

Usage


aastroctl <command> [flags]

Commands

CommandDescription
plugin initGenerate a new plugin or middleware skeleton
openapi exportGenerate an OpenAPI document from a gateway configuration
helpShow help for any command (also available via --help)

Global flags

LongDescription
--versionPrint version with build details and exit
--helpPrint help and exit

aastroctl plugin init

Generates a starter .go file for a new plugin or middleware. The generated code compiles as-is — you can run go build -buildmode=plugin on it immediately and load the resulting .so into Aastro.

aastroctl plugin init --type=<type> --name=<name> [flags]

Flags:

FlagRequiredDescription
--typeyesPlugin type: request, response, or middleware
--nameyesPlugin name (used in Info().Name and as the default output filename)
--descriptionnoPlugin description for Info().Description
--authornoAuthor name for Info().Author
--outnoOutput file path (default: <name>.go in the current directory)

Examples:

# Generate a request-phase plugin
aastroctl plugin init --type=request --name=add-header

# Generate a middleware in a specific location
aastroctl plugin init --type=middleware --name=ratelimit --out=./plugins/ratelimit/main.go

# With full metadata
aastroctl plugin init \
--type=response \
--name=wrap-payload \
--description="Wraps response bodies in a JSON envelope" \
--author="ops-team"

The generated file is formatted with gofmt before writing. If the output path already exists, the command refuses to overwrite it.

See Plugin & Middleware Development for the full guide on writing plugins.

aastroctl openapi export

Generates an OpenAPI 3.1 (or 3.0) document from a gateway configuration. The configuration is loaded through the same pipeline as the gateway itself — defaults applied, validation performed — so the resulting document describes what the gateway will actually execute, and a broken configuration fails here before it reaches a deploy.

aastroctl openapi export [flags]

Flags:

FlagShortDefaultDescription
--config-caastro.yamlPath to the gateway configuration
--out-o-Output file (- for stdout)
--formatby extensionyaml or json; inferred from the output extension, else yaml
--oas-version3.1OpenAPI version: 3.1 or 3.0
--servernoServer URL for servers[]; repeat the flag for multiple entries
--titleservice nameinfo.title
--api-version0.0.0info.version
--extensionsoffEmbed x-aastro snapshots of each flow for future config import

Examples:

# Generate a request-phase plugin
# Print the document to stdout
aastroctl openapi export -c config.yaml

# Write YAML and JSON files (format inferred from the extension)
aastroctl openapi export -c config.yaml -o openapi.yaml
aastroctl openapi export -c config.yaml -o openapi.json

# Target OpenAPI 3.0 for older client generators
aastroctl openapi export -c config.yaml --oas-version 3.0 -o openapi.yaml

# Full metadata for a published spec
aastroctl openapi export -c config.yaml \
--title "Customer API" \
--api-version 1.4.0 \
--server https://api.example.com \
--extensions \
-o openapi.yaml

aastroctl openapi import

Generates a gateway configuration from an OpenAPI 3.x document — the inverse of openapi export. Documents produced by openapi export --extensions are reconstructed losslessly; foreign documents are scaffolded into a working starting point. The generated configuration is validated before it is written, so import never emits a config the gateway would reject.

aastroctl openapi import -i <document> [flags]

Flags:

FlagShortDefaultDescription
--in-irequiredOpenAPI document to import (yaml or json)
--out-o-Output configuration file (- for stdout)
--default-hostservers[0]Upstream host for scaffolded flows; falls back to a placeholder
--modeenvelopeFlow shape for scaffolded operations: envelope or passthrough
--server-port7805Gateway data port written into the generated config
--admin-port9090Gateway admin port written into the generated config
--forceoffOverwrite the output file if it already exists

Examples:

# Print the generated configuration to stdout
aastroctl openapi import -i openapi.yaml

# Write to a file (refuses to overwrite unless --force)
aastroctl openapi import -i openapi.yaml -o aastro.yaml

# Import a JSON document (format detected automatically)
aastroctl openapi import -i openapi.json -o aastro.yaml

# Scaffold a foreign spec, pointing every flow at one host
aastroctl openapi import -i petstore.yaml --default-host https://backend.internal -o aastro.yaml

# Scaffold streaming-style flows as passthrough
aastroctl openapi import -i events-api.yaml --mode passthrough -o aastro.yaml

Lossless import vs. scaffolding

The command has two modes of operation, chosen automatically per operation:

  • Lossless reconstruction — operations carrying an x-aastro extension (written by openapi export --extensions) are restored in full: flows, aggregation, upstreams, per-upstream policy, and transport. Fields left at their gateway defaults are omitted from the result, so the output is minimal and reads like a hand-written config rather than an exhaustive dump.
  • Scaffolding — operations without the extension (any third-party document) become single-upstream flows. Path parameters, and the query and header parameters declared on the operation, are turned into forward_params, forward_queries, and forward_headers. The upstream host comes from --default-host, then servers[0], then a https://CHANGE-ME.internal placeholder. Flows default to array aggregation, or to passthrough under --mode passthrough.

Some inputs are inferred rather than restored:

  • Operations that respond with a streamed */* body are scaffolded as passthrough flows regardless of --mode.
  • If any operation carries a 429 response, the rate limiter is enabled with default settings.

What is not restored

Secrets and credentials never appear in an OpenAPI document, so they cannot be reconstructed. Where the input signals that something was configured, import emits a warning instead of guessing:

  • Plugin and middleware configurations — only their names survive in x-aastro. Each is reported so you can re-add its config block manually.
  • TLS material — an upstream that used TLS is restored with tls.enabled: true and system roots, and a warning reminds you to re-add certificate or CA paths for mTLS or a private CA. The upstream fails the handshake loudly rather than silently downgrading to plain HTTP.
  • Auth requirements in foreign documents — a security requirement on an operation becomes a warning to configure the auth middleware.

Warnings go to stderr; the configuration goes to stdout, so redirection stays clean:

aastroctl openapi import -i openapi.yaml -o aastro.yaml 2> import-warnings.log
info

Round-tripping a config through export --extensions and back is stable: the topology is reconstructed exactly. Plugin and middleware config blocks are the only parts that need re-adding by hand, because their contents are never written to the spec.

info

The generated configuration is intentionally minimal — fields at their gateway defaults are omitted and re-applied on load. If you prefer a config with every effective value pinned explicitly (for example, to stay independent of a future change in gateway defaults), materialize it with aastro -T:

aastroctl openapi import -i openapi.yaml -o - | aastro -T -c /dev/stdin > aastro.yaml

Conventions

A few conventions to keep in mind when scripting against either binary.

Output streams

  • stdout carries the primary output of the command — version strings, configuration dumps, future command results.
  • stderr carries diagnostic messages — test is successful, created myplugin.go, error reports.

This means redirection works the way you expect:

aastro -T -c config.yaml > snapshot.yaml # dump only, diagnostics to terminal
aastro -t -c config.yaml 2> test.log # log diagnostics, no stdout
aastroctl --version | cut -d/ -f2 # parse just the version

Short flag grouping

Short boolean flags can be combined. These are equivalent:

aastro -t -q -c config.yaml
aastro -tq -c config.yaml
aastro -tqc config.yaml

The value-taking flag (-c here) must come last in the group; its argument follows immediately.

Environment variables

VariableUsed byDescription
AASTRO_CONFIGaastroDefault config path (overridden by -c)

Additional environment variables for configuration values themselves are documented under Configuration.