# Instance Deployment Implementation Guide

## Quick Start for Developers

### Understanding the Current State

The application is installed at `/home/ashraffarid2010/wakelai.com` with:
- **Next.js 15.5.19** running on port 9100
- **PostgreSQL** database on port 55433
- **Docker** for instance containers
- **nginx** reverse proxy on port 80/443

### What Works ✅

1. **Main application**: https://wakelai.com
2. **User authentication**: Login/register functional
3. **Instance creation**: Creates database records and Docker containers
4. **Instance deletion**: UI button + API endpoint functional
5. **DNS**: Wildcard subdomain resolution (`*.wakelai.com` → server IP)
6. **Rebranding**: Complete from "Geney Agent" to "Wakel AI"

### What Needs Implementation 🔨

#### 1. Instance Subdomain Routing

**Problem**: All subdomains (`test2-o45wo.wakelai.com`) currently show the main landing page instead of instance containers.

**Root Cause**: 
- Docker containers ARE being created (check with `docker ps`)
- nginx routes all `*.wakelai.com` to main app (port 9100)
- No instance-specific nginx configs for routing to container ports

**Solution**: Implement dynamic nginx configuration

```typescript
// File: src/lib/nginx-manager.ts

import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

export async function createInstanceNginxConfig(subdomain: string, port: number) {
  const config = `
server {
    listen 80;
    listen [::]:80;
    server_name ${subdomain}.wakelai.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        proxy_pass         http://127.0.0.1:${port};
        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;
        proxy_read_timeout 86400;
        proxy_connect_timeout 86400;
    }
}
`;

  const configPath = `/etc/nginx/conf.d/instance-${subdomain}.conf`;
  await fs.writeFile(configPath, config);
  await execAsync("nginx -s reload");
}

export async function removeInstanceNginxConfig(subdomain: string) {
  const configPath = `/etc/nginx/conf.d/instance-${subdomain}.conf`;
  await execAsync(`rm ${configPath}`);
  await execAsync("nginx -s reload");
}
```

**Integration points**:
- Call `createInstanceNginxConfig()` after Docker container creation
- Call `removeInstanceNginxConfig()` before container deletion

#### 2. Port Allocation System

**Problem**: No system to track assigned ports or prevent conflicts.

**Solution**: Add port tracking to database schema

```prisma
// File: prisma/schema.prisma

model Instance {
  // ... existing fields ...
  
  port          Int?      @unique  // Assigned host port
  containerName String?   // Docker container name
}

// You could also create a separate port allocation table:
model PortAllocation {
  id          Int      @id @default(autoincrement())
  port        Int      @unique
  instanceId  String?  @unique
  allocatedAt DateTime @default(now())
  releasedAt  DateTime?
}
```

**Port allocation logic**:
```typescript
// Port range: 9500-9999
const PORT_START = 9500;
const PORT_END = 9999;

async function allocatePort(): Promise<number> {
  // Find first available port
  const allocated = await prisma.portAllocation.findMany({
    where: { releasedAt: null }
  });
  
  const usedPorts = new Set(allocated.map(p => p.port));
  
  for (let port = PORT_START; port <= PORT_END; port++) {
    if (!usedPorts.has(port)) {
      await prisma.portAllocation.create({
        data: { port }
      });
      return port;
    }
  }
  
  throw new Error("No ports available");
}

async function releasePort(port: number) {
  await prisma.portAllocation.update({
    where: { port },
    data: { releasedAt: new Date() }
  });
}
```

#### 3. Container Lifecycle Management

**Problem**: Containers created but not properly managed (start/stop/restart).

**Solution**: Implement Docker operations

```typescript
// File: src/lib/docker-manager.ts

import { exec } from "child_process";
import { promisify } from "util";

const execAsync = promisify(exec);

export async function createContainer(params: {
  instanceId: string;
  subdomain: string;
  port: number;
}) {
  const { instanceId, subdomain, port } = params;
  const containerName = `${instanceId}-hermes`;
  
  // Check if container already exists
  const { stdout: exists } = await execAsync(
    `docker ps -a -q -f name=${containerName}`
  );
  
  if (exists.trim()) {
    await execAsync(`docker rm -f ${containerName}`);
  }
  
  // Create container
  const cmd = [
    "docker run -d",
    `--name ${containerName}`,
    "--network wakelai-runtime",
    `-p ${port}:4860`,
    `-e INSTANCE_NAME=${subdomain}`,
    `-e DOMAIN=wakelai.com`,
    "ghcr.io/hostinger/hvps-hermes-agent:latest"
  ].join(" ");
  
  await execAsync(cmd);
  
  return containerName;
}

export async function startContainer(instanceId: string) {
  const containerName = `${instanceId}-hermes`;
  await execAsync(`docker start ${containerName}`);
}

export async function stopContainer(instanceId: string) {
  const containerName = `${instanceId}-hermes`;
  await execAsync(`docker stop ${containerName}`);
}

export async function removeContainer(instanceId: string) {
  const containerName = `${instanceId}-hermes`;
  await execAsync(`docker rm -f ${containerName}`);
}

export async function getContainerStatus(instanceId: string): Promise<string> {
  const containerName = `${instanceId}-hermes`;
  
  try {
    const { stdout } = await execAsync(
      `docker inspect -f '{{.State.Status}}' ${containerName}`
    );
    return stdout.trim();
  } catch {
    return "not_found";
  }
}
```

#### 4. Update Instance API

**File**: `src/app/api/instances/[id]/route.ts`

Update the DELETE endpoint to clean up resources:

```typescript
export async function DELETE(
  req: NextRequest,
  { params }: { params: { id: string } }
) {
  try {
    const session = await getServerSession(authOptions);
    if (!session) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    
    const instance = await prisma.instance.findUnique({
      where: { id: params.id }
    });
    
    if (!instance || instance.userId !== session.user.id) {
      return NextResponse.json({ error: "Not found" }, { status: 404 });
    }
    
    // 1. Remove nginx config
    if (instance.subdomain) {
      await removeInstanceNginxConfig(instance.subdomain);
    }
    
    // 2. Stop and remove container
    await removeContainer(instance.id);
    
    // 3. Release port
    if (instance.port) {
      await releasePort(instance.port);
    }
    
    // 4. Delete database record
    await prisma.instance.delete({
      where: { id: params.id }
    });
    
    return NextResponse.json({ success: true });
  } catch (error) {
    console.error("Delete instance error:", error);
    return NextResponse.json({ error: "Failed to delete" }, { status: 500 });
  }
}
```

## Security Considerations

### nginx Configuration
- Each instance should be isolated to its port
- Add rate limiting per subdomain if needed
- Implement proper logging per instance

### Docker
- Containers should run in isolated network
- Limit container resources (CPU/memory)
- Use non-privileged containers

### Application
- Validate subdomain format to prevent injection attacks
- Rate limit instance creation per user
- Monitor for abuse

## Testing Checklist

- [ ] Create instance → verify in Docker (`docker ps`)
- [ ] Check nginx config created (`ls /etc/nginx/conf.d/instance-*`)
- [ ] Access subdomain → shows container content, not main page
- [ ] Stop instance → container stopped, subdomain returns error
- [ ] Start instance → container running, subdomain accessible
- [ ] Delete instance → all resources cleaned up

## Monitoring

Add these metrics to track:
- Instance count per user
- Port utilization
- Container health status
- nginx errors per subdomain

## Rollback Plan

If something breaks:
1. Check nginx logs: `tail -f /var/log/nginx/wakelai.com-error.log`
2. Verify Docker: `docker ps -a`
3. Test nginx config: `nginx -t`
4. Rollback to previous nginx config if needed
5. Restore instance from database backup if deleted incorrectly
