Getting Started
Getting Started
Section titled “Getting Started”This guide takes you from a fresh clone to a running, uncommissioned Aether
system: build the aether CLI, apply a reviewed safe-empty setup plan, start
the services, and confirm that the runtime is healthy.
Prerequisites
Section titled “Prerequisites”- Rust — the toolchain is pinned to
1.90.0byrust-toolchain.toml; rustup installs it automatically on first build. The pin also declares theaarch64-unknown-linux-muslcross-compilation target used for edge builds. - Docker Engine and Docker Compose — required for the container
composition.
aether services startdrives Docker Compose under the hood. Redis and PostgreSQL are not prerequisites.
Build and configure
Section titled “Build and configure”Build the aether CLI:
cargo build --release -p aetherInstall the binary onto your PATH — cp target/release/aether /usr/local/bin/
or cargo install --path tools/aether — so this and every other guide can
invoke it as bare aether.
The repository ships a fail-safe empty configuration in config.template/.
In a source checkout the CLI and docker-compose.yml both use
./data/config and ./data by default. Planning is persistently read-only and
will not create either directory:
aether --json setupRead data.plan_id from the JSON output, review the listed actions, then
explicitly apply that exact unchanged plan:
aether setup apply --plan-id <PLAN_ID>Apply is accepted only for a fresh site or an exact safe subset of the four
distribution files. Before any persistent write, Aether stages the complete
configuration, runs normal validation and the full atomic sync against a
temporary SQLite database, then creates only missing files without
overwriting. It initializes aether.db and syncs the empty runtime, but does
not start a service, enable a device or rule, or install a domain pack. If the
site changed after planning, the plan ID is stale and apply stops without a
write. Rerunning setup on the resulting safe_ready site is a no-op.
Existing/custom sites are reported but never rewritten by setup. Operators
can still use aether init for an explicit schema migration and aether sync
for an explicit configuration apply; aether sync --dry-run validates the
same nested files without changing the installed database.
The CLI resolves each path independently in this order: command-line flag,
AETHER_CONFIG_PATH/AETHER_DATA_PATH, /etc/aether/install.yaml, then the
current checkout’s data/config/ and data/. Installed packages write the
context file automatically. Without that context, Aether never adopts an old
installation directory merely because it exists.
For a fresh manual Compose deployment, create a private environment file and fill both first-start secrets before validating the composition. Packaged installers do this automatically; repository setup deliberately keeps secrets out of configuration templates.
cp .env.example .envchmod 600 .env
random_hex_32() { if command -v openssl >/dev/null 2>&1; then openssl rand -hex 32 else od -An -N32 -tx1 /dev/urandom | tr -d ' \n' fi}export JWT_SECRET_KEY="$(random_hex_32)"export AETHER_BOOTSTRAP_ADMIN_PASSWORD="$(random_hex_32)"
env_tmp="$(mktemp ./.env.tmp.XXXXXX)"chmod 600 "$env_tmp"awk ' /^JWT_SECRET_KEY=/ { print "JWT_SECRET_KEY=" ENVIRON["JWT_SECRET_KEY"]; next } /^AETHER_BOOTSTRAP_ADMIN_PASSWORD=/ { print "AETHER_BOOTSTRAP_ADMIN_PASSWORD=" ENVIRON["AETHER_BOOTSTRAP_ADMIN_PASSWORD"]; next } { print }' .env > "$env_tmp"mv "$env_tmp" .env
JWT_SECRET_KEY="$JWT_SECRET_KEY" \ AETHER_BOOTSTRAP_ADMIN_PASSWORD="$AETHER_BOOTSTRAP_ADMIN_PASSWORD" \ docker compose config --quietunset JWT_SECRET_KEY AETHER_BOOTSTRAP_ADMIN_PASSWORDKeep JWT_SECRET_KEY stable. Sign in as admin with the generated bootstrap
value, change the password immediately, then remove
AETHER_BOOTSTRAP_ADMIN_PASSWORD from .env. Public registration stays off
because the example sets AETHER_ALLOW_PUBLIC_REGISTRATION=false.
Start and verify
Section titled “Start and verify”aether services startaether doctoraether services start brings up the Docker Compose stack. The compose file
references pre-built images; on a machine that does not yet have
aetherems:latest, produce it by running ./scripts/build-installer.sh
(which builds the image from cross-compiled binaries) or load a prebuilt
image archive with docker load — see Deployment.
aether doctor checks the required local runtime and exits nonzero if any
required component fails:
- Docker Engine — the daemon is installed and running.
- Six core services — IO, automation, history, API, uplink, and alarm answer their service-specific health routes. Optional cloud or storage dependencies may report degraded without becoming core failures.
- SQLite database —
aether.dbexists, is initialized, and shows its last sync time. - Config files —
global.yaml,io/io.yaml,automation/automation.yaml, andautomation/instances.yamlare present. - Shared memory — the segment file
/dev/shm/aether-rtdb.shmexists and has a readable, valid data-plane header and a fresh IO-writer heartbeat. Missing, stale, truncated, symlinked, or invalid SHM is an error because it is the authoritative live-state plane.AETHER_SHM_PATHoverrides the platform default when an installation deliberately uses another location.
With everything healthy, these ports are listening (see
System Architecture for what each service
does). Only the authenticated API gateway is remotely exposed by the packaged
composition; the other five process APIs listen on 127.0.0.1:
| Service | Port |
|---|---|
| aether-io | 6001 |
| aether-automation | 6002 |
| aether-history | 6004 |
| aether-api | 6005 |
| aether-uplink | 6006 |
| aether-alarm | 6007 |
AetherEdge intentionally exposes no bundled Web UI. Product consoles such as
AetherEMS are deployed independently and enter through aether-api.
First look around
Section titled “First look around”The default template deliberately contains no device channel or instance, so these commands should initially return empty collections:
# 1. The communication channels aether-io is pollingaether channels list
# 2. The device instances aether-automation is servingaether models instances list
# 3. Confirm that no control rule was activated implicitlyaether rules listEvery command accepts --json for structured output, which is the mode AI
agents and scripts should use. Data starts flowing only after an explicit
commissioning step adds and enables a channel; continue with Connect Devices.
Next steps
Section titled “Next steps”- Connect Devices — add a real channel and map its points to instances
- Writing Rules — automate control with the rule engine
- AI Assistants — drive Aether from an AI agent
- Deployment — Docker Compose details and the edge installer