# Portainer Deployment Guide

This guide provides step-by-step instructions for deploying the Shopify AI App Builder to Portainer.

## Quick Start

1. **Go to Portainer** → Stacks → Add Stack
2. **Name your stack**: e.g., `shopify-ai-builder`
3. **Upload** `stack-portainer.yml` or paste its contents
4. **Set environment variables** (see below)
5. **Deploy**

## Environment Variables Setup

### Critical: Avoid Copy-Paste Issues

**UPDATE:** The latest version of the container automatically sanitizes environment variables on startup, removing invisible Unicode characters. However, it's still best practice to manually type variable names when possible.

When setting environment variables in Portainer, **manually type** the variable names and values instead of copying and pasting. This prevents invisible Unicode characters (like U+200E) from being inserted, which could cause deployment failures on older versions.

### Required Variables

```env
# OpenRouter API key (for AI planning mode)
OPENROUTER_API_KEY=your_openrouter_key

# Admin credentials for /admin dashboard
ADMIN_USER=admin
ADMIN_PASSWORD=your_secure_password

# Terminal password (for port 4001)
ACCESS_PASSWORD=your_terminal_password
```

### Optional Variables

```env
# OpenCode API key (required for some providers/models)
OPENCODE_API_KEY=your_opencode_key

# GitHub integration
GITHUB_PAT=your_github_token
GITHUB_USERNAME=your_github_username
GITHUB_CLIENT_ID=your_github_oauth_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_client_secret

# Dodo Payments integration
DODO_PAYMENTS_API_KEY=dp_test_...
DODO_PAYMENTS_ENV=test
DODO_PAYMENTS_WEBHOOK_KEY=whsec_...
DODO_TOPUP_PRODUCT_FREE=prod_free_topup
DODO_TOPUP_PRODUCT_PLUS=prod_plus_topup
DODO_TOPUP_PRODUCT_PRO=prod_pro_topup
DODO_TOPUP_TOKENS_FREE=500000
DODO_TOPUP_TOKENS_PLUS=1000000
DODO_TOPUP_TOKENS_PRO=1000000
DODO_MIN_AMOUNT=50

# Google OAuth
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret

# OAuth callback base URL (optional, for reverse proxies)
PUBLIC_BASE_URL=https://your-domain.com

# Session configuration
SESSION_SECRET=your_random_secret_key

# OpenRouter model configuration
OPENROUTER_MODEL_PRIMARY=anthropic/claude-3.5-sonnet
OPENROUTER_DEFAULT_MODEL=openai/gpt-4o-mini
```

## Common Deployment Errors

### Error: "unexpected character \u200e in variable name"

**Full error message:**
```
Failed to deploy a stack: unable to get the environment from the env file: 
failed to read /data/compose/42/stack.env: line 8: unexpected character "\u200e" 
in variable name "ADMIN_USER\u200e=user"
```

**Cause:**
Invisible Unicode characters (U+200E Left-to-Right Mark, U+200B Zero-Width Space, etc.) were copied into the variable names or values. This typically happens when:
- Copying from web pages or documentation
- Pasting from certain text editors (especially rich text editors)
- Copying from PDFs or formatted documents

**Automatic Fix (Latest Version):**
The container now automatically sanitizes environment variables on startup, removing these invisible characters. Simply rebuild or pull the latest image:

```bash
# Pull latest image
docker pull your-registry/shopify-ai-builder:latest

# Or rebuild locally
docker compose build --no-cache

# Redeploy in Portainer
```

**Manual Solutions (if automatic fix doesn't work):**

#### Solution 1: Recreate Variables Manually (Recommended)
1. In Portainer, delete all environment variables
2. **Manually type** each variable name and value (don't copy-paste)
3. Save and redeploy

#### Solution 2: Use a Clean .env File
1. Download the clean `.env.example` from the repository
2. Fill in your values using a plain text editor (Notepad++, VS Code, nano, vim)
3. Run the validation script:
   ```bash
   ./scripts/validate-env.sh .env
   ```
4. If issues are found, clean the file:
   ```bash
   ./scripts/clean-env.sh .env
   ```
5. Upload to Portainer or copy-paste the cleaned values

#### Solution 3: Use the Cleanup Script
If you already have a `.env` file with invisible characters:

```bash
# Validate the file
./scripts/validate-env.sh your-file.env

# Clean invisible characters
./scripts/clean-env.sh your-file.env

# Verify it's clean
./scripts/validate-env.sh your-file.env
```

### Error: "secret GITHUB_PAT not found"

**Cause:**
The stack references a Docker secret `GITHUB_PAT` that doesn't exist in Portainer.

**Solutions:**

#### Option 1: Remove the secret reference
Edit `stack-portainer.yml` and remove these sections:
```yaml
# Remove this from the service:
    secrets:
      - GITHUB_PAT

# Remove this entire section at the bottom:
secrets:
  GITHUB_PAT:
    external: true
```

Then set `GITHUB_PAT` as a regular environment variable instead.

#### Option 2: Create the secret in Portainer
1. Go to Portainer → Secrets → Add Secret
2. Name: `GITHUB_PAT`
3. Secret: paste your GitHub Personal Access Token
4. Save and redeploy the stack

### Error: Port conflicts

**Cause:**
Ports 4000 or 4001 are already in use by another service.

**Solution:**
Change the ports in the stack configuration:
```yaml
ports:
  - "5000:4000"  # Map external 5000 to internal 4000
  - "5001:4001"  # Map external 5001 to internal 4001
```

### Error: Architecture mismatch / Exit code 139 / Segmentation fault

**Full error message:**
```
ERROR: process "/bin/sh -c ..." did not complete successfully: exit code: 139
```

**Cause:**
Exit code 139 indicates a segmentation fault, which typically occurs when:
- Building an image on one architecture (e.g., ARM64) but trying to run binaries compiled for another (e.g., AMD64)
- The build process isn't properly detecting the target platform
- Cross-architecture builds without proper emulation (QEMU)
- Docker buildx not properly passing `TARGETARCH` build argument

**Solution:**

The Dockerfile has been updated to properly use Docker's `TARGETARCH` build argument, which Portainer automatically provides. This ensures the correct binaries are downloaded for your host architecture.

**If you still encounter this error:**

1. **Check your host architecture:**
   ```bash
   # On the Portainer host
   uname -m
   # x86_64 = amd64
   # aarch64 = arm64
   ```

2. **Rebuild with --no-cache to ensure fresh build:**
   - In Portainer → Stacks → Your Stack → Editor
   - Check "Re-pull image and re-deploy" or use "Build" option
   - Enable "No cache" if available

3. **Verify build logs:**
   - Look for messages like "Unsupported architecture" in the build logs
   - Check if the correct binaries are being downloaded (should match your host arch)

4. **For ARM hosts (Raspberry Pi, Apple Silicon, AWS Graviton, etc.):**
   - Ensure your Portainer is up-to-date (needs buildx support)
   - The Dockerfile will automatically download ARM64 binaries

5. **For AMD64 hosts:**
   - Standard x86_64 servers should work without any changes

6. **Advanced: Force specific platform (not recommended):**
   ```yaml
   # Only use if auto-detection fails
   services:
     shopify-ai-builder:
       platform: linux/amd64  # or linux/arm64
   ```

**Why this was happening:**

The previous version used `dpkg --print-architecture` to detect the architecture, which doesn't work reliably in cross-platform Docker builds. The updated Dockerfile now:

1. Prioritizes Docker's `TARGETARCH` build argument (passed by Portainer/buildx)
2. Falls back to `dpkg` if `TARGETARCH` is not available
3. Provides detailed error messages showing the detected platform

This ensures reliable builds on both AMD64 and ARM64 architectures in Portainer.

## Post-Deployment

### Access Points
- **Web UI**: `http://your-server:4000`
- **Terminal**: `http://your-server:4001`
- **Admin Dashboard**: `http://your-server:4000/admin`

### Health Check
```bash
# Check if the container is running
docker ps | grep shopify-ai-builder

# View logs
docker logs -f <container-id>

# Check health status
docker inspect <container-id> | grep -A 10 Health
```

### Testing the Deployment
1. Open `http://your-server:4000` in a browser
2. You should see the Shopify AI App Builder homepage
3. Click "Get Started" to create your first app
4. Enter a test message to verify the AI responds

## Production Recommendations

- **Use HTTPS**: Set up a reverse proxy (NGINX, Traefik, or Caddy) with SSL/TLS
- **Set strong passwords**: For `ADMIN_PASSWORD` and `ACCESS_PASSWORD`
- **Use secrets**: For sensitive values like API keys and tokens
- **Enable secure cookies**: Set `COOKIE_SECURE=1` when using HTTPS
- **Configure firewall**: Restrict access to ports 4000 and 4001
- **Regular backups**: Backup the `web_data` volume regularly
- **Resource limits**: Adjust CPU and memory limits based on your usage

## Volume Management

The stack creates two volumes:

1. **shopify_ai_pwsh_profile**: PowerShell profile and configuration
2. **shopify_ai_data**: All app data, sessions, and workspaces

To backup:
```bash
# Create backup directory
mkdir -p backups

# Backup data volume
docker run --rm \
  -v shopify_ai_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/shopify-data-$(date +%Y%m%d).tar.gz /data
```

To restore:
```bash
# Restore data volume
docker run --rm \
  -v shopify_ai_data:/data \
  -v $(pwd)/backups:/backup \
  alpine tar xzf /backup/shopify-data-20240101.tar.gz -C /
```

## Troubleshooting Commands

```bash
# View real-time logs
docker logs -f shopify-ai-builder

# Enter the container
docker exec -it shopify-ai-builder bash

# Check OpenCode installation
docker exec shopify-ai-builder opencode --version

# Restart the container
docker restart shopify-ai-builder

# Check environment variables
docker exec shopify-ai-builder env | grep -E "(ADMIN|OPENROUTER|GITHUB)"
```

## Support

If you encounter issues not covered here:
1. Check the main [README.md](README.md) troubleshooting section
2. Review container logs for error messages
3. Open a GitHub issue with:
   - Error message
   - Deployment method (Portainer)
   - Stack configuration (redact sensitive values)
   - Container logs
