{"id":31644494,"url":"https://github.com/pantaleone-ai/selfhosted-ai-workflow-content-engine","last_synced_at":"2025-10-07T04:53:28.852Z","repository":{"id":297545587,"uuid":"997101539","full_name":"pantaleone-ai/selfhosted-ai-workflow-content-engine","owner":"pantaleone-ai","description":"Self-hosted AI content engine with LLM support (GPT, open-source models) — build and run your own marketing, SEO, and automation pipelines in under 60 minutes.","archived":false,"fork":false,"pushed_at":"2025-10-03T19:39:18.000Z","size":246,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-03T21:33:08.411Z","etag":null,"topics":["ampere","docker-compose","llama","llamacpp","llm","n8n","openwebui","oracle-cloud","postgres","qwen3","redis","traefik"],"latest_commit_sha":null,"homepage":"https://saas-ai-starter.vercel.app/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pantaleone-ai.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["pantaleone-ai"],"custom":["https://github.com/sponsors/pantaleone-ai","https://rapigent.com"]}},"created_at":"2025-06-06T00:49:48.000Z","updated_at":"2025-10-03T19:39:21.000Z","dependencies_parsed_at":"2025-06-06T03:27:03.693Z","dependency_job_id":"fb9c449e-02ce-41a6-9501-19155da149e3","html_url":"https://github.com/pantaleone-ai/selfhosted-ai-workflow-content-engine","commit_stats":null,"previous_names":["pantaleone-ai/selfhosted-ai-engine","pantaleone-ai/selfhosted-ai-workflow-content-engine"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pantaleone-ai/selfhosted-ai-workflow-content-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaleone-ai%2Fselfhosted-ai-workflow-content-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaleone-ai%2Fselfhosted-ai-workflow-content-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaleone-ai%2Fselfhosted-ai-workflow-content-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaleone-ai%2Fselfhosted-ai-workflow-content-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pantaleone-ai","download_url":"https://codeload.github.com/pantaleone-ai/selfhosted-ai-workflow-content-engine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pantaleone-ai%2Fselfhosted-ai-workflow-content-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278722768,"owners_count":26034461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-07T02:00:06.786Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ampere","docker-compose","llama","llamacpp","llm","n8n","openwebui","oracle-cloud","postgres","qwen3","redis","traefik"],"created_at":"2025-10-07T04:53:24.611Z","updated_at":"2025-10-07T04:53:28.846Z","avatar_url":"https://github.com/pantaleone-ai.png","language":null,"funding_links":["https://github.com/sponsors/pantaleone-ai","https://rapigent.com"],"categories":[],"sub_categories":[],"readme":"# Create Your Own Local Agentic AI Content Engine\nCreate an AI content engine in less than 60 minutes for free!  Note, some of my specific configs are included below; tune to your own use case!\n\n[![GitHub stars](https://img.shields.io/github/stars/pantaleone-ai/selfhosted-ai-engine?style=social)](https://github.com/pantaleone-ai/selfhosted-ai-engine/stargazers)\n[![GitHub forks](https://img.shields.io/github/forks/pantaleone-ai/selfhosted-ai-engine?style=social)](https://github.com/pantaleone-ai/selfhosted-ai-engine/network/members)\n[![GitHub issues](https://img.shields.io/github/issues/pantaleone-ai/selfhosted-ai-engine)](https://github.com/pantaleone-ai/selfhosted-ai-engine/issues)\n[![License](https://img.shields.io/github/license/pantaleone-ai/selfhosted-ai-engine)](./LICENSE)\n[![Last commit](https://img.shields.io/github/last-commit/pantaleone-ai/selfhosted-ai-engine)](https://github.com/pantaleone-ai/selfhosted-ai-engine/commits/main)\n\n\n# Step 1 - Get an OCI (or similar) Server\n\n## 1. Sign Up for OCI Always Free\n\n*   **Access the Free Tier:** Go to the [Oracle Cloud website](https://www.oracle.com/cloud/free/).\n*   **Create Account:** Sign up for a Free Tier account.\n    *   *Note:* A credit card is required for identity verification, but you will not be charged for Always Free resources unless you explicitly upgrade.\n\n## 2. Launch Your Ampere VM Instance\n\nOnce logged into your OCI console, follow these steps to create your virtual machine (VM) instance:\n\n*   **Navigate to Instances:** In the OCI console, select **Compute \u003e Instances**.\n*   **Create New Instance:** Click the \"Create Instance\" button.\n*   **Instance Details:**\n    *   **Name:** Provide a memorable name (e.g., `ai-content-factory`).\n    *   **Image:** Click \"Change image.\"\n        *   Select **\"Oracle Cloud Marketplace.\"**\n        *   Search for `ubuntu-22-04-arm`.\n        *   Choose the pre-configured image: `https://cloudmarketplace.oracle.com/marketplace/en_US/listing/165367725`.\n        *   Click \"Select Image.\"\n    *   **Shape:** Click \"Change shape.\"\n        *   Select the **\"Ampere ARM\"** processor.\n        *   Choose the **\"VM.Standard.A1.Flex\"** shape.\n        *   Configure the shape to **4 OCPUs** and **24 GB of Memory**. These resources are part of the OCI Always Free tier.\n    *   **SSH Key:**\n        *   Set up your **SSH Key** (needed to connect to your instance).\n        *   If you don't have one, OCI can generate it for you.\n    *   **Networking:**\n        *   Configure your **networking details**. The default Virtual Cloud Network (VCN) is usually sufficient for initial setup.\n*   **Create Instance:** Click the \"Create\" button.\n*   **Connect:** Allow a few minutes for provisioning. Once the instance is running, connect to it using an SSH client and your generated SSH key.\n\n# Step 2 - Firewall Setup for Your OCI AI Content Engine\n\nThis guide provides simple steps to open the necessary ports for your AI Content Factory on Oracle OCI. You'll configure two layers of firewall rules:\n\n1.  **Oracle OCI Console:** Your cloud-level firewall (Network Security Group or Security List).\n2.  **Your Server's Firewall:** The internal firewall on your server (UFW for Ubuntu).\n\n### **Overview: Ports to Open**\n\nYou only need to open two main ports externally to the internet:\n\n*   **Port 80 (HTTP):** Used by Traefik for automatic SSL certificate generation (Let's Encrypt) and for redirecting traffic to HTTPS.\n*   **Port 443 (HTTPS):** Used by Traefik for all secure web traffic to n8n, OpenWebUI, and Crawl4AI.\n\n**Important:** All other component-specific ports (e.g., 8080 for Llama.cpp, 5678 for n8n) are handled *internally* by Docker and Traefik. **Do not open these directly to the internet.**\n\n### **1: Open Ports in Oracle OCI Console**\n\nThis involves adding Ingress (incoming) rules to your Virtual Cloud Network's Security List or Network Security Group.\n\n1.  **Log in** to your Oracle OCI Console.\n2.  **Navigate:** Go to **Networking \u003e Virtual Cloud Networks**.\n3.  **Select your VCN:** Click on the Virtual Cloud Network associated with your AI Content Factory instance.\n4.  **Access Security Rules:**\n    *   If your instance uses the **Default Security List**, click on it.\n    *   If you assigned your instance to a custom **Network Security Group (NSG)**, go to **Networking \u003e Network Security Groups** and select your NSG.\n5.  **Add Ingress Rules:** Click \"Add Ingress Rules.\"\n\n    *   **Rule 1 (for Port 80):**\n        *   **Source Type:** `CIDR`\n        *   **Source CIDR:** `0.0.0.0/0` (Allows traffic from any IP)\n        *   **IP Protocol:** `TCP`\n        *   **Destination Port Range:** `80`\n        *   **Description (Optional):** `Allow HTTP for Traefik SSL setup`\n\n    *   **Rule 2 (for Port 443):**\n        *   **Source Type:** `CIDR`\n        *   **Source CIDR:** `0.0.0.0/0` (Allows traffic from any IP)\n        *   **IP Protocol:** `TCP`\n        *   **Destination Port Range:** `443`\n        *   **Description (Optional):** `Allow HTTPS for Traefik`\n\n    *   Click \"Add Ingress Rules\" to save your changes.\n\n### **2: Open Ports on Your Server's Firewall (UFW)**\n\nConnect to your OCI instance via SSH to configure UFW (Uncomplicated Firewall).\n\n1.  **SSH into your OCI instance:**\n    ```bash\n    ssh -i /path/to/your/ssh/key ubuntu@\u003cYOUR_OCI_INSTANCE_PUBLIC_IP\u003e\n    ```\n2.  **Enable UFW (if not already enabled):**\n    ```bash\n    sudo ufw enable\n    ```\n    *   If prompted about SSH connections, type `y` and press Enter.\n3.  **Allow SSH (Port 22):** (Essential to maintain your connection)\n    ```bash\n    sudo ufw allow ssh\n    ```\n    *(Alternatively: `sudo ufw allow 22`)*\n4.  **Allow HTTP (Port 80):**\n    ```bash\n    sudo ufw allow http\n    ```\n    *(Alternatively: `sudo ufw allow 80`)*\n5.  **Allow HTTPS (Port 443):**\n    ```bash\n    sudo ufw allow https\n    ```\n    *(Alternatively: `sudo ufw allow 443`)*\n6.  **Verify UFW status:**\n    ```bash\n    sudo ufw status\n    ```\n    Confirm that `80/tcp` and `443/tcp` (and `22/tcp` or `ssh`) are listed as `ALLOW Anywhere`.\n    \n---\n---\n# Start Your AI Brain (Ampere Llama.cpp Container) 🧠\n\nThis container runs your AI models. It's the core component for generating AI content.\n\n*   **Start the server:** (--privileged=true optional!)\n    ```bash\n    sudo docker run --privileged=true --name llama --entrypoint /bin/bash -it amperecomputingai/llama.cpp:latest\n    ```\n\n*   **Download AI models (if needed):**\n    ```bash\n    #deepseek-r1-0528-qwen-3-8b\n    huggingface-cli download AmpereComputing/deepseek-r1-0528-qwen-3-8b-gguf deepseek-r1-0528-qwen-3-8b-Q8R16.gguf --local-dir /models \u0026\u0026 ./llama-cli -m /models/deepseek-r1-0528-qwen-3-8b-Q8R16.gguf -t 3 -tb 3\n    \n    #qwen-3-1.7b\n    huggingface-cli download AmpereComputing/qwen-3-1.7b-gguf Qwen3-1.7B-Q8R16.gguf --local-dir /models \u0026\u0026 ./llama-cli -m /models/qwen-3-1.7b-gguf -t 3 -tb 3\n    \n    #qwen-3-4b\n    huggingface-cli download AmpereComputing/qwen-3-4b-gguf Qwen3-4B-Q8R16.gguf --local-dir /models \u0026\u0026 ./llama-cli -m /models/qwen-3-4b-gguf -t 3 -tb 3 \n\n    #DeepSeek-R1-0528-Qwen3-8B\n    huggingface-cli download unsloth/DeepSeek-R1-0528-Qwen3-8B-GGUF DeepSeek-R1-0528-Qwen3-8B-Q4_K_M.gguf --local-dir /models \u0026\u0026 ./llama-cli -m /models/DeepSeek-R1-0528-Qwen3-8B-Q4_K_M.gguf -t 3 -tb 3\n\n    #gemma-3-4b-it-qat\n    huggingface-cli download unsloth/gemma-3-4b-it-qat-GGUF gemma-3-4b-it-qat-Q4_K_M.gguf --local-dir /models \u0026\u0026 ./llama-cli -m /models/gemma-3-4b-it-qat-Q4_K_M.gguf -t 3 -tb 3\n    \n    ```\n\n*   **Load Qwen3-4B-Q8R16 model for use via llama-server:**\n    ```bash\n    #Qwen3-4B-Q8R16\n    ./llama-server -m /models/Qwen3-4B-Q8R16.gguf -c 32768 --jinja -t 3 -tb 3 --host 0.0.0.0 --port 8080\n    ```\n    use --jinja for Qwen family models\n\n * **Once you've tested inference and all is working, get out of the CLI via:**\n    ```bash\n    control + c\n    ```\n\n*   **Keep container running:** To exit the CLI without stopping the container, press `CTRL + P`, then `CTRL + Q`.\n\n  \n---\n# Step 2: Bring the Whole Crew Online with Docker Compose 🚀\n\nThis step launches all the other components of your AI content factory, orchestrating them with Docker Compose. Ensure the `docker-compose.yml` file below is accurately saved on your OCI instance (e.g., in `/home/ubuntu/ai/` as mentioned in the Traefik volume mount, or adjust path if needed).\n\n*   **First, for Traefik and SSL configuration**, create a configuration file called `traefik_dynamic.yml` with the following content to protect your services from abuse (configure according to your requirements):\n      ```yaml\n    tls:\n      stores:\n        default:\n    #      defaultCertificate:\n    #        certFile: /etc/traefik/certs/default.crt\n    #        keyFile: /etc/traefik/certs/default.key\n      options:\n        default:\n          minVersion: VersionTLS12\n          cipherSuites:\n            - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n            - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n          curvePreferences:\n            - CurveP256\n            - CurveP384\n    #      sniStrict: true\n\n    http:\n      middlewares:\n        rate-limit:\n          rateLimit:\n            average: 100\n            burst: 50\n    ```\n\n\n\n*   **Ensure `docker-compose.yml` is ready, then launch it:**\n    ```bash\n    docker compose up -d\n    ```\n    This command brings up your PostgreSQL database (for storing data), n8n (workflow automation), OpenWebUI (AI interface), Traefik (traffic controller), Redis (fast caching), and Crawl4AI (web-scraping), all in the background.\n\n*   **Your `docker-compose.yml` blueprint:**\n\n    ```yaml\n\n      version: '3.8'\n      \n      services:\n      langfuse:\n    image: langfuse/langfuse:latest\n    container_name: langfuse\n    restart: always\n    environment:\n      DATABASE_URL: postgres://n8n_user:n8n_pass@postgres_local:5432/langfuse_db\n      NEXTAUTH_SECRET: supersecretkey   # replace with a real random secret\n      NEXTAUTH_URL: http://localhost:3000\n    ports:\n      - \"3000:3000\"\n    volumes:\n      - langfuse_data:/app/.langfuse\n    depends_on:\n      - postgres_local\n    networks:\n      internal:\n        ipv4_address: 172.18.0.11\n    \n        # PostgreSQL Database (Local) with pgvector\n        postgres:\n          image: ankane/pgvector:latest\n          container_name: postgres_local\n          ports:\n            - \"5432:5432\" \n         environment:\n            POSTGRES_USER: n8n_user\n            POSTGRES_PASSWORD: UPDATE-ME\n            POSTGRES_DB: n8n_db\n          volumes:\n            - postgres_data:/var/lib/postgresql/data\n          networks:\n            internal:\n              ipv4_address: 172.18.0.5\n          labels:\n            - \"traefik.enable=false\"\n          deploy:\n            resources:\n              limits:\n                cpus: '0.5'\n                memory: 512m\n          restart: unless-stopped\n      \n        # n8n Workflow Automation (Configured for Local Postgres \u0026 Redis)\n        n8n:\n          image: n8nio/n8n:latest\n          container_name: n8n\n          environment:\n            # --- Local PostgreSQL Connection ---\n            - DB_TYPE=postgresdb\n            - DB_POSTGRESDB_HOST=postgres\n            - DB_POSTGRESDB_PORT=5432\n            - DB_POSTGRESDB_DATABASE=n8n_db\n            - DB_POSTGRESDB_USER=n8n_user\n            - DB_POSTGRESDB_PASSWORD=UPDATE-ME\n            - DB_POSTGRESDB_SSL=false\n      \n            # --- Redis Connection ---\n            - EXECUTIONS_MODE=regular\n            - CACHE_MODE=redis\n            - CACHE_REDIS_HOST=redis\n            - CACHE_REDIS_PORT=6379\n            # - CACHE_REDIS_PASSWORD=your_redis_password # Uncomment if Redis has a password\n            - CACHE_REDIS_DB=0 # Explicitly setting n8n to use DB 0\n      \n            # --- n8n Specific Configuration ---\n            #- N8N_ENCRYPTION_KEY=UPDATE-ME\n            - N8N_HOST=n8n.rapigent.com\n            - N8N_PORT=5678\n            - N8N_PROTOCOL=https\n            - N8N_EDITOR_BASE_URL=https://n8n.rapigent.com\n            - WEBHOOK_URL=https://n8n.rapigent.com\n            - N8N_LOG_LEVEL=info\n            - N8N_COMMUNITY_PACKAGES_ENABLED=true\n            - NODE_FUNCTION_ALLOW_EXTERNAL=* # Be cautious. List specific modules if possible.\n            - N8N_PUSH_BACKEND=websocket\n            - N8N_DIAGNOSTICS_ENABLED=false\n            - N8N_TEMPLATES_ENABLED=false\n            - GENERIC_TIMEZONE=America/Denver # Set to your timezone\n          volumes:\n            - n8n_data:/home/node/.n8n\n          labels:\n            - \"traefik.enable=true\"\n            - \"traefik.http.routers.n8n.rule=Host(`n8n.rapigent.com`)\"\n            - \"traefik.http.routers.n8n.entrypoints=websecure\"\n            - \"traefik.http.routers.n8n.tls=true\"\n            - \"traefik.http.routers.n8n.tls.certresolver=myresolver\"\n            - \"traefik.http.routers.n8n.tls.options=default\"\n            - \"traefik.http.services.n8n.loadbalancer.server.port=5678\"\n          networks:\n            internal:\n              ipv4_address: 172.18.0.6\n          depends_on:\n            postgres:\n              condition: service_started\n            redis:\n              condition: service_started\n          deploy:\n            resources:\n              limits:\n                cpus: '0.5'\n                memory: 5g\n          restart: unless-stopped\n      \n        # OpenWebUI AI Interface\n        openwebui:\n          image: ghcr.io/open-webui/open-webui:main\n          container_name: openwebui\n          environment:\n            # Connects to llama.cpp on host port 8080\n            - OPENAI_API_BASE_URLS=http://0.0.0.0:8080/v1\n            - WEBUI_URL=https://openwebui.rapigent.com \n            - DATA_DIR=/app/backend/data\n            - NO_PROXY=0.0.0.0,localhost,127.0.0.1,host.docker.internal\n            - UV_SYSTEM_PYTHON=true\n            - WEBUI_NAME=PantaleoneAI\n            # --- PostgreSQL Connection for pgvector ---\n            - PGVECTOR_URL=postgresql://UPDATE-ME\n      \n            # --- Redis Connection for OpenWebUI ---\n            - REDIS_HOST=redis\n            - REDIS_PORT=6379\n            # - REDIS_PASSWORD=your_redis_password # Uncomment and set if your Redis has a password\n            - REDIS_DB=1 # Using DB 1 for OpenWebUI\n          volumes:\n            - openwebui_data:/app/backend/data\n          labels:\n            - \"traefik.enable=true\"\n            - \"traefik.http.routers.openwebui.rule=Host(`openwebui.rapigent.com`)\"\n            - \"traefik.http.routers.openwebui.entrypoints=websecure\"\n            - \"traefik.http.routers.openwebui.tls=true\"\n            - \"traefik.http.routers.openwebui.tls.certresolver=myresolver\"\n            - \"traefik.http.routers.openwebui.tls.options=default\"\n            - \"traefik.http.services.openwebui.loadbalancer.server.port=8080\"\n          networks:\n            internal:\n              ipv4_address: 172.18.0.7\n          depends_on:\n            - redis # Wait for redis container to be started\n          deploy:\n            resources:\n              limits:\n                cpus: '0.5'\n                memory: 2g\n          extra_hosts:\n            - \"host.docker.internal:host-gateway\"\n          restart: unless-stopped\n      \n        # Traefik Reverse Proxy (Configuration as provided by user initially)\n        traefik:\n          image: traefik:v2.11\n          container_name: traefik\n          command:\n            - --providers.docker=true\n            - --providers.docker.exposedbydefault=false\n            - --entrypoints.web.address=:80\n            - --entrypoints.websecure.address=:443\n            - --certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web\n            - --certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory\n            - --certificatesresolvers.myresolver.acme.email=UPDATE-ME\n            - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json\n            - --log.level=INFO\n            - --providers.file.filename=/etc/traefik/traefik_dynamic.yml # If you use a dynamic config file\n            # Optional: Traefik Dashboard\n            # - --api.dashboard=true\n            # - --api.insecure=true # For local testing of dashboard only, DO NOT use in production\n          ports:\n            - \"80:80\"\n            - \"443:443\"\n          volumes:\n            - /var/run/docker.sock:/var/run/docker.sock:ro\n            - ./acme.json:/letsencrypt/acme.json\n            - /home/ubuntu/ai/traefik_dynamic.yml:/etc/traefik/traefik_dynamic.yml:ro # Mount your dynamic config\n          networks:\n            internal:\n              ipv4_address: 172.18.0.2\n          labels:\n            - \"traefik.enable=true\"\n            - \"traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)\"\n            - \"traefik.http.routers.http-catchall.entrypoints=web\"\n            - \"traefik.http.routers.http-catchall.middlewares=redirect-to-https@docker\"\n            - \"traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https\"\n            - \"traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true\"\n            # Labels for secure Traefik Dashboard (if enabled in command and DNS is set for traefik.rapigent.com)\n            # - \"traefik.http.routers.traefik-dashboard.rule=Host(`traefik.rapigent.com`)\"\n            # - \"traefik.http.routers.traefik-dashboard.entrypoints=websecure\"\n            # - \"traefik.http.routers.traefik-dashboard.tls=true\"\n            # - \"traefik.http.routers.traefik-dashboard.tls.certresolver=myresolver\"\n            # - \"traefik.http.routers.traefik-dashboard.service=api@internal\"\n            # - \"traefik.http.middlewares.my-auth.basicauth.users=YOUR_USER:YOUR_HASHED_PASSWORD\" # Example: admin:$$apr1$$...\n            # - \"traefik.http.routers.traefik-dashboard.middlewares=my-auth\"\n          deploy:\n            resources:\n              limits:\n                cpus: '0.25' # Using previously agreed optimization\n                memory: 256m # Using previously agreed optimization\n          restart: unless-stopped\n      \n        # Redis Caching\n        redis:\n          image: redis:latest\n          container_name: redis\n          # command: [\"redis-server\", \"--requirepass\", \"your_strong_redis_password\"] # Uncomment to set password\n          volumes:\n            - redis_data:/data\n          networks:\n            internal:\n              ipv4_address: 172.18.0.3\n          labels:\n            - \"traefik.enable=false\"\n          deploy:\n            resources:\n              limits:\n                cpus: ‘0.25’\n                memory: 256m\n          restart: unless-stopped\n      \n        # Crawl4AI Web Scraping\n      #  crawl4ai:\n      #   image: unclecode/crawl4ai:latest\n      #    container_name: crawl4ai\n      #    environment:\n      #      - PLAYWRIGHT_BROWSERS_PATH=/ms-playwright\n            # FastAPI in crawl4ai image listens on 0.0.0.0:8000 by default\n      #    volumes:\n      #      - crawl4ai_data:/app/data\n      #      - /dev/shm:/dev/shm # Important for Playwright/Chrome stability\n      #    labels:\n      #      - \"traefik.enable=true\"\n      #      - \"traefik.http.routers.crawl4ai.rule=Host(`crawl4ai.rapigent.com`)\"\n      #      - \"traefik.http.routers.crawl4ai.entrypoints=websecure\"\n      #      - \"traefik.http.routers.crawl4ai.tls=true\"\n      #      - \"traefik.http.routers.crawl4ai.tls.certresolver=myresolver\"\n      #      - \"traefik.http.services.crawl4ai.loadbalancer.server.port=8000\" # crawl4ai listens on port 8000\n      #    networks:\n      #      internal:\n      #        ipv4_address: 172.18.0.4\n      #    deploy:\n      #      resources:\n      #        limits:\n      #          cpus: '0.5'\n      #          memory: 3g # Monitor this, Playwright can be memory hungry\n      #    restart: unless-stopped\n      \n      networks:\n        internal:\n          driver: bridge\n          ipam:\n            config:\n              - subnet: 172.18.0.0/16\n      \n      volumes:\n        postgres_data:\n        n8n_data:\n        openwebui_data:\n        redis_data:\n        letsencrypt:\n        crawl4ai_data:\n        langfuse_data:\n   \n    ```\n    *   **Remember to replace `email` with *your* actual email address in the `traefik` service configuration for SSL certificate issuance!**\n \n    *   **Finally, makle sure all containers on the same network and add the llama container to the network ai_internal:**\n         ```bash\n             docker network connect --ip 172.18.0.8 ai_internal llama\n         ```\n\n    *   **For your PGVector Database, connect to it, then enable the PG Vector extension**\n         ```bash\n             docker exec -it postgres_local psql -U n8n_user -d n8n_db\n         ```\n         \n         ```sql\n            CREATE EXTENSION vector;\n         ```\n \n# Updating \u0026 Upgrading\n\n*   **Remove containers via docker compose**\n    ```bash\n    docker compose down\n    ```\n\n    **Remove llama.cpp**\n    ```bash\n    docker stop my_container or docker stop \"1a2b3c4d5e6f\"\n    ```\n\n    **Remove the llama.cpp volume**\n    ```bash\n    docker rm \"1a2b3c4d5e6f\"\n    ```\n\n    **Download the latest docker image (if needed)**\n    ```bash\n    sudo docker pull amperecomputingai/llama.cpp:latest\n    ```\n    I often need to go back to the llama container command line to optimize of download new models.\n    \n    **Use this command to get back into the shell environment.  Then use the huggingface-cli to download new models per the instructions above**\n    ```bash\n     docker exec -it llama sh\n    ```\n\n# Other helpful commands\n\n*   **Check server CPU and process utilization**\n    ```bash\n    top\n    ```\n*   **Check server RAM utilization**\n    ```bash\n    free -h\n    ```\n\n*   **Docker images not connected, then remove em!**\n    ```bash\n    docker images -f dangling=true\n\n    docker image prune\n    ```\n\n*   **Similarly, kill Docker volumes not connected, then remove em!**\n    ```bash\n    docker volume ls -f dangling=true\n\n    docker volume prune\n\n    #remove a specific volume with\n    docker volume rm \u003cvolume_name\u003e\n    ```\n    \n*   **Export all N8N credentials \u0026 copy to your servers' file system(or workflows or other settings)**\n    ```bash\n       docker exec -u node -it n8n n8n export:credentials --all --decrypted --output=/tmp/creds.json\n\n       sudo docker cp n8n:/tmp/creds.json/home/ubuntu/automate/creds.json\n\n    #then copy to your your new N8N docker file system via:\n    docker cp ./my_file.txt my_container:/app/ \n    ```\n\n\n*   **Create chat_history table for use with N8N, including vector embeddings(768)**\n```sql\nCREATE TABLE chat_history (\n    id SERIAL PRIMARY KEY, -- A unique identifier for each message\n    session_id VARCHAR(255) NOT NULL, -- To group messages belonging to the same chat session\n    sender VARCHAR(255), -- The sender of the message\n    content TEXT NOT NULL, -- The message content\n    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the message was created\n    embedding VECTOR(768) -- A vector column to store embeddings (adjust dimension as needed, e.g., 1024 or 512)\n);\n\n-- Optional: Create an index on the embedding column for efficient vector search\nCREATE INDEX ON chat_history USING hnsw (embedding vector_cosine_ops); -- Using HNSW index for cosine distance\n```\n    \n---\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpantaleone-ai%2Fselfhosted-ai-workflow-content-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpantaleone-ai%2Fselfhosted-ai-workflow-content-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpantaleone-ai%2Fselfhosted-ai-workflow-content-engine/lists"}