> ## Documentation Index
> Fetch the complete documentation index at: https://oxy.tech/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Run Airhouse locally with Docker Compose, create a database, and run your first queries.

<Warning>
  **Access required.** Airhouse is proprietary and not open source. The Airhouse container image is provided by Oxygen once access is granted. [Contact Oxygen](https://oxygen-hq.com/contact) to get access, or see [Getting access](./access).
</Warning>

This guide runs a complete Airhouse stack on your machine: Postgres for the catalog, MinIO for S3-compatible storage, and the Airhouse server. You then create a database and a user, connect with `psql`, and run a few queries.

## Prerequisites

* Access to Airhouse from Oxygen, and the image tag to use
* Docker with Docker Compose
* `psql` (any recent PostgreSQL client)
* `curl`

<Steps>
  <Step title="Log in to the registry">
    The Airhouse image is published to the GitHub Container Registry at `ghcr.io/oxy-hq/airhouse`. If Oxygen gave you registry credentials, log in with them:

    ```bash theme={null}
    docker login ghcr.io
    ```
  </Step>

  <Step title="Create a Compose file">
    Save the following as `docker-compose.yml` in an empty directory:

    ```yaml docker-compose.yml theme={null}
    services:
      postgres:
        image: postgres:18
        environment:
          POSTGRES_DB: airhouse
          POSTGRES_USER: airhouse
          POSTGRES_PASSWORD: airhouse
          PGDATA: /var/lib/postgresql/18/docker
        volumes:
          - pgdata:/var/lib/postgresql
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U airhouse"]
          interval: 2s
          timeout: 5s
          retries: 10

      minio:
        # MinIO RELEASE.2026-09-22T19-25-18Z.
        image: ghcr.io/oxy-hq/minio:RELEASE.2026-09-22T19-25-18Z@sha256:4692462f35d97d7e82c30371d82f057703c5d9489bcae726010594c812f2d285
        # Root keeps a data volume written by an older MinIO image readable.
        user: "0:0"
        command: server /data --console-address ":9001"
        environment:
          MINIO_ROOT_USER: minioadmin
          MINIO_ROOT_PASSWORD: minioadmin
        volumes:
          - miniodata:/data
        healthcheck:
          test: ["CMD", "mc", "ready", "local"]
          interval: 2s
          timeout: 5s
          retries: 10

      # Creates the S3 bucket Airhouse writes Parquet files to.
      createbucket:
        image: ghcr.io/oxy-hq/minio:RELEASE.2026-09-22T19-25-18Z@sha256:4692462f35d97d7e82c30371d82f057703c5d9489bcae726010594c812f2d285
        depends_on:
          minio:
            condition: service_healthy
        entrypoint:
          - sh
          - -c
          - |
            mc alias set local http://minio:9000 minioadmin minioadmin
            mc mb local/airhouse --ignore-existing

      # Creates the database that holds the list of Airhouse databases and users.
      createcpdb:
        image: postgres:18
        depends_on:
          postgres:
            condition: service_healthy
        environment:
          PGPASSWORD: airhouse
        entrypoint:
          - sh
          - -c
          - |
            psql -h postgres -U airhouse -d airhouse -tc \
              "SELECT 1 FROM pg_database WHERE datname='airhouse_cp'" | grep -q 1 \
              || psql -h postgres -U airhouse -d airhouse -c "CREATE DATABASE airhouse_cp"

      airhouse:
        image: ghcr.io/oxy-hq/airhouse:<version>   # the tag Oxygen gave you, for example 0.1.51
        command: ["server"]
        depends_on:
          createbucket:
            condition: service_completed_successfully
          createcpdb:
            condition: service_completed_successfully
        environment:
          AIRHOUSE_CP_DATABASE_URL: postgres://airhouse:airhouse@postgres:5432/airhouse_cp?sslmode=disable
          AIRHOUSE_CP_CATALOG_ADMIN_URL: postgres://airhouse:airhouse@postgres:5432/airhouse?sslmode=disable
          AIRHOUSE_CP_ADMIN_TOKEN: local-admin-token
          S3_ENDPOINT: http://minio:9000
          S3_BUCKET: airhouse
          S3_ACCESS_KEY: minioadmin
          S3_SECRET_KEY: minioadmin
          S3_REGION: us-east-1
        ports:
          - "5445:5445"   # Postgres wire protocol
          - "8080:8080"   # HTTP: Admin API, health, metrics

    volumes:
      pgdata:
      miniodata:
    ```

    <Warning>
      Replace `<version>` with your release tag before starting. The passwords and the `local-admin-token` value above are for local testing only. Use strong, secret values for anything else. See [Installation](./installation) and [Configuration](./reference/configuration).
    </Warning>
  </Step>

  <Step title="Start the stack">
    ```bash theme={null}
    docker compose up -d
    ```

    Wait until the server reports healthy:

    ```bash theme={null}
    curl -fsS http://localhost:8080/healthz
    ```
  </Step>

  <Step title="Create a database and a user">
    Airhouse databases and users are managed through the Admin API on port `8080`. Create a database named `demo`, then a user `alice` with the `admin` role:

    ```bash theme={null}
    curl -X POST http://localhost:8080/admin/v1/tenants \
      -H 'Authorization: Bearer local-admin-token' \
      -H 'Content-Type: application/json' \
      -d '{"id": "demo"}'

    curl -X POST http://localhost:8080/admin/v1/tenants/demo/users \
      -H 'Authorization: Bearer local-admin-token' \
      -H 'Content-Type: application/json' \
      -d '{"username": "alice", "password": "alice-password", "role": "admin"}'
    ```
  </Step>

  <Step title="Connect with psql">
    ```bash theme={null}
    psql "host=localhost port=5445 dbname=demo user=alice"
    ```

    Enter `alice-password` when prompted. The `dbname` is the database you created in the previous step.
  </Step>

  <Step title="Run your first queries">
    Create a table in the `lake` catalog, load some rows, and query them:

    ```sql theme={null}
    CREATE TABLE lake.main.events (
      id         INTEGER,
      kind       TEXT,
      amount     DOUBLE,
      created_at TIMESTAMP
    );

    INSERT INTO lake.main.events VALUES
      (1, 'signup',   0,     '2026-01-01 09:00'),
      (2, 'purchase', 42.50, '2026-01-01 09:05'),
      (3, 'purchase', 17.25, '2026-01-02 14:30'),
      (4, 'refund',   -5.00, '2026-01-03 11:00');

    SELECT kind, count(*) AS events, sum(amount) AS total
    FROM lake.main.events
    GROUP BY kind
    ORDER BY total DESC;
    ```

    Update and delete rows just like in Postgres:

    ```sql theme={null}
    UPDATE lake.main.events SET amount = 45.00 WHERE id = 2;
    DELETE FROM lake.main.events WHERE kind = 'refund';
    ```

    List your tables with `\dt`. Your data is now stored as Parquet files in the `airhouse` bucket, and survives restarts of the stack.
  </Step>
</Steps>

## Clean up

```bash theme={null}
docker compose down      # stop, keep data
docker compose down -v   # stop and delete all data
```

## Next steps

* [Connect from drivers and BI tools](./connect/drivers)
* [Tables and storage](./guides/tables-and-storage): transactions, time travel, and schema changes
* [Databases and users](./guides/managing-databases): manage databases and users with the Admin API


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.