For this project, use AWS App Runner as the default deployment target.
When a change needs to be deployed for shared use, do not stop at a local Docker rebuild; deploy the stack through App Runner unless someone explicitly asks for local-only verification.
This project can be shared as a hosted web app for a small team by running three public services:
frontend: Next.js web appbackend: FastAPI APImemory-server: Redis Agent Memory Server
For a two-person testing setup, the simplest AWS path is:
AWS App RunnerforfrontendAWS App RunnerforbackendAWS App Runnerformemory-serverAmazon ElastiCache for Redis OSSor your existing Redis providerAWS Secrets Managerfor API keys
If you want lower-latency conversational responses without calling a public LLM API,
run Ollama on a small EC2 instance in the same AWS region as the backend and point
the backend at it with OLLAMA_URL.
Colleague Browser
-> Frontend App Runner
-> Backend App Runner
-> Memory Server App Runner
-> Redis
Use HTTPS everywhere so browser microphone access works correctly.
For Google login, create a Google OAuth web client and copy its client ID into both:
GOOGLE_CLIENT_IDNEXT_PUBLIC_GOOGLE_CLIENT_ID
Also add these Authorized JavaScript origins in Google Cloud Console:
http://localhost:3000https://<frontend-service-url>
- Rotate any AWS secret that was pasted into chat or another unsafe place.
- Store app secrets in AWS Secrets Manager instead of source control.
- Decide whether you want to keep using your current Redis provider or move to AWS Redis later.
Create an App Runner service from the public image:
- Image:
redislabs/agent-memory-server:latest - Port:
8000 - Start command:
agent-memory api --host 0.0.0.0 --port 8000 --task-backend asyncioEnvironment variables:
OPENAI_API_KEY=<from Secrets Manager>
REDIS_URL=<your redis url>
GENERATION_MODEL=gpt-4o-mini
After deployment, note the service URL:
https://<memory-service-url>
Create an App Runner service from this repository using docker/Dockerfile.backend.
- Port:
8080 - Root directory: repository root
- Dockerfile path:
docker/Dockerfile.backend
Environment variables:
SARVAM_API_KEY=<from Secrets Manager>
OPENAI_API_KEY=<from Secrets Manager>
REDIS_URL=<your redis url>
GOOGLE_CLIENT_ID=<your google oauth client id>
MEMORY_SERVER_URL=https://<memory-service-url>
CORS_ORIGINS=https://<frontend-service-url>
OLLAMA_URL=
OLLAMA_MODEL=llama3.2
Notes:
- Leave
OLLAMA_URLempty if you are not hosting Ollama. - If you host Ollama on EC2, use the EC2 private IP here, for example
OLLAMA_URL=http://10.0.12.34:11434. - Smallest EC2 instance I would trust for
llama3.2:t3.largein the same region as the backend. AWS documentst3.largewith2 vCPUsand8 GiBmemory, which is a practical floor for a warm small model in this app. - If Redis is private inside a VPC, attach an App Runner VPC connector.
Recommended shape:
- Region: same as backend, currently
us-east-2 - Instance type:
t3.large - OS: Ubuntu 24.04 LTS
- Model:
llama3.2
Why:
- the model is small enough for CPU inference
- same-region traffic keeps backend-to-Ollama latency low
- keeping the model warm matters more than shaving a few milliseconds of network time
Bootstrap script:
After EC2 is ready:
- set
OLLAMA_URL=http://<ollama-private-ip>:11434in.env - run
./infra/terraform/deploy.sh - verify the backend can reach Ollama from the logs
After deployment, note the backend URL:
https://<backend-service-url>
Create an App Runner service from this repository using docker/Dockerfile.frontend.
- Port:
3000 - Root directory: repository root
- Dockerfile path:
docker/Dockerfile.frontend
Build argument:
NEXT_PUBLIC_API_URL=https://<backend-service-url>
NEXT_PUBLIC_GOOGLE_CLIENT_ID=<your google oauth client id>
After deployment, note the frontend URL:
https://<frontend-service-url>
Then update the backend CORS_ORIGINS setting to match that frontend URL exactly.
- Deploy
memory-server - Deploy
backend - Deploy
frontend - Update backend
CORS_ORIGINSwith the final frontend URL - Test recording, chat, and mood save from your browser
- Share the frontend URL with your colleague
GET /api/healthreturns healthy from the backend- microphone permission prompt appears in the browser
- voice recording transcribes successfully
- chat responses return with audio
- your colleague sees their own data, not yours
If App Runner feels too expensive for three always-on services, run the stack on one EC2 instance with Docker Compose and put HTTPS in front with Caddy or Nginx. That is cheaper, but more hands-on than App Runner.