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:
| Value | Maps to | Notes |
|---|---|---|
| API user email/username | AUTOTASK_API_USER | e.g. [email protected] |
| API user secret/password | AUTOTASK_API_SECRET | AutoTask 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 code | AUTOTASK_API_INTEGRATION_CODE | The "integration code" AutoTask requires alongside the API user |
| Zone (data-center) REST URL | AUTOTASK_API_ZONE_URL | Discovered 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 entity | Operations AVA performs |
|---|---|
| Tickets | Create (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 Entries | Create the billed time entry on close |
| Companies | Query by web address and by name (email-domain → company matching) |
| Contacts | Query by email; create a contact when none exists |
| Resources | Query 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 persistent401s, 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_TYPEAUTOTASK_PRIORITY_P1…AUTOTASK_PRIORITY_P4(triage priority → AT priority)AUTOTASK_NOTE_PUBLISH_EXTERNAL— the notepublishvalue. This is a
per-instance picklist; the universally valid default is1("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:
| Item | Maps to | Notes |
|---|---|---|
| Application (client) ID | AZURE_AD_CLIENT_ID | |
| Directory (tenant) ID | AZURE_AD_TENANT_ID | |
| A client secret | AZURE_AD_CLIENT_SECRET | Create under Certificates & secrets; store securely |
| Redirect URI (Web) | AZURE_AD_REDIRECT_URI | Must 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:
- Create (or choose) a security group and add your engineers to it. Note its
object ID →ENGINEERING_GROUP_ID. - Configure the app registration to emit the
groupsclaim 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
fullgroupsarray 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:
| Value | Maps to | Exposure |
|---|---|---|
| Site key | NEXT_PUBLIC_RECAPTCHA_SITE_KEY | Public — baked into the browser bundle at build time |
| Secret key | RECAPTCHA_SECRET_KEY | Secret — 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:
| Value | Maps to | Default |
|---|---|---|
| SMTP host | SMTP2GO_HOST | mail.smtp2go.com |
| SMTP port | SMTP2GO_PORT | 2525 |
| SMTP username | SMTP2GO_USER | (required to boot) |
| SMTP password | SMTP2GO_PASSWORD | (required to boot) |
| From address | SMTP2GO_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. Seeconfiguration.md.
5. Docker host
AVA ships as a single container image (Next.js 16 + Socket.io + SQLite).
| Aspect | Requirement |
|---|---|
| Runtime | Docker (with Compose). The app container targets ~250 MB RAM; the production template caps it at mem_limit: 768m. |
| Sizing | 1 vCPU / 2 GB RAM is comfortable for a small–mid helpdesk. Reference deployment: a single 2-vCPU / 8 GB host with plenty of headroom. |
| Disk | A 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). |
| Networking | A public DNS hostname pointing at the host, ports 80/443 open. |
| TLS | HTTPS 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. |
| Persistence | SQLite lives on a Docker volume (ava-data → /app/data); uploads on ava-uploads → /app/uploads. Back these up. |
| Proxy trust | If 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_FROMsender address and
SUPPORT_FALLBACK_EMAILrecipient decided. -
NEXTAUTH_SECRETgenerated (≥ 32 chars,openssl rand -base64 48). - Docker host provisioned with a TLS-terminated public hostname.
Next: quickstart.md.
Updated about 1 hour ago