<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Server Specs:

<aside> <img src="/icons/cloud_green.svg" alt="/icons/cloud_green.svg" width="40px" />

Install Ubuntu Server

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Updates

sudo apt update && sudo apt upgrade

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Docker Engine

sudo apt update && sudo apt upgrade -y

sudo apt install -y ca-certificates curl gnupg lsb-release

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL <https://download.docker.com/linux/ubuntu/gpg> | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  <https://download.docker.com/linux/ubuntu> \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Casa

curl -fsSL <https://get.casaos.io> | sudo bash

For IP Address:

ip a | grep "inet " | grep -v 127

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Portainer

mkdir -p ~/portainer/data

docker run -d \
  -p 8000:8000 \
  -p 9443:9443 \
  --name portainer \
  --restart=always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v ~/portainer/data:/data \
  portainer/portainer-ce:latest

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Cloudflare

# Add cloudflare gpg key
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL <https://pkg.cloudflare.com/cloudflare-public-v2.gpg> | sudo tee /usr/share/keyrings/cloudflare-public-v2.gpg >/dev/null

# Add this repo to your apt repositories
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-public-v2.gpg] <https://pkg.cloudflare.com/cloudflared> any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list

# install cloudflared
sudo apt-get update && sudo apt-get install cloudflared
sudo cloudflared service install <enter your key>

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install n8n

mkdir -p ~/n8n/data

docker run -d \
  --name n8n \
  --restart=always \
  -p 5678:5678 \
  -v ~/n8n/data:/home/node/.n8n \
  -e GENERIC_TIMEZONE="Asia/Kolkata" \ #Change According to your Time Zone
  -e TZ="Asia/Kolkata" \  #Change According to your Time Zone
  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
  -e N8N_RUNNERS_ENABLED=true \
  -e N8N_HOST=yourdomain.com \
  -e N8N_PORT=5678 \
  -e N8N_PROTOCOL=https \
  -e NODE_ENV=production \
  -e WEBHOOK_URL=yourdomain.com \
  -e N8N_EDITOR_BASE_URL=yourdomain.com \
  -e N8N_SECURE_COOKIE=false \
  docker.n8n.io/n8nio/n8n

Updated Code:

docker run -d \
  --name n8n \
  --restart=always \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e GENERIC_TIMEZONE="Asia/Kolkata" \ #Change According to your Time Zone
  -e TZ="Asia/Kolkata" \ #Change According to your Time Zone
  -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \
  -e N8N_RUNNERS_ENABLED=true \
  -e N8N_HOST=yourdomain.com \
  -e N8N_PORT=5678 \
  -e N8N_PROTOCOL=https \
  -e NODE_ENV=production \
  -e WEBHOOK_URL=yourdomain.com \
  -e N8N_EDITOR_BASE_URL=yourdomain.com \
  -e N8N_SECURE_COOKIE=false \
  docker.n8n.io/n8nio/n8n:latest

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Qdrant VD

mkdir ~/qdrant && cd ~/qdrant
nano docker-compose.yml
version: "3.8"

services:
  qdrant:
    image: qdrant/qdrant:latest
    container_name: qdrant
    restart: unless-stopped
    ports:
      - "6333:6333"   # REST API
      - "6334:6334"   # gRPC
    volumes:
      - ./qdrant_storage:/qdrant/storage
    environment:
      - QDRANT__SERVICE__API_KEY=changeme123   # change this!
    networks:
      - ai-stack

networks:
  ai-stack:
    name: ai-stack
    driver: bridge
docker compose up -d
docker network connect ai-stack n8n

Verify:

curl -H "api-key: changeme123" <http://localhost:6333>

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Postgres Setup

mkdir -p ~/docker/postgres && cd ~/docker/postgres

nano docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    container_name: postgres
    restart: unless-stopped
    environment:
      - POSTGRES_USER=n8n
      - POSTGRES_PASSWORD=your_secure_password # <-- Change this to a real password!
      - POSTGRES_DB=n8n
    volumes:
      - ./data:/var/lib/postgresql/data
    networks:
      - ai-stack

networks:
  ai-stack:
    external: true
docker compose up -d

If Permission Error:

sudo chown -R $USER:$USER ~/docker/postgres

Details:

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Adminer

mkdir ~/docker/adminer && cd ~/docker/adminer
nano docker-compose.yml
services:
  adminer:
    image: adminer
    container_name: adminer
    restart: unless-stopped
    ports:
      - "8080:8080"
    networks:
      - ai-stack

networks:
  ai-stack:
    external: true
docker compose up -d

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Ollama

mkdir ~/docker/ollama && cd ~/docker/ollama
mkdir ~/docker/ollama/ollama_data
nano docker-compose.yml
version: "3.8"

services:
  ollama:
    image: ollama/ollama:latest
    container_name: ollama
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - ./ollama_data:/root/.ollama
    networks:
      - ai-stack

networks:
  ai-stack:
    external: true

docker compose up -d

</aside>

<aside> <img src="/icons/refresh_green.svg" alt="/icons/refresh_green.svg" width="40px" />

Install Beszel

mkdir ~/docker/beszel && cd ~/docker/beszel
nano docker-compose.yml
services:
  beszel:
    image: henrygd/beszel
    container_name: beszel
    restart: unless-stopped
    ports:
      - 8090:8090
    volumes:
      - ./data:/beszel_data
docker compose up -d

Beszel Agent:

mkdir ~/docker/beszel-agent && cd ~/docker/beszel-agent
nano docker-compose.yml
services:
  beszel-agent:
    image: henrygd/beszel-agent
    container_name: beszel-agent
    restart: unless-stopped
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./beszel_agent_data:/var/lib/beszel-agent
    environment:
      LISTEN: 45876
      KEY: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBiOl70sO+UNw6lJW4J5DmRIGuMG1kxfjRDqXUqkL7uZ'
      TOKEN: 61aa-84b0a027f-4541-35ca081188
      HUB_URL: <http://dell-inspiron:8090>
docker compose up -d

</aside>

<aside> <img src="/icons/arrows-vertical_green.svg" alt="/icons/arrows-vertical_green.svg" width="40px" />

Firecrawl

cd ~/docker
# Clone the repository
git clone <https://github.com/mendableai/firecrawl.git>
cd firecrawl

# Configure Environment
cp apps/api/.env.example .env
nano .env

Update the following in .env:

Mine API-Key - key123

# Modify Compose File for Pre-built Images and Ports
nano docker-compose.yaml

Make the following updates in docker-compose.yaml:

  1. Use Pre-built API Image: Scroll to the x-common-service: block. Comment out build: apps/api and uncomment/update the image line to: image: ghcr.io/firecrawl/firecrawl:latest
  2. Use Pre-built Playwright Image: Scroll to the playwright-service: block. Comment out build: apps/playwright-service-ts and uncomment/update the image line to: image: ghcr.io/firecrawl/playwright-service:latest
  3. Update API Port: Scroll to the api: block. Change the port configuration to "3010:3002".
# Start the Stack
docker compose up -d

Test:

# Test the Deployment (Run this in the terminal after it boots)
curl -X POST <http://localhost:3010/v2/scrape> \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer your_custom_test_api_key' \
  -d '{"url": "<https://example.com>"}'

</aside>

<aside> <img src="/icons/arrows-vertical_green.svg" alt="/icons/arrows-vertical_green.svg" width="40px" />

</aside>

<aside> <img src="/icons/arrows-vertical_green.svg" alt="/icons/arrows-vertical_green.svg" width="40px" />

</aside>