Requirements & Prerequisites

Everything you must provision before running the
quickstart. Each section lists what to create, why AVA needs
it, and the environment variable(s) the value maps to. The complete variable
reference is in configuration.md.


1. Datto AutoTask PSA

1.1 An API-only user

Create a dedicated API user in AutoTask (Admin → Resources/Users → New →
API User). Do not reuse a human login — API users have their own credential
and security level, and a human password change would break the integration.

You will collect four values:

ValueMaps toNotes
API user email/usernameAUTOTASK_API_USERe.g. [email protected]
API user secret/passwordAUTOTASK_API_SECRETAutoTask generates this. May contain a $ — AVA reads it raw from disk to avoid shell mangling; you must wrap it in double quotes in the env file.
API tracking integration codeAUTOTASK_API_INTEGRATION_CODEThe "integration code" AutoTask requires alongside the API user
Zone (data-center) REST URLAUTOTASK_API_ZONE_URLDiscovered in the quickstart — see below

1.2 Security level — which entities the API user must reach

The API user's security level must grant read/write on the entities AVA
touches. AVA exercises exactly these:

AutoTask entityOperations AVA performs
TicketsCreate (new chat), query by id, update (resolution + status on close), read field metadata (picklist discovery)
Ticket Notes (child of Tickets)Create client-facing and internal notes, plus the transcript note
Ticket Attachments (child of Tickets)Upload files shared during the chat
Time EntriesCreate the billed time entry on close
CompaniesQuery by web address and by name (email-domain → company matching)
ContactsQuery by email; create a contact when none exists
ResourcesQuery by email (map each engineer's O365 login to an AutoTask resource)
Billing Codes (picklist)Query to resolve a valid billing code / work type for time entries

Grant the Web Services API permission and the ability to create/edit
tickets, notes, time entries, attachments, contacts, and to read companies and
resources. Start from a stock "API User (system)" security level and confirm it
covers the above; if your AutoTask admin locks down security levels, verify
each entity explicitly. An overly restrictive level typically surfaces as a
403 on one specific entity while everything else works.

Account-lockout caution: repeated 401s from a mistyped/mangled secret
can lock the AutoTask API user. If you hit persistent 401s, verify the
account isn't locked in AutoTask admin before assuming a code problem.

1.3 Picklist IDs and default ticket values

AutoTask picklist IDs (status, priority, queue, source, ticket type, issue
type, note publish value, billing code) are specific to your AutoTask
instance
— never copy another instance's numbers. The quickstart runs
npx tsx scripts/discover-picklists.ts to list yours. These map to:

  • AUTOTASK_DEFAULT_TICKET_STATUS, AUTOTASK_DEFAULT_TICKET_PRIORITY,
    AUTOTASK_DEFAULT_TICKET_QUEUE_ID, AUTOTASK_DEFAULT_TICKET_SOURCE,
    AUTOTASK_DEFAULT_TICKET_TYPE
  • AUTOTASK_PRIORITY_P1AUTOTASK_PRIORITY_P4 (triage priority → AT priority)
  • AUTOTASK_NOTE_PUBLISH_EXTERNAL — the note publish value. This is a
    per-instance picklist
    ; the universally valid default is 1 ("Internal
    Only"). Never hardcode another instance's value.
  • AUTOTASK_DEFAULT_ROLE_ID — the resource role ID used for time entries. If
    unset, AVA warns (it does not fail) and uses a built-in fallback that will
    not match your instance — set this for your own instance.

1.4 A catchall company (strongly recommended)

When a client chats in from an email domain not tied to any AutoTask company
(personal Gmail, etc.), AVA files the ticket under a catchall company you
designate — set AUTOTASK_CATCHALL_COMPANY_ID to that company's numeric ID.
If it is left unset, unknown-domain chats get no ticket at start time and
fall into a degraded recovery path at close. Pick (or create) a company for
this and note its ID; the quickstart shows how to find one with
scripts/test-autotask.ts.


2. Microsoft Entra ID (O365)

Engineers authenticate with Entra ID. You need an app registration and a
security group.

2.1 App registration

In the Entra admin center → App registrations → New registration:

ItemMaps toNotes
Application (client) IDAZURE_AD_CLIENT_ID
Directory (tenant) IDAZURE_AD_TENANT_ID
A client secretAZURE_AD_CLIENT_SECRETCreate under Certificates & secrets; store securely
Redirect URI (Web)AZURE_AD_REDIRECT_URIMust be exactly https://<your-host>/api/auth/callback

The OAuth flow is server-side (@azure/msal-node) — the browser never
holds Azure tokens, only AVA's own signed session cookie. The requested scopes
are openid, profile, email, User.Read.

2.2 Groups claim — engineer authorization

Sign-in is allowed only for members of one Entra security group. AVA reads
the groups claim from the Entra ID token and checks that it includes
your group's object ID. You must therefore:

  1. Create (or choose) a security group and add your engineers to it. Note its
    object IDENGINEERING_GROUP_ID.
  2. Configure the app registration to emit the groups claim in the ID
    token: App registration → Token configuration → Add groups claim
    (Security groups), for the ID token.

The check is fail-closed: if the groups claim is missing, malformed, does
not contain your group, or ENGINEERING_GROUP_ID is unset, sign-in is denied.

Large-directory note: if an engineer is a member of many groups, Entra
can switch to an overage "group source" reference instead of emitting the
full groups array in the token. If you have engineers in very many groups,
restrict the emitted groups to those assigned to the application to keep the
claim inline.

2.3 Resource mapping (no config, but plan for it)

On an engineer's first sign-in, AVA looks up an AutoTask Resource
whose email matches their O365 login and stores the mapping, so time entries
attribute to the right person. Make sure each engineer's O365 sign-in email
matches their AutoTask resource email. If there's no match, the engineer can
still sign in — time entries just fall back to the default role and won't be
attributed to their resource. Full onboarding walkthrough:
first-login.md.


3. Google reCAPTCHA v3

The public chat form is protected by reCAPTCHA v3 (invisible scoring).
Create a reCAPTCHA v3 site at the Google reCAPTCHA admin console for your
public hostname and collect:

ValueMaps toExposure
Site keyNEXT_PUBLIC_RECAPTCHA_SITE_KEYPublic — baked into the browser bundle at build time
Secret keyRECAPTCHA_SECRET_KEYSecret — server-side verification only

Verification is fail-closed in production: if the secret is missing or
Google is unreachable, chat starts are refused rather than waved through.


4. SMTP2GO (outbound email)

AVA sends transactional email through SMTP2GO: the after-hours "email us a
ticket" fallback, engineer feedback, and the weekly survey report. Create an
SMTP2GO account and an SMTP user, then collect:

ValueMaps toDefault
SMTP hostSMTP2GO_HOSTmail.smtp2go.com
SMTP portSMTP2GO_PORT2525
SMTP usernameSMTP2GO_USER(required to boot)
SMTP passwordSMTP2GO_PASSWORD(required to boot)
From addressSMTP2GO_FROM(no default — set it, e.g. [email protected]; with it unset, every send fails closed with a logged error)

You must also decide where email lands:

  • SUPPORT_FALLBACK_EMAIL — the recipient for the after-hours email-a-ticket
    form. Required at boot — there is no vendor default, and the container
    refuses to start without it, so a misconfigured deployment can never
    silently mail the wrong inbox.
  • FEEDBACK_EMAIL, REPORTS_EMAIL — optional; when unset those features
    skip the send (fail closed with a logged error) rather than defaulting
    anywhere. See configuration.md.

5. Docker host

AVA ships as a single container image (Next.js 16 + Socket.io + SQLite).

AspectRequirement
RuntimeDocker (with Compose). The app container targets ~250 MB RAM; the production template caps it at mem_limit: 768m.
Sizing1 vCPU / 2 GB RAM is comfortable for a small–mid helpdesk. Reference deployment: a single 2-vCPU / 8 GB host with plenty of headroom.
DiskA few GB free at runtime. --no-cache image rebuilds accumulate build cache — keep ≥ 8 GB free if you rebuild in place (the deploy flow in production-deployment.md prunes and checks before every build).
NetworkingA public DNS hostname pointing at the host, ports 80/443 open.
TLSHTTPS is required (Entra redirect URI, secure WebSockets). The shipped production template terminates TLS with an nginx + Let's Encrypt (certbot) pair with automatic renewal — see production-deployment.md; day-2 operating practice is in operations.md. You may instead terminate TLS at your own load balancer / reverse proxy.
PersistenceSQLite lives on a Docker volume (ava-data/app/data); uploads on ava-uploads/app/uploads. Back these up.
Proxy trustIf AVA sits behind a reverse proxy (it does, in the shipped template), you must set NGINX_TRUSTED_PROXY=1. Trust in X-Forwarded-For is opt-in only — with the variable unset, AVA never trusts the header and per-IP rate limiting collapses to one shared bucket. Details in production-deployment.md.

You will also generate one secret yourself: NEXTAUTH_SECRET, the key that
signs every session token. It must be at least 32 characters and not a
placeholder — both are enforced at container start (the entrypoint refuses
to boot otherwise). Generate it with openssl rand -base64 48.


Checklist

  • AutoTask API user created; security level covers Tickets, Ticket Notes,
    Ticket Attachments, Time Entries, Companies, Contacts, Resources,
    Billing Codes.
  • AutoTask integration code recorded.
  • A catchall company chosen; its numeric ID recorded.
  • Entra app registration created; client ID / tenant ID / client secret /
    redirect URI recorded.
  • Entra security group created, engineers added, groups claim enabled
    on the ID token; group object ID recorded.
  • reCAPTCHA v3 site + secret keys generated.
  • SMTP2GO account + SMTP user created; SMTP2GO_FROM sender address and
    SUPPORT_FALLBACK_EMAIL recipient decided.
  • NEXTAUTH_SECRET generated (≥ 32 chars, openssl rand -base64 48).
  • Docker host provisioned with a TLS-terminated public hostname.

Next: quickstart.md.


Did this page help you?