diff --git a/README.md b/README.md index bca17f8..0d61875 100644 --- a/README.md +++ b/README.md @@ -94,54 +94,38 @@ Distributed as pre-built Docker containers via **Oracle Container Registry (OCIR --- -## Quick Start +## Deployment Options -### Prerequisites +The platform is distributed as a single Docker image available on **Oracle Container Registry (OCIR)**: -- Docker and Docker Compose v2 -- Access to the OCI Container Registry (OCIR) +``` +us-ashburn-1.ocir.io/idi1o0a010nx/oci-cis-agent:latest +``` -### 1. Configure +Multi-architecture: `linux/amd64` + `linux/arm64` + +--- + +### Option 1 — Local Docker (any machine) + +Run on any machine with Docker installed (Linux, macOS, Windows). ```bash +# 1. Login to OCIR +docker login us-ashburn-1.ocir.io + +# 2. Configure cp .env.example .env -``` +# Edit .env: set APP_SECRET (openssl rand -hex 64) -Edit `.env`: -```env -OCIR_REGION=us-ashburn-1 -OCIR_NAMESPACE=your_namespace -APP_SECRET= -``` - -### 2. Login to OCIR - -```bash -docker login .ocir.io -``` - -- **Username:** `/` or `/oracleidentitycloudservice/` -- **Password:** Auth Token (generate in OCI Console > Profile > Auth Tokens) - -### 3. Run - -**Option A — Single Container** (recommended for simplicity): - -```bash -docker compose -f docker-compose.single.yml up -d -``` - -One container runs everything (nginx + backend). Port `8080`. - -**Option B — Two Containers** (recommended for production): - -```bash +# 3. Run docker compose up -d + +# 4. Access: http://localhost:8080 +docker logs oci-cis-agent | grep "password" ``` -Separate backend and frontend containers with internal networking. - -**Option C — Docker Run** (no compose needed): +Or with `docker run` (no compose file needed): ```bash docker run -d \ @@ -150,32 +134,16 @@ docker run -d \ -v agent-data:/data \ -e APP_SECRET=$(openssl rand -hex 64) \ -e TZ=America/Sao_Paulo \ - .ocir.io//oci-cis-agent:latest + us-ashburn-1.ocir.io/idi1o0a010nx/oci-cis-agent:latest ``` -### 4. Access - -Open `http://localhost:8080` - -The initial admin password is generated automatically and displayed in the container logs: - -```bash -# Single container / docker run -docker logs oci-cis-agent | grep "password" - -# Two containers -docker compose logs backend | grep "password" -``` - -> You will be prompted to change the password on first login. - --- -## Deploy on OCI (Terraform) +### Option 2 — OCI Compute Instance (Terraform) -For production deployment on Oracle Cloud Infrastructure with Load Balancer, WAF, and SSL. +Production deployment on Oracle Cloud with Load Balancer, WAF, SSL, and persistent storage. -### Architecture +**Architecture:** ``` +--------------------------------------------------------------+ @@ -189,25 +157,24 @@ For production deployment on Oracle Cloud Infrastructure with Load Balancer, WAF | | | | Compute Instance | | | | +-----------------+ | | (ARM, Free Tier eligible) | | | | | | | | | | | -| | Load Balancer |---->| | Backend (FastAPI :8000) | | | -| | (HTTPS / 443) | | | Frontend (nginx :80) | | | -| | Public Subnet | | | Block Volume (/data) | | | +| | Load Balancer |---->| | oci-cis-agent container | | | +| | (HTTPS / 443) | | | Block Volume (/data) | | | +| | Public Subnet | | | | | | | | | | +---------------------------+ | | | +-----------------+ +--------------------------------+ | | | +--------------------------------------------------------------+ ``` -### Setup +**Setup:** ```bash cd terraform cp terraform.tfvars.example terraform.tfvars +# Edit terraform.tfvars with OCI credentials ``` -Edit `terraform.tfvars` with your OCI credentials and configuration. - -### Deploy +**Deploy:** ```bash terraform init @@ -215,7 +182,7 @@ terraform plan terraform apply ``` -### Resources Created +**Resources Created:** | Resource | Description | |----------|-------------| @@ -224,22 +191,119 @@ terraform apply | Block Volume | 50GB persistent storage for application data | | Load Balancer | Flexible 10-100 Mbps with SSL (self-signed or Let's Encrypt) | | WAF | OWASP protection — XSS, SQL injection, path traversal + rate limiting | -| OCIR | 2 private container repositories (backend + frontend) | | DNS | OCI DNS Zone + A record (conditional — when domain is configured) | -### Outputs - -After `terraform apply`: +**Outputs:** ```bash terraform output load_balancer_ip # Public IP address terraform output app_url # Application URL -terraform output ocir_backend_url # Backend image URL -terraform output ocir_frontend_url # Frontend image URL ``` --- +### Option 3 — OCI Container Instances + +Run as a serverless container on OCI without managing VMs. + +```bash +oci container-instances container-instance create \ + --compartment-id \ + --display-name "oci-cis-agent" \ + --availability-domain \ + --shape "CI.Standard.E4.Flex" \ + --shape-config '{"ocpus": 2, "memoryInGBs": 16}' \ + --containers '[{ + "imageUrl": "us-ashburn-1.ocir.io/idi1o0a010nx/oci-cis-agent:latest", + "displayName": "agent", + "environmentVariables": { + "APP_SECRET": "", + "TZ": "America/Sao_Paulo" + } + }]' \ + --vnics '[{"subnetId": ""}]' \ + --image-pull-secrets '[{"registryEndpoint": "us-ashburn-1.ocir.io", "secretType": "BASIC", "username": "", "password": ""}]' +``` + +--- + +### Option 4 — Kubernetes (OKE / any K8s cluster) + +Deploy on Oracle Kubernetes Engine or any Kubernetes cluster. + +```yaml +# Minimal deployment +apiVersion: apps/v1 +kind: Deployment +metadata: + name: oci-cis-agent +spec: + replicas: 1 + selector: + matchLabels: + app: oci-cis-agent + template: + metadata: + labels: + app: oci-cis-agent + spec: + containers: + - name: agent + image: us-ashburn-1.ocir.io/idi1o0a010nx/oci-cis-agent:latest + ports: + - containerPort: 8080 + env: + - name: APP_SECRET + valueFrom: + secretKeyRef: + name: agent-secret + key: app-secret + - name: TZ + value: "America/Sao_Paulo" + volumeMounts: + - name: data + mountPath: /data + resources: + requests: + memory: "2Gi" + limits: + memory: "4Gi" + volumes: + - name: data + persistentVolumeClaim: + claimName: agent-data + imagePullSecrets: + - name: ocir-credentials +--- +apiVersion: v1 +kind: Service +metadata: + name: oci-cis-agent +spec: + type: LoadBalancer + ports: + - port: 443 + targetPort: 8080 + selector: + app: oci-cis-agent +``` + +--- + +### First Login + +After any deployment option, check the container logs for the initial admin password: + +```bash +docker logs oci-cis-agent | grep "password" +# or +kubectl logs deployment/oci-cis-agent | grep "password" +``` + +> You will be prompted to change the password on first login. + +--- + ## Configuration Guide ### Step 1 — OCI Credentials diff --git a/docker-compose.yml b/docker-compose.yml index 346e598..95e57ba 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ services: - backend: - image: ${OCIR_REGION}.ocir.io/${OCIR_NAMESPACE}/oci-cis-agent-backend:${IMAGE_TAG:-latest} - container_name: oci-agent-backend + agent: + image: ${OCIR_REGION:-us-ashburn-1}.ocir.io/${OCIR_NAMESPACE:-idi1o0a010nx}/oci-cis-agent:${IMAGE_TAG:-latest} + container_name: oci-cis-agent restart: unless-stopped environment: - APP_SECRET=${APP_SECRET:?Set APP_SECRET in .env (openssl rand -hex 64)} @@ -10,12 +10,12 @@ services: - CORS_ORIGINS=${CORS_ORIGINS:-} - TZ=${TZ:-America/Sao_Paulo} - OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True + ports: + - "${PORT:-8080}:8080" volumes: - agent-data:/data - networks: - - agent-net healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"] + test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"] interval: 30s timeout: 10s retries: 3 @@ -26,29 +26,6 @@ services: max-file: "3" mem_limit: 4g - frontend: - image: ${OCIR_REGION}.ocir.io/${OCIR_NAMESPACE}/oci-cis-agent-frontend:${IMAGE_TAG:-latest} - container_name: oci-agent-frontend - restart: unless-stopped - environment: - - TZ=${TZ:-America/Sao_Paulo} - ports: - - "${PORT:-8080}:80" - depends_on: - - backend - networks: - - agent-net - logging: - driver: "json-file" - options: - max-size: "5m" - max-file: "3" - mem_limit: 512m - volumes: agent-data: driver: local - -networks: - agent-net: - driver: bridge diff --git a/terraform/templates/cloud-init.sh.tpl b/terraform/templates/cloud-init.sh.tpl index 90e8afd..1ff1316 100644 --- a/terraform/templates/cloud-init.sh.tpl +++ b/terraform/templates/cloud-init.sh.tpl @@ -48,7 +48,6 @@ fi mkdir -p /data mount "$DATA_DEVICE" /data -# Add to fstab if not already present if ! grep -q "$DATA_DEVICE" /etc/fstab; then echo "$DATA_DEVICE /data ext4 defaults,_netdev,nofail 0 2" >> /etc/fstab fi @@ -56,9 +55,6 @@ fi echo ">>> /data mounted successfully" df -h /data -# Create application data directories -mkdir -p /data/db /data/configs /data/reports /data/terraform /data/wallets - # ----------------------------------------------------------------------------- # 4. Docker login to OCIR # ----------------------------------------------------------------------------- @@ -69,16 +65,12 @@ echo '${ocir_auth_token}' | docker login "$OCIR_ENDPOINT" \ --password-stdin # ----------------------------------------------------------------------------- -# 5. Pull images +# 5. Pull image # ----------------------------------------------------------------------------- -BACKEND_IMAGE="$OCIR_ENDPOINT/${ocir_namespace}/${ocir_repo_prefix}/backend:latest" -FRONTEND_IMAGE="$OCIR_ENDPOINT/${ocir_namespace}/${ocir_repo_prefix}/frontend:latest" +IMAGE="$OCIR_ENDPOINT/${ocir_namespace}/${ocir_repo_prefix}:latest" -echo ">>> Pulling backend image: $BACKEND_IMAGE" -docker pull "$BACKEND_IMAGE" - -echo ">>> Pulling frontend image: $FRONTEND_IMAGE" -docker pull "$FRONTEND_IMAGE" +echo ">>> Pulling image: $IMAGE" +docker pull "$IMAGE" # ----------------------------------------------------------------------------- # 6. Write docker-compose.yml @@ -88,43 +80,29 @@ mkdir -p "$APP_DIR" cat > "$APP_DIR/docker-compose.yml" <<'COMPOSE_EOF' services: - backend: - image: ${ocir_region}.ocir.io/${ocir_namespace}/${ocir_repo_prefix}/backend:latest - container_name: cisagent-backend + agent: + image: ${ocir_region}.ocir.io/${ocir_namespace}/${ocir_repo_prefix}:latest + container_name: oci-cis-agent restart: unless-stopped environment: - APP_SECRET=${app_secret} - JWT_EXPIRY_HOURS=${jwt_expiry_hours} + - DATA_DIR=/data - CORS_ORIGINS=${cors_origins} - TZ=${app_timezone} + - OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True + ports: + - "8080:8080" volumes: - /data:/data mem_limit: 4g healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"] + test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s - networks: - - agent-net - frontend: - image: ${ocir_region}.ocir.io/${ocir_namespace}/${ocir_repo_prefix}/frontend:latest - container_name: cisagent-frontend - restart: unless-stopped - ports: - - "8080:80" - mem_limit: 512m - depends_on: - backend: - condition: service_healthy - networks: - - agent-net - -networks: - agent-net: - driver: bridge COMPOSE_EOF echo ">>> docker-compose.yml written to $APP_DIR" @@ -132,7 +110,7 @@ echo ">>> docker-compose.yml written to $APP_DIR" # ----------------------------------------------------------------------------- # 7. Start application # ----------------------------------------------------------------------------- -echo ">>> Starting application with Docker Compose..." +echo ">>> Starting application..." cd "$APP_DIR" docker compose up -d @@ -154,10 +132,10 @@ done if [ $ATTEMPTS -eq $MAX_ATTEMPTS ]; then echo "WARNING: Application did not become healthy within expected time" - echo ">>> Docker container status:" + echo ">>> Container status:" docker compose ps - echo ">>> Backend logs:" - docker compose logs backend --tail 50 + echo ">>> Logs:" + docker compose logs --tail 50 fi echo "=== OCI CIS Agent cloud-init finished at $(date) ==="