# 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 # Check health status docker inspect | 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