Server deploy script

This commit is contained in:
Chandresh Kerkar 2025-12-20 00:42:37 +05:30
parent 9c82c677ce
commit 4c2a2f6aca
6 changed files with 690 additions and 390 deletions

465
DEPLOYMENT_GUIDE.md Normal file
View File

@ -0,0 +1,465 @@
# Deployment Guide: Farm Auth Service on AWS Lightsail
This guide will help you deploy the Farm Auth Service on AWS Lightsail Ubuntu server with the domain `auth.livingai.app`.
## Prerequisites
- AWS Lightsail Ubuntu server (at least 1GB RAM recommended)
- Domain name `auth.livingai.app` pointing to your Lightsail server IP
- Access to AWS Console (for database if using AWS RDS)
- SSH access to your Lightsail server
---
## Step 1: Set Up AWS Lightsail Instance
1. **Create Lightsail Instance**
- Go to AWS Lightsail Console
- Click "Create instance"
- Choose:
- Platform: Linux/Unix
- Blueprint: Ubuntu 22.04 LTS (or latest)
- Instance plan: At least $5/month (1GB RAM)
- Name: `auth-service-server`
- Click "Create instance"
2. **Configure Static IP**
- In Lightsail, go to Networking → Static IPs
- Click "Create static IP"
- Attach to your instance
- **Note the static IP address** - you'll need it for DNS configuration
3. **Configure Firewall (Security Groups)**
- Go to Networking → Firewall
- Add rules:
- HTTP (port 80) - Allow from Anywhere
- HTTPS (port 443) - Allow from Anywhere
- SSH (port 22) - Allow from Your IP (for security)
- Custom TCP 3000 - Allow from localhost only (for Node.js app)
---
## Step 2: Configure DNS
1. **Point Domain to Lightsail IP**
- Go to your domain registrar (where you manage livingai.app)
- Add/Update A record:
- Type: A
- Name: auth (or @ if using subdomain)
- Value: Your Lightsail static IP address
- TTL: 300 (5 minutes)
- Wait for DNS propagation (can take up to 48 hours, usually faster)
2. **Verify DNS**
```bash
# On your local machine
nslookup auth.livingai.app
# Should return your Lightsail IP
```
---
## Step 3: Initial Server Setup (SSH into server)
1. **Connect to Server**
```bash
# Download SSH key from Lightsail or use existing key
ssh -i /path/to/your-key.pem ubuntu@your-lightsail-ip
```
2. **Update System**
```bash
sudo apt update && sudo apt upgrade -y
```
3. **Install Node.js (v18 or higher)**
```bash
# Install Node.js using NodeSource repository
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# Verify installation
node --version
npm --version
```
4. **Install Nginx**
```bash
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
```
5. **Install PM2 (Process Manager)**
```bash
sudo npm install -g pm2
```
6. **Install Git**
```bash
sudo apt install -y git
```
7. **Install Certbot (for SSL)**
```bash
sudo apt install -y certbot python3-certbot-nginx
```
---
## Step 4: Deploy Application Code
1. **Clone Repository**
```bash
# Create application directory
cd /home/ubuntu
mkdir -p apps
cd apps
# Clone your repository (adjust URL as needed)
git clone <your-repository-url> farm-auth-service
# OR if you need to upload manually:
# scp -r /path/to/farm-auth-service ubuntu@your-ip:/home/ubuntu/apps/
```
2. **Navigate to Project Directory**
```bash
cd farm-auth-service
```
3. **Install Dependencies**
```bash
npm install --production
```
---
## Step 5: Configure Environment Variables
1. **Create .env File**
```bash
cp example.env .env
nano .env
```
2. **Configure .env File** (Update these values)
```env
# Database Mode
DATABASE_MODE=aws
# AWS Configuration (for SSM Parameter Store)
AWS_REGION=ap-south-1
AWS_ACCESS_KEY_ID=your_aws_access_key_here
AWS_SECRET_ACCESS_KEY=your_aws_secret_key_here
DB_USE_READONLY=false
# Database connection (auto-detected from SSM if not set)
# DB_HOST=db.livingai.app
# DB_PORT=5432
# DB_NAME=livingai_test_db
# JWT Configuration (IMPORTANT: Generate new secrets for production!)
JWT_ACCESS_SECRET=your_strong_random_secret_here_min_32_chars
JWT_REFRESH_SECRET=your_strong_random_secret_here_min_32_chars
JWT_ACCESS_TTL=15m
JWT_REFRESH_TTL=7d
# Redis Configuration (Optional - for rate limiting)
# REDIS_URL=redis://your-redis-host:6379
# Or if password protected:
# REDIS_URL=redis://:password@your-redis-host:6379
# Application Configuration
NODE_ENV=production
PORT=3000
TRUST_PROXY=true
# CORS Configuration (REQUIRED for production)
CORS_ALLOWED_ORIGINS=https://your-mobile-app-domain.com,https://app.livingai.app
# Add all domains that will access this API
# Twilio Configuration (if using SMS OTP)
# TWILIO_ACCOUNT_SID=your_twilio_account_sid
# TWILIO_AUTH_TOKEN=your_twilio_auth_token
# TWILIO_PHONE_NUMBER=+1234567890
# Admin Dashboard (optional)
# ENABLE_ADMIN_DASHBOARD=false
```
3. **Generate Strong JWT Secrets** (Do this on your local machine)
```bash
# Generate random secrets (64 characters each)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
Copy the output to `JWT_ACCESS_SECRET` and `JWT_REFRESH_SECRET`
4. **Secure .env File**
```bash
chmod 600 .env
```
---
## Step 6: Configure Nginx Reverse Proxy
1. **Create Nginx Configuration**
```bash
sudo nano /etc/nginx/sites-available/auth.livingai.app
```
2. **Add Configuration** (Before SSL)
```nginx
server {
listen 80;
server_name auth.livingai.app;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
```
3. **Enable Site**
```bash
sudo ln -s /etc/nginx/sites-available/auth.livingai.app /etc/nginx/sites-enabled/
sudo nginx -t # Test configuration
sudo systemctl reload nginx
```
---
## Step 7: Set Up SSL Certificate (Let's Encrypt)
1. **Obtain SSL Certificate**
```bash
sudo certbot --nginx -d auth.livingai.app
```
- Follow prompts (enter email, agree to terms)
- Choose redirect HTTP to HTTPS (option 2)
2. **Verify Auto-renewal**
```bash
sudo certbot renew --dry-run
```
3. **Update Nginx Config** (Certbot should have done this automatically)
Your config should now include SSL and redirect HTTP to HTTPS.
---
## Step 8: Start Application with PM2
1. **Start Application**
```bash
cd /home/ubuntu/apps/farm-auth-service
pm2 start src/index.js --name "auth-service"
```
2. **Save PM2 Configuration**
```bash
pm2 save
pm2 startup
# Copy and run the command it outputs (starts PM2 on boot)
```
3. **PM2 Useful Commands**
```bash
pm2 list # View running processes
pm2 logs auth-service # View logs
pm2 restart auth-service # Restart service
pm2 stop auth-service # Stop service
pm2 monit # Monitor resources
```
---
## Step 9: Configure Firewall (UFW)
1. **Set Up Firewall Rules**
```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
sudo ufw status
```
---
## Step 10: Test Deployment
1. **Check Application Status**
```bash
pm2 status
pm2 logs auth-service --lines 50
```
2. **Test API Endpoint**
```bash
# From server
curl http://localhost:3000/health
# From your local machine (should work via domain)
curl https://auth.livingai.app/health
```
3. **Check Nginx Logs**
```bash
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
```
---
## Step 11: Database Setup (if using AWS RDS)
1. **Ensure Database is Accessible**
- Your Lightsail instance should be able to connect to your AWS RDS instance
- Check security groups allow connection from Lightsail IP
- Verify SSM Parameter Store has correct credentials
2. **Test Database Connection**
```bash
cd /home/ubuntu/apps/farm-auth-service
node -e "require('./src/db').then(() => console.log('DB Connected')).catch(e => console.error(e))"
```
---
## Step 12: Optional - Set Up Redis (for Rate Limiting)
If you want to use Redis for rate limiting:
1. **Option A: Install Redis on Same Server**
```bash
sudo apt install -y redis-server
sudo systemctl start redis-server
sudo systemctl enable redis-server
```
Then update `.env`:
```env
REDIS_URL=redis://localhost:6379
```
2. **Option B: Use AWS ElastiCache**
- Create ElastiCache Redis cluster
- Update `.env` with ElastiCache endpoint:
```env
REDIS_URL=redis://your-elasticache-endpoint:6379
```
---
## Monitoring and Maintenance
### View Logs
```bash
pm2 logs auth-service
pm2 logs auth-service --err # Error logs only
pm2 logs auth-service --out # Output logs only
```
### Restart Service
```bash
pm2 restart auth-service
```
### Update Application
```bash
cd /home/ubuntu/apps/farm-auth-service
git pull # or upload new files
npm install --production
pm2 restart auth-service
```
### Monitor Resources
```bash
pm2 monit
htop # System resources
```
---
## Troubleshooting
### Application Not Starting
1. Check logs: `pm2 logs auth-service`
2. Verify .env file exists and has correct values
3. Check database connectivity
4. Verify all dependencies installed: `npm list`
### 502 Bad Gateway
- Check if app is running: `pm2 status`
- Check app logs: `pm2 logs auth-service`
- Verify port 3000 is listening: `netstat -tlnp | grep 3000`
- Check Nginx error logs: `sudo tail -f /var/log/nginx/error.log`
### SSL Certificate Issues
- Verify DNS points to correct IP: `nslookup auth.livingai.app`
- Check certificate: `sudo certbot certificates`
- Renew manually: `sudo certbot renew`
### Database Connection Issues
- Verify AWS SSM parameters are correct
- Check AWS credentials in .env
- Test database connectivity from server
- Check security group allows connection
---
## Security Checklist
- [ ] Strong JWT secrets generated and stored securely
- [ ] .env file has 600 permissions
- [ ] Firewall configured (UFW)
- [ ] SSL certificate installed and auto-renewal working
- [ ] CORS configured with specific allowed origins (not *)
- [ ] AWS credentials have minimal required permissions
- [ ] Regular security updates: `sudo apt update && sudo apt upgrade`
- [ ] PM2 logs are monitored
- [ ] Database credentials stored in SSM (not in .env)
---
## Backup Strategy
1. **Database Backups**
- Set up automated RDS snapshots in AWS Console
- Or use pg_dump for manual backups
2. **Application Code**
- Code is in Git repository (already backed up)
- Keep .env file backed up securely (encrypted)
3. **Configuration**
- Document all configuration changes
- Keep .env template versioned (without secrets)
---
## Next Steps
1. Set up monitoring/alerting (e.g., CloudWatch, PM2 Plus)
2. Configure log rotation for PM2
3. Set up CI/CD pipeline for automated deployments
4. Configure health checks and auto-restart on failure
5. Set up database backups schedule
---
## Support
For issues, check:
- Application logs: `pm2 logs auth-service`
- Nginx logs: `/var/log/nginx/`
- System logs: `journalctl -xe`

View File

@ -1,159 +0,0 @@
# AWS Database Migration - Implementation Summary
## ✅ Completed Changes
All code changes have been implemented to migrate from local Docker PostgreSQL to AWS PostgreSQL using AWS SSM Parameter Store for secure credential management.
## 📁 Files Modified
### 1. `src/utils/awsSsm.js`
**Changes:**
- ✅ Updated to use correct SSM parameter paths:
- Read-Write: `/test/livingai/db/app`
- Read-Only: `/test/livingai/db/app/readonly`
- ✅ Added support for `DB_USE_READONLY` environment variable
- ✅ Improved error handling with detailed error messages
- ✅ Added `buildDatabaseConfig()` function for SSL support
- ✅ Updated credential validation and parsing
### 2. `src/db.js`
**Changes:**
- ✅ Added SSL configuration for self-signed certificates
- ✅ Updated to use `buildDatabaseConfig()` instead of connection string
- ✅ Improved error handling and logging
- ✅ Auto-detection of AWS database when `DB_HOST=db.livingai.app`
- ✅ Connection pool configuration (max: 20, idleTimeout: 30s)
### 3. `src/config.js`
**Changes:**
- ✅ Updated to require AWS credentials when using SSM
- ✅ Removed `DATABASE_URL` from required env vars when `USE_AWS_SSM=true`
- ✅ Added validation for AWS credentials
### 4. Documentation
**New Files:**
- ✅ `docs/getting-started/AWS_DATABASE_MIGRATION.md` - Complete migration guide
- ✅ `docs/getting-started/ENV_VARIABLES_REFERENCE.md` - Environment variables reference
- ✅ `MIGRATION_SUMMARY.md` - This file
## 🔒 Security Implementation
### ✅ Credentials Management
- **NO database credentials in `.env` files**
- Credentials fetched from AWS SSM Parameter Store at runtime
- Only AWS credentials (for SSM access) in `.env`
- Supports both read-write and read-only users
### ✅ SSL Configuration
- SSL enabled with `rejectUnauthorized: false` for self-signed certificates
- Connection string includes `?sslmode=require`
- Proper SSL configuration in connection pool
## 📋 Required Environment Variables
### For AWS Database (Production)
```env
# AWS Configuration (for SSM access)
AWS_REGION=ap-south-1
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
USE_AWS_SSM=true
# JWT Configuration
JWT_ACCESS_SECRET=your_secret
JWT_REFRESH_SECRET=your_secret
```
### Optional
```env
DB_USE_READONLY=false # false = read_write_user, true = read_only_user
DB_HOST=db.livingai.app
DB_PORT=5432
DB_NAME=livingai_test_db
```
## 🔄 Migration Steps
1. **Set up AWS SSM Parameters:**
- Create `/test/livingai/db/app` with read-write user credentials (JSON format)
- Create `/test/livingai/db/app/readonly` with read-only user credentials (optional)
2. **Update `.env` file:**
- Add AWS credentials (AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
- Set `USE_AWS_SSM=true`
- Remove any database credentials (DB_USER, DB_PASSWORD, DATABASE_URL)
3. **Verify IAM Permissions:**
- Ensure IAM user/role has `ssm:GetParameter` permission for both SSM parameter paths
4. **Test Connection:**
- Start application: `npm start`
- Verify logs show successful SSM credential fetch and database connection
## 🧪 Testing Checklist
- [ ] AWS SSM parameters created with correct paths and JSON format
- [ ] IAM user has SSM read permissions
- [ ] `.env` file has AWS credentials (no DB credentials)
- [ ] `USE_AWS_SSM=true` in `.env`
- [ ] Application starts without errors
- [ ] Database connection established successfully
- [ ] SSL connection working (no SSL errors)
- [ ] API endpoints respond correctly
- [ ] Database queries execute successfully
- [ ] All business logic works as before
## 🔍 Verification Commands
### Check AWS SSM Parameter
```bash
aws ssm get-parameter --name "/test/livingai/db/app" --with-decryption --region ap-south-1
```
### Test Database Connection
```bash
npm start
# Look for these log messages:
# ✅ Successfully fetched DB credentials from SSM: /test/livingai/db/app (read-write user)
# ✅ Using database credentials from AWS SSM Parameter Store
# ✅ Database connection established successfully
```
## ⚠️ Important Notes
1. **No Breaking Changes**: All business logic remains unchanged. Only database connection configuration was updated.
2. **Backward Compatibility**: Local development still works with `DATABASE_URL` when `USE_AWS_SSM=false`.
3. **Security**: Database credentials are never stored in files. They are fetched from AWS SSM at runtime.
4. **SSL**: Self-signed certificates are supported via `rejectUnauthorized: false` configuration.
5. **Connection Pooling**: Configured with sensible defaults (max 20 connections, 30s idle timeout).
## 📚 Documentation
For detailed information, see:
- `docs/getting-started/AWS_DATABASE_MIGRATION.md` - Complete migration guide
- `docs/getting-started/ENV_VARIABLES_REFERENCE.md` - Environment variables reference
## 🐛 Troubleshooting
Common issues and solutions are documented in `docs/getting-started/AWS_DATABASE_MIGRATION.md` under the "Troubleshooting" section.
## ✨ Next Steps
1. Review the changes in the modified files
2. Set up AWS SSM parameters with your database credentials
3. Update your `.env` file with AWS credentials
4. Test the connection
5. Deploy to your AWS environment
---
**Migration Status**: ✅ Complete
**All Requirements Met**: ✅ Yes
**Security Requirements Met**: ✅ Yes
**Backward Compatibility**: ✅ Maintained

131
QUICK_DEPLOY.md Normal file
View File

@ -0,0 +1,131 @@
# Quick Deployment Reference - auth.livingai.app
## TL;DR - Quick Steps
### 1. Lightsail Setup
- Create Ubuntu 22.04 instance
- Attach static IP
- Open ports: 80, 443, 22
### 2. DNS Configuration
- Point `auth.livingai.app` A record to Lightsail static IP
### 3. Server Setup (SSH into server)
```bash
# Run setup script
cd ~ && wget https://your-repo/setup-server.sh
bash setup-server.sh
# OR manually:
sudo apt update && sudo apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs nginx git certbot python3-certbot-nginx
sudo npm install -g pm2
```
### 4. Deploy Application
```bash
cd ~/apps
git clone <your-repo-url> farm-auth-service
cd farm-auth-service
npm install --production
cp example.env .env
nano .env # Configure environment variables
```
### 5. Configure Nginx
```bash
sudo nano /etc/nginx/sites-available/auth.livingai.app
# Add configuration (see DEPLOYMENT_GUIDE.md)
sudo ln -s /etc/nginx/sites-available/auth.livingai.app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### 6. SSL Certificate
```bash
sudo certbot --nginx -d auth.livingai.app
```
### 7. Start Application
```bash
cd ~/apps/farm-auth-service
pm2 start ecosystem.config.js
pm2 save
pm2 startup # Follow instructions
```
### 8. Configure Firewall
```bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
```
---
## Critical Configuration (.env)
**Required Settings:**
```env
NODE_ENV=production
PORT=3000
TRUST_PROXY=true
DATABASE_MODE=aws
AWS_REGION=ap-south-1
AWS_ACCESS_KEY_ID=your_key
AWS_SECRET_ACCESS_KEY=your_secret
JWT_ACCESS_SECRET=generate_strong_secret_min_32_chars
JWT_REFRESH_SECRET=generate_strong_secret_min_32_chars
CORS_ALLOWED_ORIGINS=https://your-app-domain.com,https://app.livingai.app
```
**Generate JWT Secrets:**
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
---
## Useful Commands
```bash
# View logs
pm2 logs auth-service
# Restart
pm2 restart auth-service
# Status
pm2 status
# Nginx logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
# Test API
curl https://auth.livingai.app/health
```
---
## Troubleshooting
**502 Bad Gateway?**
- Check PM2: `pm2 status`
- Check logs: `pm2 logs auth-service`
- Check Nginx: `sudo nginx -t`
**Can't connect to database?**
- Verify AWS credentials in .env
- Check SSM Parameter Store access
- Test connection: `node -e "require('./src/db')"`
**SSL issues?**
- Verify DNS: `nslookup auth.livingai.app`
- Renew cert: `sudo certbot renew`
---
For detailed instructions, see `DEPLOYMENT_GUIDE.md`

27
ecosystem.config.js Normal file
View File

@ -0,0 +1,27 @@
// PM2 Ecosystem Configuration File
// Usage: pm2 start ecosystem.config.js
module.exports = {
apps: [{
name: 'auth-service',
script: 'src/index.js',
instances: 1, // For single instance, use 1. For cluster mode, use 'max' or number
exec_mode: 'fork', // 'fork' for single instance, 'cluster' for multiple instances
watch: false, // Set to true for development
max_memory_restart: '500M', // Restart if memory exceeds 500MB
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: './logs/pm2-error.log',
out_file: './logs/pm2-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
autorestart: true,
max_restarts: 10,
min_uptime: '10s',
listen_timeout: 10000,
kill_timeout: 5000
}]
};

View File

@ -1,231 +0,0 @@
# Kotlin OTP Verification Fix
## Issue Analysis
The backend `/auth/verify-otp` endpoint expects:
```json
{
"phone_number": "+919876543210", // Must be E.164 format with +
"code": "123456", // String, not number
"device_id": "optional-device-id",
"device_info": {
"platform": "android",
"model": "device-model",
"os_version": "Android 13",
"app_version": "1.0.0",
"language_code": "en",
"timezone": "Asia/Kolkata"
}
}
```
## Common Issues in Kotlin Implementation
1. **Phone Number Format**: Must include `+` prefix (E.164 format)
2. **OTP Code Type**: Must be sent as string, not integer
3. **Request Body**: Must match exact field names (`phone_number`, `code`)
4. **Missing Device Info**: Backend accepts but doesn't require device_info
## Fixed Kotlin Code
### Option 1: Update AuthManager.login() method
```kotlin
// In AuthManager.kt or AuthApiClient.kt
suspend fun login(phoneNumber: String, otpCode: String): Result<LoginResponse> {
return try {
// Ensure phone number has + prefix (E.164 format)
val normalizedPhone = if (phoneNumber.startsWith("+")) {
phoneNumber
} else if (phoneNumber.length == 10) {
"+91$phoneNumber" // Add +91 for 10-digit Indian numbers
} else {
phoneNumber // Keep as is if already formatted
}
// Ensure OTP is string (not integer)
val otpString = otpCode.toString().trim()
// Get device info
val deviceId = getDeviceId() // Your method to get device ID
val deviceInfo = getDeviceInfo() // Your method to get device info
val requestBody = mapOf(
"phone_number" to normalizedPhone,
"code" to otpString,
"device_id" to deviceId,
"device_info" to deviceInfo
)
val response = apiClient.post("/auth/verify-otp", requestBody)
if (response.isSuccessful) {
val loginResponse = response.body() // Parse your LoginResponse
Result.success(loginResponse)
} else {
// Handle error response
val errorBody = response.errorBody()?.string()
Result.failure(Exception("OTP verification failed: $errorBody"))
}
} catch (e: Exception) {
Result.failure(e)
}
}
// Helper function to get device info
private fun getDeviceInfo(): Map<String, String?> {
return mapOf(
"platform" to "android",
"model" to android.os.Build.MODEL,
"os_version" to android.os.Build.VERSION.RELEASE,
"app_version" to getAppVersion(), // Your method
"language_code" to Locale.getDefault().language,
"timezone" to TimeZone.getDefault().id
)
}
private fun getDeviceId(): String {
// Use your existing device ID logic
// Could be Android ID, UUID, etc.
return Settings.Secure.getString(
context.contentResolver,
Settings.Secure.ANDROID_ID
) ?: UUID.randomUUID().toString()
}
```
### Option 2: Quick Fix in OtpScreen.kt
Update your `OtpScreen.kt` to ensure proper formatting:
```kotlin
@Composable
fun OtpScreen(navController: NavController, phoneNumber: String, name: String) {
val otp = remember { mutableStateOf("") }
val context = LocalContext.current.applicationContext
val scope = rememberCoroutineScope()
val authManager = remember { AuthManager(context, AuthApiClient(context), TokenManager(context)) }
val isSignInFlow = name == "existing_user"
// Normalize phone number to ensure it has + prefix
val normalizedPhone = remember(phoneNumber) {
if (phoneNumber.startsWith("+")) {
phoneNumber
} else if (phoneNumber.length == 10) {
"+91$phoneNumber"
} else {
phoneNumber
}
}
Box(
modifier = Modifier.fillMaxSize()
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 36.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(200.dp))
Text("Enter OTP", fontSize = 24.sp, fontWeight = FontWeight.Medium, color = Color(0xFF364153))
Spacer(modifier = Modifier.height(32.dp))
TextField(
value = otp.value,
onValueChange = { if (it.length <= 6 && it.all { char -> char.isDigit() }) otp.value = it },
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.shadow(elevation = 1.dp, shape = RoundedCornerShape(16.dp)),
shape = RoundedCornerShape(16.dp),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.White.copy(alpha = 0.9f),
unfocusedContainerColor = Color.White.copy(alpha = 0.9f),
disabledContainerColor = Color.White.copy(alpha = 0.9f),
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
),
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center, fontSize = 24.sp),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
Spacer(modifier = Modifier.height(48.dp))
Button(
onClick = {
scope.launch {
// Ensure OTP is not empty and is 6 digits
if (otp.value.length != 6) {
Toast.makeText(context, "Please enter a valid 6-digit OTP", Toast.LENGTH_SHORT).show()
return@launch
}
// Use normalized phone number
authManager.login(normalizedPhone, otp.value.trim())
.onSuccess { response ->
if (isSignInFlow) {
navController.navigate("success") { popUpTo("login") { inclusive = true } }
} else {
if (response.needsProfile) {
navController.navigate("create_profile/$name")
} else {
navController.navigate("success") { popUpTo("login") { inclusive = true } }
}
}
}
.onFailure { error ->
// More detailed error handling
val errorMessage = error.message ?: "Invalid or expired OTP"
Toast.makeText(context, errorMessage, Toast.LENGTH_SHORT).show()
Log.e("OtpScreen", "OTP verification failed", error)
}
}
},
shape = RoundedCornerShape(16.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFFE9A00)),
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.shadow(elevation = 4.dp, shape = RoundedCornerShape(16.dp))
) {
Text("Continue", color = Color.White, fontSize = 16.sp, fontWeight = FontWeight.Medium)
}
}
}
}
```
## Key Changes to Check in Your AuthManager/AuthApiClient
1. **Phone Number Normalization**: Ensure `+` prefix is present
2. **OTP as String**: Send OTP as string, not integer
3. **Request Body Format**: Use exact field names from backend
4. **Error Handling**: Check response status and error body
## Debugging Steps
1. **Add Logging**: Log the exact request being sent
```kotlin
Log.d("AuthManager", "Sending verify-otp: phone=$normalizedPhone, code=$otpString")
Log.d("AuthManager", "Request body: $requestBody")
```
2. **Check Response**: Log the response
```kotlin
Log.d("AuthManager", "Response code: ${response.code()}")
Log.d("AuthManager", "Response body: ${response.body()?.string()}")
```
3. **Compare with HTML**: Use the same phone number and OTP in HTML test page to verify backend is working
## Most Likely Issues
1. **Phone number missing `+` prefix** - Backend normalizes but expects E.164 format
2. **OTP sent as number instead of string** - Backend expects string
3. **Wrong field names** - Must be `phone_number` and `code` (with underscores)
4. **Request body not properly serialized** - Check your JSON serialization

67
setup-server.sh Normal file
View File

@ -0,0 +1,67 @@
#!/bin/bash
# Quick Setup Script for AWS Lightsail Ubuntu Server
# Run this script on your Lightsail server after initial SSH connection
# Usage: bash setup-server.sh
set -e
echo "🚀 Starting Farm Auth Service Server Setup..."
# Update system
echo "📦 Updating system packages..."
sudo apt update && sudo apt upgrade -y
# Install Node.js
echo "📦 Installing Node.js..."
if ! command -v node &> /dev/null; then
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
else
echo "✅ Node.js already installed: $(node --version)"
fi
# Install Nginx
echo "📦 Installing Nginx..."
if ! command -v nginx &> /dev/null; then
sudo apt install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx
else
echo "✅ Nginx already installed"
fi
# Install PM2
echo "📦 Installing PM2..."
if ! command -v pm2 &> /dev/null; then
sudo npm install -g pm2
else
echo "✅ PM2 already installed: $(pm2 --version)"
fi
# Install Git
echo "📦 Installing Git..."
sudo apt install -y git
# Install Certbot
echo "📦 Installing Certbot..."
sudo apt install -y certbot python3-certbot-nginx
# Create application directory
echo "📁 Creating application directory..."
mkdir -p ~/apps
cd ~/apps
# Create logs directory
echo "📁 Creating logs directory..."
mkdir -p ~/apps/farm-auth-service/logs
echo "✅ Server setup completed!"
echo ""
echo "Next steps:"
echo "1. Clone your repository: cd ~/apps && git clone <your-repo-url> farm-auth-service"
echo "2. Install dependencies: cd farm-auth-service && npm install --production"
echo "3. Configure .env file: cp example.env .env && nano .env"
echo "4. Configure Nginx (see DEPLOYMENT_GUIDE.md)"
echo "5. Set up SSL: sudo certbot --nginx -d auth.livingai.app"
echo "6. Start application: pm2 start ecosystem.config.js"