> For the complete documentation index, see [llms.txt](https://docs.kawa.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kawa.ai/11_00_exploitation/single-appliance-deployment.md).

# Single Appliance Deployment

KAWA runs on one machine, as a single `docker compose` package. Everything it stores lives on a dedicated persistent volume that survives the machine, and periodic snapshots of that volume are the backup. There is no cluster and no managed database: one appliance to operate, replaced rather than repaired when it fails.

This is the simplest production topology. It fits a team that runs KAWA inside its own network, with a single instance serving a bounded set of users, and accepts a recovery measured in minutes rather than an active/active setup. For the multi-datacenter design, see [Disaster Recovery Architecture](/11_00_exploitation/disaster-recovery-architecture.md).

The reference below is on AWS. The same design applies on GCP, Azure or on-premise with the equivalent services: a VM, a persistent disk with snapshots, a secret store and an internal load balancer.

## 1. Overview

Users reach KAWA through an internal load balancer over HTTPS. The instance mounts the data volume on `/data`, fetches its configuration secrets from the secret store with its own IAM role, and starts the KAWA package. It can run without any internet access: the KAWA images come from an internal container registry, the Python packages for user scripts from an internal PyPI mirror, and the identity provider and SMTP relay, when used, are reached on the intranet.

<div data-with-frame="true"><figure><img src="https://2701963830-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6wXylCyyATfFd8yjjWTn%2Fuploads%2Fgit-blob-43c868d0772c0dba7e79e5addc0be748f4fcc318%2FKAWA-single-appliance-diagram.svg?alt=media" alt=""><figcaption></figcaption></figure></div>

| Component                              | Role                                                                                                                                                                                          |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Appliance** (EC2 instance)           | Runs KAWA as one `docker compose` package. Holds nothing of value itself: everything is on the data volume or in the secret store.                                                            |
| **Data volume** (EBS)                  | All KAWA state, mounted on `/data`. Encrypted, kept when the instance is terminated, in the same availability zone as the instance.                                                           |
| **Snapshots** (Data Lifecycle Manager) | Taken every N hours. Restored into a new volume in any availability zone; copied to a second region for disaster recovery.                                                                    |
| **Secret store** (Secrets Manager)     | The KAWA environment: encryption keys, database passwords, tokens. Fetched at boot by the instance role, never stored on the volume.                                                          |
| **Internal load balancer** (ALB)       | The only inbound path. Terminates TLS and forwards to the instance on port `8080`, health check `GET /`.                                                                                      |
| **Internal registries**                | A container registry holding the KAWA images at the deployed version, and a PyPI mirror for user scripts. The KAWA registry and pypi.org can be used instead when internet access is allowed. |
| **Identity provider**, optional        | OIDC single sign-on. KAWA's own email and password login works without it.                                                                                                                    |
| **SMTP relay**, optional               | Alerting and notifications. Without it, emails go to the server log.                                                                                                                          |

## 2. Boot and upgrade

A systemd unit on the appliance runs the sequence at every boot: mount `/data`, fetch the secret with the instance role, write the environment file, `docker compose up`. Nothing else runs on the machine.

An upgrade is a new version tag in the environment and a `docker compose pull`. Take a snapshot of the data volume first; rolling back is the previous tag plus that snapshot.

## 3. Prerequisites

**Network.** A VPC with private subnets for the instance and the load balancer, and a VPC endpoint for the secret store. No internet gateway is needed.

**Instance.** AMD64, any Linux distribution with docker and the docker compose v2 plugin, `git`, `python3` with `venv` and `openssl`. An EBS-only instance type, so that EC2 auto-recovery applies.

**Data volume.** A separate gp3 volume, encrypted, `DeleteOnTermination = false`, tagged for the snapshot policy, in the same availability zone as the instance. Sized as in section 4.

**Load balancer.** An internal Application Load Balancer with a certificate for the KAWA URL and the matching DNS record. Target: the instance on port `8080`.

**Security group.** Inbound `8080` from the load balancer only, `22` from a bastion or SSM instead. Outbound `443` to the registries, the identity provider and the VPC endpoint, `465` or `587` to the SMTP relay.

**IAM.** An instance role with `secretsmanager:GetSecretValue` on the KAWA secret, plus SSM access if used.

**Snapshot policy.** A Data Lifecycle Manager policy on the volume tag, with the interval and retention agreed.

**Identity provider, optional.** A web application on the provider with the authorization code grant, refresh tokens and the scopes `openid profile email offline_access`. Redirect URI: `https://<kawa-url>/authentication/login?credentialType=OAUTH2_TOKEN`. Hand over the client id, the client secret and the issuer URL. Users need a verified email on the provider.

**SMTP relay, optional.** Host, port (`465` SSL or `587` STARTTLS), username and password, with the KAWA sender address allowed on the relay.

## 4. Sizing

Three rules drive the size of the appliance:

* **Memory** follows the data KAWA holds: RAM ≈ compressed data, plus about 20 GB for the platform itself. Data compresses roughly 10× inside KAWA (about 100 bytes per row for a wide table).
* **Disk** is the raw input files kept in the file store, plus the compressed data, plus headroom. EBS volumes grow online, so start reasonably and grow.
* **CPU** is rarely the driver. The extra cores buy concurrency for analysts and Python scripts, not batch throughput.

Worked example, 1M rows a day kept as daily history for 3 years, 60 to 80 fields per row:

|             | `r7a.4xlarge`                                                      | `r7a.8xlarge`                                                                                                   |
| ----------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| vCPU / RAM  | 16 / 128 GiB                                                       | 32 / 256 GiB                                                                                                    |
| Data held   | 750M rows, about 75 GB compressed, about 750 GB of raw input files | same                                                                                                            |
| Data volume | 1.5 TB gp3, 6 000 IOPS / 500 MB/s                                  | same                                                                                                            |
| Fits        | 3 years of history, the daily batch, a handful of analysts         | the same, plus heavy Python scripts, many concurrent analysts, intraday re-snapshots, or history beyond 3 years |

Moving from one size to the other is a stop and start with a different instance type, since all data sits on the separate volume.

## 5. Disaster recovery

The appliance itself is disposable; the data volume and the secret are what recovery needs. Three layers, cheapest first:

| Failure                                | Recovery                                                                                                                 | RTO              | RPO                   |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | ---------------- | --------------------- |
| Hardware fault                         | EC2 auto-recovery restarts the same instance with the same volume. Nothing to do.                                        | minutes          | none                  |
| Instance broken (OS, failed upgrade)   | Launch a new instance in the same availability zone, attach the data volume, start. Re-register it on the load balancer. | about 15 minutes | none                  |
| Volume lost, or availability zone down | Create a volume from the latest snapshot in another availability zone, then as above.                                    | about 30 minutes | the snapshot interval |
| Region down                            | Snapshots copied to a second region, secret replicated there, the same build in that region.                             | hours            | the copy interval     |

Snapshots are crash-consistent: KAWA recovers from them as after a power cut. For a clean snapshot before an upgrade, stop KAWA, snapshot, start again. Keep the secret replicated wherever the snapshots are copied: a volume without its secret cannot be read. Test the restore, volume and secret together, on a schedule.

For an active/active deployment across two datacenters, with replicated databases and a near-zero RPO, see [Disaster Recovery Architecture](/11_00_exploitation/disaster-recovery-architecture.md).
