Index: /branches/amp_4_0/platform/tools/container/DEPLOYMENT.md
===================================================================
--- /branches/amp_4_0/platform/tools/container/DEPLOYMENT.md	(revision 2885)
+++ /branches/amp_4_0/platform/tools/container/DEPLOYMENT.md	(working copy)
@@ -15,11 +15,24 @@
 * All nodes must be on the same LAN/VLAN.
 * Static IPs are recommended for stability.
 
-### Firewall Configuration (On ALL Nodes)
+### Firewall & System Tuning (On ALL Nodes)
 
-You must open the following ports for Docker Swarm and AMP services:
+OpenSearch requires increased virtual memory, and Docker Swarm needs specific ports open. Run on each node:
 
 ```bash
+./manage_amp.sh system_tune
+```
+
+This command automatically:
+
+* Sets `vm.max_map_count=262144` (persisted across reboots)
+* Creates required log directories (`/var/log/amp/opensearch`)
+* Configures all required firewall ports for Docker Swarm and AMP services
+
+<details>
+<summary>Manual firewall configuration (if needed)</summary>
+
+```bash
 # Docker Swarm Ports
 firewall-cmd --add-port=2377/tcp --permanent
 firewall-cmd --add-port=7946/tcp --permanent
@@ -37,7 +50,6 @@
 firewall-cmd --add-port=9200/tcp --permanent # OpenSearch REST (Inter-node & Dashboards)
 firewall-cmd --add-port=9300/tcp --permanent # OpenSearch Transport (Cluster)
 firewall-cmd --add-port=5601/tcp --permanent # OpenSearch Dashboards
-# IMPORTANT: Traffic between nodes on Overlay (UDP 4789) and OpenSearch (9200) MUST be allowed!
 firewall-cmd --add-port=3000/tcp --permanent # Grafana
 firewall-cmd --add-port=514/tcp --permanent  # Logstash Syslog TCP
 firewall-cmd --add-port=514/udp --permanent  # Logstash Syslog UDP
@@ -46,21 +58,10 @@
 firewall-cmd --reload
 ```
 
-> ⚠️ **WARNING**: Do NOT manually add Docker interfaces (`docker0`, `docker_gwbridge`) to firewalld zones. Docker manages these interfaces itself. Manual zone assignments cause `ZONE_CONFLICT` errors that prevent Docker from starting.
+</details>
 
-### System Tuning (On ALL Nodes)
-
-OpenSearch requires increased virtual memory. Run on each node:
-
-```bash
-# Using manage_amp.sh (recommended)
-./manage_amp.sh system_tune
+> ⚠️ **WARNING**: Do NOT manually add Docker interfaces (`docker0`, `docker_gwbridge`) to firewalld zones. Docker manages these interfaces itself. Manual zone assignments cause `ZONE_CONFLICT` errors that prevent Docker from starting.
 
-# Or manually:
-sudo sysctl -w vm.max_map_count=262144
-echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
-```
-
 ---
 
 ## 2. Docker Swarm Setup
@@ -230,6 +231,25 @@
 ./manage_amp.sh configurator
 ```
 
+### Step 8: Create CLI Users (Optional)
+
+Create users who will access the AMP CLI via SSH:
+
+```bash
+# Create a user with ca_shell (CLI only)
+sudo useradd -m -s /ca/bin/ca_shell amp_operator
+sudo passwd amp_operator
+
+# Create a user with bash (full access)
+sudo useradd -m -s /bin/bash amp_admin
+sudo passwd amp_admin
+
+# Add users to docker group (required for ca_shell)
+sudo usermod -aG docker amp_operator
+```
+
+> **Note**: The deploy script automatically installs `/ca/bin/ca_shell` wrapper and sets the SELinux context.
+
 ---
 
 ## 4. Verification
Index: /branches/amp_4_0/platform/tools/container/manage_amp.sh
===================================================================
--- /branches/amp_4_0/platform/tools/container/manage_amp.sh	(revision 2885)
+++ /branches/amp_4_0/platform/tools/container/manage_amp.sh	(working copy)
@@ -20,6 +20,7 @@
 export TAG_REGISTRY="${TAG_REGISTRY:-3.0.0}"
 export TAG_BUSYBOX="${TAG_BUSYBOX:-1.37.0}"
 export TAG_ROCKY="${TAG_ROCKY:-9}"
+export TAG_AMP_CORE="${TAG_AMP_CORE:-1.0.0}"
 
 # Logging Configuration
 export AMP_LOG_ROOT="${AMP_LOG_ROOT:-/var/log/amp}"
@@ -40,6 +41,7 @@
     "registry:registry:${TAG_REGISTRY}"
     "busybox:busybox:${TAG_BUSYBOX}"
     "rocky:rockylinux:${TAG_ROCKY}"
+    "amp-core:custom_build" # Backend + WebUI Agent
 )
 
 # REPO_ROOT Resolution
@@ -416,6 +418,48 @@
         echo "✅ Created $LOG_DIR"
     else
         echo "✅ Log directory already exists: $LOG_DIR"
+    fi
+    
+    # Configure Firewall Rules (if firewalld is available)
+    if command -v firewall-cmd &> /dev/null; then
+        echo ""
+        echo "--- Configuring Firewall Rules ---"
+        
+        # Check if firewalld is running
+        if systemctl is-active --quiet firewalld; then
+            echo "Configuring firewalld rules..."
+            
+            # Docker Swarm Ports
+            echo "  Adding Docker Swarm ports..."
+            sudo firewall-cmd --add-port=2377/tcp --permanent 2>/dev/null || true
+            sudo firewall-cmd --add-port=7946/tcp --permanent 2>/dev/null || true
+            sudo firewall-cmd --add-port=7946/udp --permanent 2>/dev/null || true
+            sudo firewall-cmd --add-port=4789/udp --permanent 2>/dev/null || true
+            
+            # AMP Service Ports
+            echo "  Adding AMP service ports..."
+            sudo firewall-cmd --add-port=80/tcp --permanent 2>/dev/null || true    # HTTP
+            sudo firewall-cmd --add-port=443/tcp --permanent 2>/dev/null || true   # HTTPS
+            sudo firewall-cmd --add-port=5000/tcp --permanent 2>/dev/null || true  # Local Registry
+            sudo firewall-cmd --add-port=5432/tcp --permanent 2>/dev/null || true  # Database (HAProxy/PGBouncer)
+            sudo firewall-cmd --add-port=5433/tcp --permanent 2>/dev/null || true  # Database (Direct Patroni)
+            sudo firewall-cmd --add-port=2379-2380/tcp --permanent 2>/dev/null || true  # Etcd
+            sudo firewall-cmd --add-port=8008/tcp --permanent 2>/dev/null || true  # Patroni API
+            sudo firewall-cmd --add-port=9200/tcp --permanent 2>/dev/null || true  # OpenSearch REST
+            sudo firewall-cmd --add-port=9300/tcp --permanent 2>/dev/null || true  # OpenSearch Transport
+            sudo firewall-cmd --add-port=5601/tcp --permanent 2>/dev/null || true  # OpenSearch Dashboards
+            sudo firewall-cmd --add-port=3000/tcp --permanent 2>/dev/null || true  # Grafana
+            sudo firewall-cmd --add-port=514/tcp --permanent 2>/dev/null || true   # Logstash Syslog TCP
+            sudo firewall-cmd --add-port=514/udp --permanent 2>/dev/null || true   # Logstash Syslog UDP
+            
+            # Reload firewall
+            sudo firewall-cmd --reload
+            echo "✅ Firewall rules configured and reloaded."
+        else
+            echo "⚠️  firewalld is not running. Skipping firewall configuration."
+        fi
+    else
+        echo "⚠️  firewall-cmd not found. Skipping firewall configuration."
     fi
     
     echo "✅ System tuning complete."
@@ -803,6 +847,9 @@
         if [ "$SERVICE_NAME" == "timescaledb" ]; then
             TAG="latest"
             SRC_IMAGE="amp/timescaledb:latest"
+        elif [ "$SERVICE_NAME" == "amp-core" ]; then
+            TAG="$TAG_AMP_CORE"
+            SRC_IMAGE="amp/amp-core:$TAG_AMP_CORE"
         else
             TAG="${UPSTREAM##*:}"
             SRC_IMAGE="$UPSTREAM"
@@ -823,6 +870,56 @@
                 echo "  ❌ Build failed. In offline mode, ensure amp/timescaledb:latest is pre-loaded."
                 continue
             }
+        elif [ "$SERVICE_NAME" == "amp-core" ]; then
+            echo "  - Building amp-core Image (Backend + WebUI Agent)..."
+            
+            # Copy binaries from build output to the Docker context
+            AMP_CORE_DIR="$SERVICES_DIR/amp-core"
+            AMP_CORE_BIN="$AMP_CORE_DIR/bin"
+            PROJECT_ROOT="$SCRIPT_DIR/../../.."
+            
+            mkdir -p "$AMP_CORE_BIN"
+            
+            # Find and copy backend binary
+            if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/backend/backend" ]; then
+                echo "  - Copying backend from build output..."
+                cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/backend/backend" "$AMP_CORE_BIN/"
+            elif [ -f "/ca/bin/backend" ]; then
+                echo "  - Copying backend from /ca/bin..."
+                cp "/ca/bin/backend" "$AMP_CORE_BIN/"
+            else
+                echo "  ❌ backend binary not found! Run 'make amp' first."
+                continue
+            fi
+            
+            # Find and copy webui_agent binary
+            if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/webui_agent/webui_agent" ]; then
+                echo "  - Copying webui_agent from build output..."
+                cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/webui_agent/webui_agent" "$AMP_CORE_BIN/"
+            elif [ -f "/ca/bin/webui_agent" ]; then
+                echo "  - Copying webui_agent from /ca/bin..."
+                cp "/ca/bin/webui_agent" "$AMP_CORE_BIN/"
+            else
+                echo "  ❌ webui_agent binary not found! Run 'make amp' first."
+                continue
+            fi
+            
+            # Find and copy ca_shell binary
+            if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/cli/ca_shell" ]; then
+                echo "  - Copying ca_shell from build output..."
+                cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/cli/ca_shell" "$AMP_CORE_BIN/"
+            elif [ -f "/ca/bin/ca_shell" ]; then
+                echo "  - Copying ca_shell from /ca/bin..."
+                cp "/ca/bin/ca_shell" "$AMP_CORE_BIN/"
+            else
+                echo "  ⚠️ ca_shell binary not found. Skipping."
+            fi
+            
+            # Build the Docker image
+            docker build -t "$LOCAL_TAG" "$AMP_CORE_DIR" || {
+                echo "  ❌ Build failed. Ensure binaries are present in $AMP_CORE_BIN."
+                continue
+            }
         else
             echo "  - Pulling $UPSTREAM"
             docker pull -q "$UPSTREAM" || {
@@ -931,6 +1028,11 @@
             echo "✅ Created volume: $vol"
         fi
     done
+    
+    # 1b. Create directories required for amp-core bind mounts
+    echo "Creating required host directories for amp-core..."
+    sudo mkdir -p /ca/conf /ca/etc "${AMP_LOG_ROOT:-/var/log/amp}/amp-core"
+    echo "✅ Created /ca/conf, /ca/etc, ${AMP_LOG_ROOT:-/var/log/amp}/amp-core"
 
     # 2. Check if Certificates Exist
     echo "Checking for existing certificates..."
@@ -948,8 +1050,76 @@
     calculate_heap_size
     generate_configs
     
+    # 4. Setup ca_shell wrapper for VM users
+    echo "--- Setting up ca_shell wrapper ---"
+    if [ ! -d "/ca/bin" ]; then
+        sudo mkdir -p /ca/bin
+    fi
+    
+    CA_SHELL_WRAPPER_SRC="$SCRIPT_DIR/scripts/ca_shell_wrapper.sh"
+    CA_SHELL_WRAPPER_DST="/ca/bin/ca_shell"
+    
+    # Copy from scripts directory if available, otherwise create inline
+    if [ -f "$CA_SHELL_WRAPPER_SRC" ]; then
+        sudo cp "$CA_SHELL_WRAPPER_SRC" "$CA_SHELL_WRAPPER_DST"
+    else
+        echo "Creating ca_shell wrapper script..."
+        sudo tee "$CA_SHELL_WRAPPER_DST" > /dev/null << 'WRAPPER_EOF'
+#!/bin/bash
+# ca_shell wrapper for Docker-containerized backend
+# Uses sudo to avoid requiring docker group membership
+
+CONTAINER_ID=$(sudo docker ps --format "{{.ID}} {{.Names}}" 2>/dev/null | grep "amp_amp-core" | awk '{print $1}' | head -1)
+
+if [ -z "$CONTAINER_ID" ]; then
+    echo "Error: amp-core container is not running."
+    echo "Check: docker service ls | grep amp-core"
+    exit 1
+fi
+
+exec sudo docker exec -it "$CONTAINER_ID" /ca/bin/ca_shell "$@"
+WRAPPER_EOF
+    fi
+    
+    sudo chmod +x "$CA_SHELL_WRAPPER_DST"
+    echo "✅ Installed ca_shell wrapper to $CA_SHELL_WRAPPER_DST"
+    
+    # Set SELinux context for shell (required for SSH login)
+    if command -v chcon &> /dev/null && [ "$(getenforce 2>/dev/null)" = "Enforcing" ]; then
+        sudo chcon -t shell_exec_t "$CA_SHELL_WRAPPER_DST" 2>/dev/null || true
+        echo "✅ Set SELinux context for $CA_SHELL_WRAPPER_DST"
+    fi
+    
+    # Add to /etc/shells if not already present
+    if ! grep -q "^$CA_SHELL_WRAPPER_DST$" /etc/shells 2>/dev/null; then
+        echo "$CA_SHELL_WRAPPER_DST" | sudo tee -a /etc/shells > /dev/null
+        echo "✅ Added $CA_SHELL_WRAPPER_DST to /etc/shells"
+    fi
+    
+    # Configure sudoers to allow ca_shell users to run docker without password
+    SUDOERS_FILE="/etc/sudoers.d/ca_shell"
+    if [ ! -f "$SUDOERS_FILE" ]; then
+        echo "Configuring sudo for ca_shell users..."
+        sudo tee "$SUDOERS_FILE" > /dev/null << 'SUDOERS_EOF'
+# Allow ca_shell wrapper to run docker commands without password
+# Users with /ca/bin/ca_shell as login shell can use docker
+Defaults!/usr/bin/docker !requiretty
+ALL ALL=(root) NOPASSWD: /usr/bin/docker ps *, /usr/bin/docker exec *
+SUDOERS_EOF
+        sudo chmod 440 "$SUDOERS_FILE"
+        echo "✅ Configured sudo for docker access"
+    fi
+    
     echo "--- Deploying Stack: $STACK_NAME (Registry: $REGISTRY) ---"
     docker stack deploy -c "$STACK_FILE" $STACK_NAME
+    
+    echo ""
+    echo "=== Deployment Complete ==="
+    echo ""
+    echo "To create CLI users for SSH access:"
+    echo "  sudo useradd -m -s /ca/bin/ca_shell amp_operator"
+    echo "  sudo passwd amp_operator"
+    echo ""
 }
 
 rm_stack() {
@@ -1232,6 +1402,54 @@
              echo "  - Building Custom Image..."
              retry_command "docker build -t amp/timescaledb:latest -f \"$SERVICES_DIR/timescaledb/Dockerfile.patroni\" \"$SERVICES_DIR/timescaledb\"" || exit 1
              IMAGE_LIST="amp/timescaledb:latest $IMAGE_LIST"
+        elif [ "$SERVICE_NAME" == "amp-core" ]; then
+             echo "  - Building amp-core Image (Backend + WebUI Agent)..."
+             
+             # Copy binaries from build output to the Docker context
+             AMP_CORE_DIR="$SERVICES_DIR/amp-core"
+             AMP_CORE_BIN="$AMP_CORE_DIR/bin"
+             PROJECT_ROOT="$SCRIPT_DIR/../../.."
+             
+             mkdir -p "$AMP_CORE_BIN"
+             
+             # Find and copy backend binary
+             if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/backend/backend" ]; then
+                 echo "  - Copying backend from build output..."
+                 cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/backend/backend" "$AMP_CORE_BIN/"
+             elif [ -f "/ca/bin/backend" ]; then
+                 echo "  - Copying backend from /ca/bin..."
+                 cp "/ca/bin/backend" "$AMP_CORE_BIN/"
+             else
+                 echo "  ❌ backend binary not found! Run 'make amp' first."
+                 exit 1
+             fi
+             
+             # Find and copy webui_agent binary
+             if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/webui_agent/webui_agent" ]; then
+                 echo "  - Copying webui_agent from build output..."
+                 cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/webui_agent/webui_agent" "$AMP_CORE_BIN/"
+             elif [ -f "/ca/bin/webui_agent" ]; then
+                 echo "  - Copying webui_agent from /ca/bin..."
+                 cp "/ca/bin/webui_agent" "$AMP_CORE_BIN/"
+             else
+                 echo "  ❌ webui_agent binary not found! Run 'make amp' first."
+                 exit 1
+             fi
+             
+             # Find and copy ca_shell binary
+             if [ -f "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/cli/ca_shell" ]; then
+                 echo "  - Copying ca_shell from build output..."
+                 cp "$PROJECT_ROOT/build/array/BUILD/amp-4.0.0/src/cli/ca_shell" "$AMP_CORE_BIN/"
+             elif [ -f "/ca/bin/ca_shell" ]; then
+                 echo "  - Copying ca_shell from /ca/bin..."
+                 cp "/ca/bin/ca_shell" "$AMP_CORE_BIN/"
+             else
+                 echo "  ⚠️ ca_shell binary not found. Skipping."
+             fi
+             
+             # Build the Docker image
+             retry_command "docker build -t amp/amp-core:${TAG_AMP_CORE} \"$AMP_CORE_DIR\"" || exit 1
+             IMAGE_LIST="amp/amp-core:${TAG_AMP_CORE} $IMAGE_LIST"
         else
              echo "  - Pulling $UPSTREAM"
              retry_command "docker pull -q $UPSTREAM" || exit 1
@@ -1257,6 +1475,7 @@
     cp install_prerequisites.sh "$BUNDLE_DIR/"
     cp stack.yml.template "$BUNDLE_DIR/"
     cp -r services "$BUNDLE_DIR/"
+    cp -r scripts "$BUNDLE_DIR/" 2>/dev/null || echo "⚠️  No scripts directory found"
     
     # Copy .env if it exists
     if [ -f ".env" ]; then
@@ -1378,6 +1597,12 @@
         fi
         echo "✅ Local Registry started."
         
+        # Configure insecure registry for both localhost and host IP
+        echo "Configuring Docker Insecure Registry..."
+        detect_host_ip  # Ensure we have the host IP
+        configure_insecure_registry "127.0.0.1:5000"
+        configure_insecure_registry "${AMP_DOMAIN_OR_IP}:5000"
+        
         # 4. Retag and push images to Local Registry
         echo "Retagging images for Local Registry..."
         
@@ -1385,24 +1610,40 @@
             SERVICE_NAME="${INFO%%:*}"
             UPSTREAM="${INFO#*:}"
             
-            # Determine Tag
+            # Determine Tag and Source Image for custom builds
             if [ "$SERVICE_NAME" == "timescaledb" ]; then
                 TAG="latest"
                 SRC_IMAGE="amp/timescaledb:latest"
+            elif [ "$SERVICE_NAME" == "amp-core" ]; then
+                TAG="$TAG_AMP_CORE"
+                SRC_IMAGE="amp/amp-core:$TAG_AMP_CORE"
             else
                 TAG="${UPSTREAM##*:}"
                 SRC_IMAGE="$UPSTREAM"
             fi
             
+            # Push to both localhost and host IP to ensure accessibility
             LOCAL_TAG="127.0.0.1:5000/amp/$SERVICE_NAME:$TAG"
+            HOST_TAG="${AMP_DOMAIN_OR_IP}:5000/amp/$SERVICE_NAME:$TAG"
             
             echo "  - $SRC_IMAGE -> $LOCAL_TAG"
             docker tag "$SRC_IMAGE" "$LOCAL_TAG"
             docker push "$LOCAL_TAG"
+            
+            # Also tag with host IP for Swarm node access
+            docker tag "$SRC_IMAGE" "$HOST_TAG"
+            docker push "$HOST_TAG" 2>/dev/null || true
         done
         
         echo "✅ Images pushed to local registry."
         
+        echo ""
+        echo "✅ Offline bundle loaded successfully!"
+        echo ""
+        echo "Next steps:"
+        echo "  1. Initialize Swarm (if not already): ./manage_amp.sh init"
+        echo "  2. Deploy with auto-config: ./manage_amp.sh deploy --auto"
+        
     else
         echo "❌ images/amp_images.tar.gz not found!"
         exit 1
Index: /branches/amp_4_0/platform/tools/container/scripts/ca_shell_wrapper.sh
===================================================================
--- /branches/amp_4_0/platform/tools/container/scripts/ca_shell_wrapper.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/scripts/ca_shell_wrapper.sh	(working copy)
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+# ca_shell wrapper for Docker-containerized backend
+# This script runs on the VM host and connects to the amp-core container
+#
+# Uses sudo to avoid requiring docker group membership
+#
+# Installation:
+#   1. Copy this script to /ca/bin/ca_shell on the VM host
+#   2. chmod +x /ca/bin/ca_shell
+#   3. chcon -t shell_exec_t /ca/bin/ca_shell   # SELinux context
+#   4. Add to /etc/shells: echo "/ca/bin/ca_shell" >> /etc/shells
+#   5. Set as login shell: usermod -s /ca/bin/ca_shell <username>
+#
+
+# Find the running amp-core container (handles Docker Swarm naming)
+CONTAINER_ID=$(sudo docker ps --format "{{.ID}} {{.Names}}" 2>/dev/null | grep "amp_amp-core" | awk '{print $1}' | head -1)
+
+if [ -z "$CONTAINER_ID" ]; then
+    echo "Error: amp-core container is not running."
+    echo "Check: docker service ls | grep amp-core"
+    exit 1
+fi
+
+# Execute ca_shell inside the container
+# -i = interactive, -t = allocate TTY
+exec sudo docker exec -it "$CONTAINER_ID" /ca/bin/ca_shell "$@"
Index: /branches/amp_4_0/platform/tools/container/scripts/setup_user_shells.sh
===================================================================
--- /branches/amp_4_0/platform/tools/container/scripts/setup_user_shells.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/scripts/setup_user_shells.sh	(working copy)
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# Setup script to configure VM users for ca_shell or bash access
+# Run this on the VM host after deploying the AMP stack
+#
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+CA_SHELL_WRAPPER="/ca/bin/ca_shell"
+
+echo "=== AMP User Shell Configuration Setup ==="
+
+# Step 1: Create /ca/bin if it doesn't exist
+if [ ! -d "/ca/bin" ]; then
+    echo "Creating /ca/bin directory..."
+    sudo mkdir -p /ca/bin
+fi
+
+# Step 2: Copy the wrapper script
+echo "Installing ca_shell wrapper to $CA_SHELL_WRAPPER..."
+sudo cp "$SCRIPT_DIR/ca_shell_wrapper.sh" "$CA_SHELL_WRAPPER"
+sudo chmod +x "$CA_SHELL_WRAPPER"
+
+# Step 3: Set SELinux context (required for SSH login)
+if command -v chcon &> /dev/null && [ "$(getenforce 2>/dev/null)" = "Enforcing" ]; then
+    echo "Setting SELinux context for $CA_SHELL_WRAPPER..."
+    sudo chcon -t shell_exec_t "$CA_SHELL_WRAPPER"
+fi
+
+# Step 4: Add to /etc/shells if not already present
+if ! grep -q "^$CA_SHELL_WRAPPER$" /etc/shells; then
+    echo "Adding $CA_SHELL_WRAPPER to /etc/shells..."
+    echo "$CA_SHELL_WRAPPER" | sudo tee -a /etc/shells > /dev/null
+fi
+
+echo ""
+echo "=== Setup Complete ==="
+echo ""
+echo "To create a user with ca_shell access:"
+echo "  sudo useradd -m -s $CA_SHELL_WRAPPER cli_user"
+echo "  sudo passwd cli_user"
+echo "  sudo usermod -aG docker cli_user  # Required for docker access"
+echo ""
+echo "To change an existing user to ca_shell:"
+echo "  sudo usermod -s $CA_SHELL_WRAPPER existing_user"
+echo "  sudo usermod -aG docker existing_user"
+echo ""
+echo "To create a user with bash access (admin):"
+echo "  sudo useradd -m -s /bin/bash admin_user"
+echo "  sudo passwd admin_user"
+echo ""
+echo "Example users:"
+echo "  sudo useradd -m -s $CA_SHELL_WRAPPER amp_operator && sudo usermod -aG docker amp_operator"
+echo "  sudo useradd -m -s /bin/bash amp_admin"
+
Index: /branches/amp_4_0/platform/tools/container/services/amp-core/Dockerfile
===================================================================
--- /branches/amp_4_0/platform/tools/container/services/amp-core/Dockerfile	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/services/amp-core/Dockerfile	(working copy)
@@ -0,0 +1,54 @@
+FROM rockylinux:9
+
+LABEL maintainer="Array Networks" \
+      description="AMP Core Services - Backend and WebUI Agent" \
+      version="4.0.0"
+
+# Install runtime dependencies for backend and webui_agent binaries
+RUN dnf update -y && \
+    dnf install -y epel-release && \
+    dnf install -y --allowerasing \
+    # Network and crypto libraries
+    libcurl \
+    libxml2 \
+    openssl-libs \
+    # Terminal/UI libraries
+    ncurses-libs \
+    # Database client library
+    libpq \
+    # Compression
+    zlib \
+    # Process utilities
+    procps-ng \
+    # Process supervisor for managing multiple daemons (from EPEL)
+    supervisor \
+    && dnf clean all
+
+# Create AMP directory structure (matching VM layout)
+RUN mkdir -p /ca/bin \
+             /ca/conf \
+             /ca/etc \
+             /ca/webui \
+             /var/log/amp \
+             /var/log/supervisor
+
+# Copy pre-built binaries (built during CI/CD pipeline on build machine)
+COPY bin/backend /ca/bin/backend
+COPY bin/webui_agent /ca/bin/webui_agent
+COPY bin/ca_shell /ca/bin/ca_shell
+
+# Make binaries executable
+RUN chmod +x /ca/bin/backend /ca/bin/webui_agent /ca/bin/ca_shell
+
+# Copy supervisord configuration
+COPY supervisord.conf /etc/supervisord.conf
+
+# Expose webui_agent port (default 8889)
+EXPOSE 8889
+
+# Health check - verify webui_agent is running (backend daemonizes separately)
+HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
+    CMD supervisorctl status webui_agent | grep -q RUNNING || exit 1
+
+# Use supervisord as the main process to manage both backend and webui_agent
+CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
Index: /branches/amp_4_0/platform/tools/container/services/amp-core/README.md
===================================================================
--- /branches/amp_4_0/platform/tools/container/services/amp-core/README.md	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/services/amp-core/README.md	(working copy)
@@ -0,0 +1,95 @@
+# AMP Core Docker Image
+
+This directory contains the Docker image definition for running the AMP backend and webui_agent services as container processes.
+
+## Contents
+
+- `Dockerfile` - Docker image definition based on Rocky Linux 9
+- `supervisord.conf` - Supervisor configuration for managing both processes
+- `build.sh` - Build script to copy binaries and create the Docker image
+- `bin/` - Directory for pre-built binaries (populated by build.sh)
+
+## Prerequisites
+
+Before building the Docker image, ensure the binaries are compiled:
+
+```bash
+# From project root
+make
+```
+
+This will compile:
+
+- `src/backend/backend` - Main AMP daemon
+- `src/webui_agent/webui_agent` - Web UI CLI handler
+
+## Building the Image
+
+```bash
+# Using default settings (tag: latest, registry: 127.0.0.1:5000)
+./build.sh
+
+# With specific tag
+./build.sh 4.0.0
+
+# With custom registry
+./build.sh 4.0.0 myregistry.example.com:5000
+```
+
+## Running Locally (Testing)
+
+```bash
+docker run -d --name amp-core-test \
+  -v /ca/conf:/ca/conf \
+  -v /ca/etc:/ca/etc:ro \
+  -p 8889:8889 \
+  127.0.0.1:5000/amp/amp-core:latest
+```
+
+## Checking Process Status
+
+```bash
+# View supervisor status
+docker exec amp-core-test supervisorctl status
+
+# View logs
+docker exec amp-core-test cat /var/log/amp/backend.log
+docker exec amp-core-test cat /var/log/amp/webui_agent.log
+```
+
+## Architecture
+
+```
+┌─────────────────────────────────────────┐
+│         amp-core Container              │
+│                                         │
+│  ┌─────────────────────────────────┐   │
+│  │        supervisord (PID 1)       │   │
+│  └─────────────┬───────────────────┘   │
+│                │                        │
+│       ┌────────┴────────┐              │
+│       ▼                 ▼              │
+│  ┌─────────┐      ┌────────────┐       │
+│  │ backend │      │ webui_agent│       │
+│  └─────────┘      └────────────┘       │
+│                         │              │
+│                    Port 8889           │
+└─────────────────────────────────────────┘
+```
+
+## Volume Mounts
+
+| Host Path | Container Path | Mode | Description |
+|-----------|----------------|------|-------------|
+| `/ca/conf` | `/ca/conf` | rw | Configuration files |
+| `/ca/etc` | `/ca/etc` | ro | Static configuration |
+| `${AMP_LOG_ROOT}/amp-core` | `/var/log/amp` | rw | Log files |
+
+## Environment Variables
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `DB_HOST` | `host.docker.internal` | Database host |
+| `DB_PORT` | `5432` | Database port |
+| `DB_USER` | `postgres` | Database user |
+| `DB_PASSWORD` | - | Database password |
Index: /branches/amp_4_0/platform/tools/container/services/amp-core/build.sh
===================================================================
--- /branches/amp_4_0/platform/tools/container/services/amp-core/build.sh	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/services/amp-core/build.sh	(working copy)
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Build script for amp-core Docker image
+# This script copies pre-built binaries and builds the Docker image
+#
+# Usage:
+#   ./build.sh [TAG] [REGISTRY]
+#
+# Examples:
+#   ./build.sh                     # Build with default tag 'latest' and registry '127.0.0.1:5000'
+#   ./build.sh 1.0.0               # Build with specific version tag
+#   ./build.sh 1.0.0 myregistry    # Build with custom registry
+#
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_ROOT="${SCRIPT_DIR}/../../../../../"
+TAG="${1:-1.0.0}"
+REGISTRY="${2:-127.0.0.1:5000}"
+
+echo "=============================================="
+echo "Building amp-core Docker image"
+echo "Tag: ${TAG}"
+echo "Registry: ${REGISTRY}"
+echo "=============================================="
+
+# Create bin directory if it doesn't exist
+mkdir -p "${SCRIPT_DIR}/bin"
+
+# Function to find and copy binary
+copy_binary() {
+    local binary_name="$1"
+    local src_subdir="$2"  # Subdirectory under src/ where the binary lives
+    local found=false
+    
+    # Priority 1: Check RPM build output (after 'make amp')
+    if [ -f "${PROJECT_ROOT}/build/array/BUILD/amp-4.0.0/src/${src_subdir}/${binary_name}" ]; then
+        echo "✓ Found ${binary_name} at build/array/BUILD/amp-4.0.0/src/${src_subdir}/${binary_name}"
+        cp "${PROJECT_ROOT}/build/array/BUILD/amp-4.0.0/src/${src_subdir}/${binary_name}" "${SCRIPT_DIR}/bin/"
+        found=true
+    # Priority 2: Check if installed on system (e.g., after RPM install)
+    elif [ -f "/ca/bin/${binary_name}" ]; then
+        echo "✓ Found ${binary_name} at /ca/bin/${binary_name}"
+        cp "/ca/bin/${binary_name}" "${SCRIPT_DIR}/bin/"
+        found=true
+    # Priority 3: Check source directory (after local 'make')
+    elif [ -f "${PROJECT_ROOT}/src/${src_subdir}/${binary_name}" ]; then
+        echo "✓ Found ${binary_name} at src/${src_subdir}/${binary_name}"
+        cp "${PROJECT_ROOT}/src/${src_subdir}/${binary_name}" "${SCRIPT_DIR}/bin/"
+        found=true
+    fi
+    
+    if [ "$found" = false ]; then
+        echo "ERROR: ${binary_name} binary not found!"
+        echo "Please build the project first using 'make amp' in the project root."
+        echo "Searched locations:"
+        echo "  - ${PROJECT_ROOT}/build/array/BUILD/amp-4.0.0/src/${src_subdir}/${binary_name}"
+        echo "  - /ca/bin/${binary_name}"
+        echo "  - ${PROJECT_ROOT}/src/${src_subdir}/${binary_name}"
+        return 1
+    fi
+    
+    return 0
+}
+
+# Copy required binaries
+echo ""
+echo "Copying binaries..."
+copy_binary "backend" "backend" || exit 1
+copy_binary "webui_agent" "webui_agent" || exit 1
+
+echo ""
+echo "Building Docker image..."
+docker build -t "${REGISTRY}/amp/amp-core:${TAG}" "${SCRIPT_DIR}"
+
+echo ""
+echo "=============================================="
+echo "✅ Successfully built: ${REGISTRY}/amp/amp-core:${TAG}"
+echo "=============================================="
+echo ""
+echo "To push to registry:"
+echo "  docker push ${REGISTRY}/amp/amp-core:${TAG}"
+echo ""
+echo "To run locally for testing:"
+echo "  docker run -d --name amp-core-test \\"
+echo "    -v /ca/conf:/ca/conf \\"
+echo "    -v /ca/etc:/ca/etc:ro \\"
+echo "    ${REGISTRY}/amp/amp-core:${TAG}"

Property changes on: platform/tools/container/services/amp-core/build.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/amp_4_0/platform/tools/container/services/amp-core/supervisord.conf
===================================================================
--- /branches/amp_4_0/platform/tools/container/services/amp-core/supervisord.conf	(nonexistent)
+++ /branches/amp_4_0/platform/tools/container/services/amp-core/supervisord.conf	(working copy)
@@ -0,0 +1,60 @@
+[supervisord]
+nodaemon=true
+logfile=/var/log/supervisor/supervisord.log
+pidfile=/var/run/supervisord.pid
+childlogdir=/var/log/supervisor
+user=root
+loglevel=info
+
+; ============================================================
+; Backend Service - Main AMP Daemon
+; NOTE: Backend calls daemon() and forks to background.
+; We use startsecs=0 and autorestart=false since it daemonizes.
+; ============================================================
+[program:backend]
+command=/ca/bin/backend
+directory=/ca
+autostart=true
+autorestart=false
+startsecs=0
+startretries=1
+stopwaitsecs=10
+stdout_logfile=/var/log/amp/backend.log
+stdout_logfile_maxbytes=50MB
+stdout_logfile_backups=3
+stderr_logfile=/var/log/amp/backend-error.log
+stderr_logfile_maxbytes=50MB
+stderr_logfile_backups=3
+priority=100
+
+; ============================================================
+; WebUI Agent Service - CLI Handler for Web Interface
+; ============================================================
+[program:webui_agent]
+command=/ca/bin/webui_agent
+directory=/ca
+autostart=true
+autorestart=true
+startsecs=3
+startretries=3
+stopwaitsecs=10
+stdout_logfile=/var/log/amp/webui_agent.log
+stdout_logfile_maxbytes=50MB
+stdout_logfile_backups=3
+stderr_logfile=/var/log/amp/webui_agent-error.log
+stderr_logfile_maxbytes=50MB
+stderr_logfile_backups=3
+priority=200
+
+; ============================================================
+; Supervisor Control Interface
+; ============================================================
+[supervisorctl]
+serverurl=unix:///var/run/supervisor.sock
+
+[unix_http_server]
+file=/var/run/supervisor.sock
+chmod=0700
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
Index: /branches/amp_4_0/platform/tools/container/stack.yml.template
===================================================================
--- /branches/amp_4_0/platform/tools/container/stack.yml.template	(revision 2885)
+++ /branches/amp_4_0/platform/tools/container/stack.yml.template	(working copy)
@@ -428,6 +428,49 @@
     networks:
       - amp-overlay
 
+  # --- AMP Core Services (Backend + WebUI Agent) ---
+  amp-core:
+    image: ${REGISTRY:-127.0.0.1:5000}/amp/amp-core:${TAG_AMP_CORE:-latest}
+    deploy:
+      mode: global  # Run on every node
+      restart_policy:
+        condition: on-failure
+        delay: 5s
+        max_attempts: 3
+    healthcheck:
+      # Check only webui_agent - backend daemonizes and exits from supervisor's view
+      test: ["CMD", "supervisorctl", "status", "webui_agent"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+      start_period: 30s
+    environment:
+      - DB_HOST=host.docker.internal
+      - DB_PORT=5432
+      - DB_USER=${POSTGRES_USER:-postgres}
+      - DB_PASSWORD=${POSTGRES_PASSWORD:-Arr@y2050}
+    volumes:
+      # Mount configuration directories from host
+      - type: bind
+        source: /ca/conf
+        target: /ca/conf
+      - type: bind
+        source: /ca/etc
+        target: /ca/etc
+        read_only: true
+      # Mount log directory
+      - type: bind
+        source: ${AMP_LOG_ROOT:-/var/log/amp}/amp-core
+        target: /var/log/amp
+    extra_hosts:
+      - "host.docker.internal:host-gateway"
+    networks:
+      - hostnet
+    ports:
+      - target: 8889
+        published: ${AMP_WEBUI_AGENT_PORT:-8889}
+        mode: host
+
 volumes:
   opensearch-data:
   timescaledb-data:
