Skip to content

Commit d293145

Browse files
committed
docs: update README, CHANGELOG, add presentation
- README: mark all features as working, update security section - README: document API key auth, nginx proxy, encryption - CHANGELOG: add security hardening entries
1 parent f3918b2 commit d293145

2 files changed

Lines changed: 98 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1313
- `modules/lambda/` - Lambda function with CloudWatch log group
1414
- `modules/api_gateway/` - API Gateway REST API with Lambda integration
1515
- `modules/monitoring/` - CloudWatch metric filter and error alarm
16+
- `modules/ec2/` - EC2 instance running Ollama for AI inference
17+
- **Ollama AI Integration**: Self-hosted LLM on EC2 (external API)
18+
- EC2 instance (t3.large) running Ollama with tinyllama model
19+
- Lambda calls `POST /api/chat` for AI-powered chat responses
20+
- Elastic IP for stable endpoint across stop/start cycles
21+
- Model persistence: S3 sync on shutdown, restore on boot
22+
- Lifecycle management script: `scripts/manage-ollama.sh`
23+
- Error handling with timeouts, structured logging, graceful fallback
1624
- **Observability**: Added structured logging and monitoring
1725
- Structured JSON logging in `handler.py` (level, timestamp, action, outcome, request_id)
1826
- CloudWatch metric filter for ERROR-level logs (`{ $.level = "ERROR" }`)
@@ -28,12 +36,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2836
- **Documentation**: Added observability and remote state sections to README
2937

3038
### Changed
31-
- **handler.py**: Replaced all `print()` calls with `StructuredLogger` for JSON-formatted logs
32-
- **main.tf**: Migrated from inline resources to module calls, added monitoring module
33-
- **outputs.tf**: Updated outputs to reference module outputs, added monitoring outputs
39+
- **handler.py**: Replaced placeholder with actual Ollama AI integration, updated `/status` and `/help`
40+
- **main.tf**: Migrated from inline resources to module calls, added monitoring and EC2 modules
41+
- **outputs.tf**: Updated outputs to reference module outputs, added monitoring and EC2 outputs
42+
- **Lambda timeout**: Increased from 30s to 60s to accommodate AI inference
3443
- **provider.tf**: Added remote state backend configuration (commented)
3544

3645
### Security
46+
- **Ollama API Key Auth**: Nginx reverse proxy on EC2 validates `X-API-Key` header (auto-generated 32-char key)
47+
- Ollama binds to localhost only (`127.0.0.1:11435`), nginx proxies on port 11434
48+
- Requests without valid API key receive HTTP 401
49+
- **S3 Hardening**: Added public access block (all 4 settings) and AES256 server-side encryption
50+
- **DynamoDB Hardening**: Enabled server-side encryption and point-in-time recovery
51+
- **Sensitive Outputs**: Marked `api_gateway_url`, `ollama_public_ip`, `ollama_url`, `webhook_setup_command` as sensitive
52+
- **Input Validation**: Added 4000-char max message length check in handler.py
53+
- **Conversation Context Limit**: Limited Ollama context to last 10 messages to prevent CPU inference timeouts
54+
- **.gitignore**: Added `*.pem`, `*.key`, `*.crt`, `.env`, `*.secret` patterns
3755
- **IAM**: Documented least-privilege policy in `docs/GAP_ANALYSIS.md`
3856
- Note: AWS Academy LabRole used due to environment constraints
3957
- Production policy template provided for non-Academy deployments

README.md

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This project deploys a **Telegram chatbot** on AWS using Infrastructure as Code (Terraform). It provisions **S3 buckets** for storing archived chat history, **DynamoDB tables** for managing user sessions, **Lambda** for serverless processing, and **API Gateway** for real-time webhook integration with Telegram.
44

5-
> **⚠️ Status**: Currently in development. Ollama AI integration (backend models) is not yet implemented. Session management, commands, archive features, and Telegram connectivity are fully functional.
5+
> **Status**: Fully functional. Ollama AI integration is live on EC2 with API key authentication. Session management, commands, archive features, and AI chat are all working.
66
77
---
88

@@ -19,6 +19,7 @@ This project deploys a **Telegram chatbot** on AWS using Infrastructure as Code
1919
* [Bot Commands](#bot-commands)
2020
* [Project Structure](#project-structure)
2121
* [Module Structure](#module-structure)
22+
* [External API Integration](#external-api-integration)
2223
* [Data Storage](#data-storage)
2324
* [Observability](#observability)
2425
* [Verification](#verification)
@@ -39,24 +40,24 @@ This project creates a serverless Telegram bot running on AWS. When users send m
3940
- ✅ Archive system (`/archive`, `/listarchives`, `/export`, file import)
4041
- ✅ DynamoDB for live session storage
4142
- ✅ S3 for archived session storage
42-
- Ollama AI integration (planned for next phase)
43+
- Ollama AI integration with API key authentication
4344

4445
---
4546

4647
## Architecture
4748

4849
```
49-
┌─────────────┐ ┌─────────────────┐ ┌────────────────┐
50-
│ Telegram │─────▶│ API Gateway │─────▶│ Lambda │
51-
│ User │◀─────│ (webhook) │◀─────│ (handler.py) │
52-
└─────────────┘ └─────────────────┘ └────────────────┘
53-
54-
┌───────────────────────┴───────────────────────┐
55-
▼ ▼
56-
┌─────────────────┐ ─────────────────┐
57-
│ DynamoDB │ S3
58-
│(active sessions)│ │ (archived chats)│
59-
└─────────────────┘ ─────────────────┘
50+
┌─────────────┐ ┌─────────────────┐ ┌────────────────┐ ┌─────────────────┐
51+
│ Telegram │─────▶│ API Gateway │─────▶│ Lambda │─────▶│ EC2 (Ollama) │
52+
│ User │◀─────│ (webhook) │◀─────│ (handler.py) │◀─────│ AI inference │
53+
└─────────────┘ └─────────────────┘ └────────────────┘ └─────────────────┘
54+
55+
┌───────────────────────┴──────────┐ │
56+
57+
┌─────────────────┐ ┌─────────────────────────────┐
58+
│ DynamoDB │ S3
59+
│(active sessions)│ │ (archived chats + AI models)│
60+
└─────────────────┘ └─────────────────────────────┘
6061
```
6162

6263
**Flow:**
@@ -89,7 +90,7 @@ This project creates a serverless Telegram bot running on AWS. When users send m
8990
| Send JSON file | Import archive from file | ✅ Working |
9091
| `/status` | Check bot status | ✅ Working |
9192
| `/echo <text>` | Echo back text (test command) | ✅ Working |
92-
| Chat messages | Send to AI model | ⏳ Not implemented |
93+
| Chat messages | Send to AI model | ✅ Working |
9394

9495
---
9596

@@ -338,7 +339,8 @@ If the bot stops responding after redeployment:
338339
│ ├── dynamodb/ # DynamoDB table module
339340
│ ├── lambda/ # Lambda function module
340341
│ ├── api_gateway/ # API Gateway module
341-
│ └── monitoring/ # CloudWatch metric filter + alarm
342+
│ ├── monitoring/ # CloudWatch metric filter + alarm
343+
│ └── ec2/ # EC2 Ollama inference server
342344
├── backend-setup/ # Remote state infrastructure
343345
│ └── main.tf # S3 bucket + DynamoDB for state
344346
├── terraform.tfvars.example # Example configuration
@@ -349,7 +351,8 @@ If the bot stops responding after redeployment:
349351
├── scripts/
350352
│ ├── setup-webhook.sh # Telegram webhook setup
351353
│ ├── view-data.sh # View S3/DynamoDB contents
352-
│ └── test-observability.sh # Verify logging, metrics, alarms
354+
│ ├── test-observability.sh # Verify logging, metrics, alarms
355+
│ └── manage-ollama.sh # Start/stop Ollama EC2 instance
353356
├── docs/
354357
│ ├── GAP_ANALYSIS.md # Best practices analysis
355358
│ └── DEMO_CHEATSHEET.md # Demo commands reference
@@ -417,6 +420,64 @@ Creates a REST API with Lambda integration.
417420
| `lambda_invoke_arn` | Lambda invoke ARN | Required |
418421
| `stage_name` | Deployment stage | `dev` |
419422

423+
### EC2 Module (`modules/ec2/`)
424+
425+
Creates an EC2 instance running Ollama for AI inference.
426+
427+
| Variable | Description | Default |
428+
|----------|-------------|---------|
429+
| `instance_name` | Name tag for the instance | Required |
430+
| `instance_type` | EC2 instance type | `t3.large` |
431+
| `ollama_model` | Model to pull on first boot | `tinyllama` |
432+
| `models_s3_bucket` | S3 bucket for model persistence | Required |
433+
| `ssh_allowed_cidr` | CIDR for SSH access | `0.0.0.0/0` |
434+
435+
---
436+
437+
## External API Integration
438+
439+
### Ollama (Self-Hosted LLM Inference)
440+
441+
The bot integrates with [Ollama](https://ollama.com), a self-hosted large language model inference server running on an EC2 instance. When users send chat messages, Lambda calls the Ollama API over HTTP to generate AI responses.
442+
443+
**API Details:**
444+
445+
| Property | Value |
446+
|---|---|
447+
| Service | Ollama (self-hosted) |
448+
| Endpoint | `POST http://<EC2_EIP>:11434/api/chat` |
449+
| Protocol | HTTP (REST) |
450+
| Authentication | API key via `X-API-Key` header (nginx reverse proxy) |
451+
| Request format | JSON: `{"model": "tinyllama", "messages": [...], "stream": false}` |
452+
| Response format | JSON: `{"message": {"content": "..."}}` |
453+
454+
**Error Handling:**
455+
- Connection timeouts (45s) with structured JSON error logging
456+
- HTTP status code validation (non-200 responses return user-friendly error)
457+
- Exception handling with stack traces logged to CloudWatch
458+
- Graceful fallback: bot remains functional even if Ollama is unreachable
459+
460+
**Secrets Management:**
461+
- `OLLAMA_URL` passed as Lambda environment variable via Terraform (not hardcoded)
462+
- `OLLAMA_API_KEY` auto-generated (32-char random password) and passed to both Lambda and EC2 via Terraform
463+
- API key validated by nginx reverse proxy on EC2 (returns 401 without valid key)
464+
465+
**Security:**
466+
- Nginx reverse proxy validates `X-API-Key` header on all requests to port 11434
467+
- Ollama binds to `127.0.0.1:11435` (localhost only, not externally accessible)
468+
- SSH restricted to configurable CIDR (`ssh_allowed_cidr` variable)
469+
- S3 bucket: public access blocked, AES256 server-side encryption
470+
- DynamoDB: server-side encryption enabled, point-in-time recovery enabled
471+
- Sensitive Terraform outputs marked with `sensitive = true`
472+
473+
**Lifecycle Management:**
474+
475+
```bash
476+
./scripts/manage-ollama.sh start # Start instance, wait for Ollama API
477+
./scripts/manage-ollama.sh stop # Stop instance (syncs models to S3)
478+
./scripts/manage-ollama.sh status # Check instance and API health
479+
```
480+
420481
---
421482

422483
## Data Storage

0 commit comments

Comments
 (0)