An automated AI-powered sales assistant for smart home installation services, built with n8n, Telegram, and GPT. This bot handles customer inquiries, guides them through the sales funnel, and schedules appointments.
- Telegram bot integration for customer communication
- AI-powered sales conversations using GPT-4
- Automated lead qualification and data collection
- Calendar integration for appointment scheduling
- PostgreSQL database for conversation memory and persistent storage
- Google Sheets integration for lead management
- Google Calendar integration for installation appointments
- Smart home-specific sales script and objection handling
- Docker and Docker Compose installed
- ngrok account (for webhook URL)
- Telegram Bot Token
- OpenAI API key (GPT-4 access)
- Google OAuth credentials (for Sheets/Calendar integration)
- Basic understanding of n8n workflows
.
βββ docker-compose.yml # Docker services configuration
βββ .env # Environment variables (DO NOT COMMIT)
βββ .gitignore # Git ignore file
βββ smart_home_assistant.json # n8n workflow export (smart home setup)
βββ start.sh # One-command script to start everything
βββ stop.sh # One-command script to stop everything
βββ README.md # This file
Before starting the containers, you need to obtain several API keys and credentials. Follow these steps:
n8n needs a public URL for webhooks (Telegram, OAuth callbacks).
# Install ngrok (if not installed)
# Download from https://ngrok.com/download
# Start ngrok tunnel
ngrok http 5678Copy the HTTPS URL (e.g., https://abc123.ngrok-free.app) - you'll need this for .env
Note: Free ngrok URLs change every time you restart. For production, use:
- ngrok paid plan (persistent domain)
- Your own domain with reverse proxy
- Cloud hosting (AWS, DigitalOcean, etc.)
- Open Telegram and search for @BotFather
- Send
/newbot - Choose a name:
Smart Home Assistant - Choose a username:
your_smarthome_bot(must end with 'bot') - Copy the Bot Token (looks like:
123456789:ABCdefGHIjklMNOpqrsTUVwxyz) - Save this token - you'll add it in n8n later
- Go to OpenAI API Keys
- Sign in or create an account
- Click "Create new secret key"
- Name it:
n8n-smart-home-bot - Copy the key (starts with
sk-...) - Important: Add credits to your OpenAI account (GPT-4 requires paid account)
- Save this key - you'll add it in n8n later
Pricing: GPT-4 costs vary. Check OpenAI Pricing
- Go to Google Cloud Console
- Click "Create Project"
- Name:
n8n-smart-home-bot - Click "Create"
- In your project, go to "APIs & Services" > "Library"
- Search and enable:
- Google Sheets API
- Google Calendar API
- Go to "APIs & Services" > "Credentials"
- Click "Configure Consent Screen":
- User Type: External
- App name:
Smart Home Bot - User support email: your email
- Developer contact: your email
- Click "Save and Continue"
- Scopes: Click "Add or Remove Scopes", search and add:
Google Sheets APIβ.../auth/spreadsheetsGoogle Calendar APIβ.../auth/calendar- Click "Update" then "Save and Continue"
- Test users: Add your Gmail address, click "Save and Continue"
- Go to "Credentials" tab
- Click "Create Credentials" > "OAuth 2.0 Client ID"
- Application type: Web application
- Name:
n8n-oauth - Authorized redirect URIs: Add your ngrok URL + callback path:
Example:
https://YOUR-NGROK-URL.ngrok-free.app/rest/oauth2-credential/callbackhttps://abc123.ngrok-free.app/rest/oauth2-credential/callback - Click "Create"
- Save the Client ID and Client Secret - you'll need these in n8n
Create two Google Sheets for your bot:
- Go to Google Sheets
- Create new sheet, name it:
Smart Home Products - Add headers and sample data:
| Product | Price | Description | |------------------|--------|---------------------------------------| | Basic Package | $999 | Smart lights + voice control | | Security Package | $1,499 | Cameras + smart locks + sensors | | Full Home | $3,999 | Complete automation for entire home | - Share the sheet with your Google account email
- Copy the Sheet ID from URL:
https://docs.google.com/spreadsheets/d/SHEET_ID_HERE/edit
- Create another sheet, name it:
Smart Home Leads - Add headers:
| name | phone | email | description | - Copy the Sheet ID from URL
- Go to Google Calendar
- Create a new calendar:
- Click "+" next to "Other calendars"
- "Create new calendar"
- Name:
Smart Home Installations - Click "Create calendar"
- Note your calendar email (usually your Gmail address)
We've created automated scripts to simplify startup and shutdown:
./start.shThis single command will:
- β Start Docker containers (n8n + PostgreSQL)
- β Launch ngrok tunnel for port 5678
- β Wait for ngrok to initialize
- β Extract the public ngrok URL
- β
Automatically update
.envfile with the new ngrok URL - β
Update OAuth redirect URI in
.env - β Display webhook registration instructions
Output example:
β
Project started successfully!
π ngrok URL: https://f23bcce90eba.ngrok-free.app (updated in .env)
π Access n8n at:
Local: http://localhost:5678
Public: https://f23bcce90eba.ngrok-free.app
β οΈ IMPORTANT FOR TELEGRAM BOT:
If you've restarted ngrok, you MUST register the webhook again:
curl -X POST "https://api.telegram.org/botYOUR_BOT_TOKEN/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://f23bcce90eba.ngrok-free.app/webhook/telegram"}'
- Free ngrok URLs change every time you restart
- Each time you run
./start.sh, you get a NEW URL - You must register the new webhook with Telegram after each restart
- The script displays the webhook registration command for you to copy-paste
./stop.shThis command will:
- β Pause all Docker containers (data is preserved)
- β Stop ngrok tunnel
- β Show instructions for restart
Note: Containers are stopped but not removed. All data (n8n workflows, PostgreSQL database) is preserved. Simply run ./start.sh again to resume.
The workflow is automatically imported on first container start using n8n's CLI!
How it works:
- Run
./start.shβ containers start - After n8n is ready, the workflow is imported via n8n CLI
- If workflow already exists (from previous session), it's skipped
- Open http://localhost:5678 β workflow is there with all your data intact!
Key features:
- β Automatic on first start (no manual import needed)
- β Idempotent (safe to restart, won't duplicate or overwrite)
- β Preserves all previous data (credentials, executions, history)
- β
Can force reimport with
./start.sh --reimport(overwrites existing) - β Data persists across stop/start cycles
Workflow restart behavior:
| Command | Container | Data | Workflow |
|---|---|---|---|
./stop.sh |
Stopped | β Preserved | β Preserved |
./start.sh (after stop) |
Restarted | β Intact | β Still there |
docker compose down |
Removed | β Deleted | β Deleted |
| ./stop.sh | Stopped | β
Preserved | β
Preserved |
| ./start.sh (after stop) | Restarted | β
Intact | β
Still there |
| docker compose down | Removed | β Deleted | β Deleted |
Manual reimport (if needed):
# Force reimport workflow on next start
./start.sh --reimport
# Or reimport via n8n UI:
# 1. Click Menu (β°) β Workflows β Import
# 2. Select smart_home_assistant.json
# 3. Click ImportOutput example:
β
Project stopped! All containers and ngrok tunnel shut down.
Before using start.sh, ensure:
- β Docker and Docker Compose are installed
- β
ngrok is installed and accessible in your PATH
- Download: https://ngrok.com/download
- After installation, verify with:
ngrok version
If you prefer manual control, use Docker Compose directly:
Edit the .env file with your credentials:
# n8n Authentication
N8N_USER=admin
N8N_PASS=adminpass
# Public URL (ngrok or your domain)
NGROK_URL=https://your-ngrok-url.ngrok-free.app
# PostgreSQL Database
PG_USER=pguser
PG_PASS=pgpass
PG_DB=memorydb
# OAuth Redirect (for Google integrations)
oauth_redirect_uri=https://your-ngrok-url.ngrok-free.app/rest/oauth2-credential/callback# Start all services
docker compose up -d
# View logs
# View logs
docker-compose logs -f
# Check running containers
docker-compose psOpen your browser and navigate to:
- Local Access:
http://localhost:5678(Port: 5678) - Public Access: Your ngrok URL (e.g.,
https://f23bcce90eba.ngrok-free.app)
Login with credentials from .env:
- Username:
admin(or your N8N_USER) - Password:
adminpass(or your N8N_PASS)
- In n8n, click on "Workflows" in the left sidebar
- Click "Add workflow" > "Import from file"
- Select
smart_home_assistant.json - The workflow will open with "smart home setup assistant" name
You need to set up 5 different credentials in the workflow. Click on each node that shows a credential error (red exclamation mark).
- Click on "Telegram Trigger" node
- Under "Credential to connect with", click "Create New"
- Name:
Smart Home Bot - Access Token: Paste your Telegram Bot Token from BotFather
- Click "Save"
- Do the same for "Send a text message" node (or select the same credential)
- Click on "OpenAI Chat Model" node
- Under "Credential to connect with", click "Create New"
- Name:
OpenAI GPT-4 - API Key: Paste your OpenAI API key (starts with
sk-...) - Click "Save"
- Click on "Postgres Chat Memory" node
- Under "Credential to connect with", click "Create New"
- Fill in the database connection details:
- Host:
postgres_memory(this is the Docker service name) - Database:
memorydb(or your PG_DB value) - User:
pguser(or your PG_USER value) - Password:
pgpass(or your PG_PASS value) - Port:
5432(internal Docker port, NOT 5444) - SSL:
disable(for local development)
- Host:
- Name:
Postgres Memory DB - Click "Save"
- Click on "Get row(s) in sheet in Google Sheets" node
- Under "Credential to connect with", click "Create New"
- You'll see OAuth setup:
- OAuth Redirect URL: Copy this URL (should match what you set in Google Cloud Console)
- Client ID: Paste from Google Cloud Console
- Client Secret: Paste from Google Cloud Console
- Name:
Google Sheets Account - Click "Sign in with Google"
- Authorize the app (you may see "unverified app" warning - click "Advanced" > "Go to app")
- Grant permissions for Google Sheets and Calendar
- Click "Save"
- Repeat for "Append row in sheet in Google Sheets" node (select the same credential)
- Click on "Get an event in Google Calendar" node
- Under "Credential to connect with", click "Create New" OR select the same Google OAuth credential from Sheets
- If creating new:
- Client ID: Same as Google Sheets
- Client Secret: Same as Google Sheets
- Click "Sign in with Google"
- Authorize
- Name:
Google Calendar Account - Click "Save"
- Repeat for "Create an event in Google Calendar" node (select the same credential)
Note: Google Sheets and Google Calendar can use the SAME OAuth credential if you enabled both APIs in the same Google Cloud project.
-
Click on "Get row(s) in sheet in Google Sheets" node
-
Click on "Document" dropdown
-
Click "From list" (it should fetch your Google Sheets)
-
Select "Smart Home Products" (your price list sheet)
-
Select the sheet tab (usually "Sheet1")
-
Click "Save"
-
Click on "Append row in sheet in Google Sheets" node
-
Select "Smart Home Leads" (your client database)
-
Click "Save"
-
Click on "Get an event in Google Calendar" node
-
Under "Calendar", select your email or calendar name
-
Click "Save"
-
Click on "Create an event in Google Calendar" node
-
Under "Calendar", select the same calendar
-
Click "Save"
- Click "Save" button (top right)
- Toggle the workflow to "Active" (switch in top right turns green)
- The Telegram webhook should now be registered
- Open Telegram
- Search for your bot username
- Send
/startor any message - The bot should respond with the smart home sales pitch!
If bot doesn't respond:
- Check n8n "Executions" tab for errors
- Verify ngrok is still running
- Check all credentials are properly configured
- Look at Docker logs:
docker-compose logs -f n8n
# Start everything with one command
./start.sh
# Stop everything with one command
./stop.sh# Stop services (containers keep running)
docker compose stop
# Restart services
docker compose restart
# Stop and remove containers
docker compose down
# Stop and remove everything (including volumes)
docker compose down -v
# View logs
docker-compose logs -f
# View logs for specific service
docker-compose logs -f n8n
docker-compose logs -f postgres_memory
# Rebuild containers
docker compose up -d --build- Click "Save" button (top right)
- Toggle the workflow to "Active" (switch in top right turns green)
- The Telegram webhook should now be registered
- Open Telegram
- Search for your bot username
- Send
/startor any message - The bot should respond with the smart home sales pitch!
If bot doesn't respond:
- Check n8n "Executions" tab for errors
- Verify ngrok is still running
- Check all credentials are properly configured
- Look at Docker logs:
docker-compose logs -f n8n
docker-compose stopdocker-compose restartdocker-compose downdocker-compose down -v# All services
docker-compose logs -f
# Specific service
docker-compose logs -f n8n
docker-compose logs -f postgres_memorydocker-compose up -d --buildPostgreSQL is accessible on port 5444:
# Connect to PostgreSQL
# First, get your container name:
CONTAINER=$(docker ps --filter "ancestor=postgres:15" --format "{{.Names}}")
docker exec -it $CONTAINER psql -U pguser -d memorydb
# Or use external client (from your machine)
psql -h localhost -p 5444 -U pguser -d memorydb# Backup workflow data
docker-compose exec n8n n8n export:workflow --all --output=/home/node/.n8n/workflows_backup.json
# Copy from container (get container name dynamically)
CONTAINER=$(docker ps --filter "ancestor=n8nio/n8n:latest" --format "{{.Names}}")
mkdir -p backup
docker cp $CONTAINER:/home/node/.n8n/workflows_backup.json ./backup/docker-compose exec postgres_memory pg_dump -U pguser memorydb > backup_$(date +%Y%m%d).sqlcat backup.sql | docker-compose exec -T postgres_memory psql -U pguser -d memorydbThis happens when the Telegram webhook is not properly registered with Telegram servers. Follow these steps:
# Check if ngrok process is running
pgrep -a ngrok
# Should show: ngrok http 5678If ngrok is NOT running, restart with:
./stop.sh && ./start.sh# Check your current .env file
cat .env | grep NGROK_URL
# Should show something like: NGROK_URL=https://abc123.ngrok-free.appImportant: ngrok URLs change every time you restart ngrok. If you restarted ngrok, the old URL is dead. You MUST run ./start.sh again to update .env with the new URL.
Open your browser and paste this URL (replace with YOUR values):
https://api.telegram.org/botYOUR_BOT_TOKEN/getWebhookInfo
Example:
https://api.telegram.org/bot123456789:ABCdefGHIjklMNOpqrsTUVwxyz/getWebhookInfo
Expected successful response:
{
"ok": true,
"result": {
"url": "https://YOUR-NGROK-URL.ngrok-free.app/webhook/telegram",
"has_custom_certificate": false,
"pending_update_count": 0,
"ip_address": "1.2.3.4",
"last_error_date": 0,
"max_connections": 40,
"allowed_updates": ["message", "callback_query"]
}
}If the URL is empty or different, the webhook is NOT registered. Continue to Step 4.
If webhook is not registered, manually set it:
# Replace YOUR_BOT_TOKEN and YOUR-NGROK-URL
curl -X POST "https://api.telegram.org/botYOUR_BOT_TOKEN/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://YOUR-NGROK-URL.ngrok-free.app/webhook/telegram"}'Example:
curl -X POST "https://api.telegram.org/bot123456789:ABCdefGHIjklMNOpqrsTUVwxyz/setWebhook" \
-H "Content-Type: application/json" \
-d '{"url":"https://f23bcce90eba.ngrok-free.app/webhook/telegram"}'Expected response:
{
"ok": true,
"result": true,
"description": "Webhook was set"
}- Open n8n:
http://localhost:5678 - Go to "Executions" tab
- Send a test message to your Telegram bot
- You should see an execution appear
If still no execution:
# Check n8n logs for errors
docker compose logs -f n8n
# Look for errors related to:
# - Telegram
# - Webhook
# - 404 errorsIn n8n workflow:
-
Click on "Telegram Trigger" node
-
Check that:
- β Credential is selected (not empty with red error)
- β
"On" is set to
message - β
"Resource" is set to
Message - β
"Event" is set to
started
-
Click the "Activate webhook" button if present
-
Check the "Test node" button - it should work
Sometimes n8n webhook cache gets corrupted. Do a full reset:
# Stop everything
./stop.sh
# Wait 5 seconds
sleep 5
# Remove n8n data volume (WARNING: loses all data)
# Find volume name:
docker volume ls | grep n8n_data
# Then remove it:
docker volume rm <volume_name>
# Start fresh
./start.sh
# Wait for n8n to start (~30 seconds)
sleep 30
# Re-import workflow and reconfigureCauses & Solutions:
| Problem | Solution |
|---|---|
| Workflow is not Active | Click the toggle switch in top-right to turn Active (green) |
| Telegram Trigger not configured | Configure credential and click "Save" |
| ngrok URL not updated in .env | Run ./start.sh again |
| n8n hasn't reloaded | Refresh browser (Ctrl+F5) or restart n8n: docker compose restart n8n |
| Webhook not registered with Telegram | Follow Step 4 above to manually set webhook |
Free ngrok accounts get a new URL every time you restart ngrok. Solutions:
-
Use the automated script (recommended):
./start.sh # Automatically updates .env with new URL -
Use ngrok paid plan ($5/month) for static URL:
- Get custom domain at https://dashboard.ngrok.com/
- Update
.envwith custom domain
-
Use your own domain with reverse proxy (nginx, Cloudflare, etc.)
Symptoms: Workflow missing after ./start.sh, need to manually import
Solutions:
# 1. Check n8n container logs for import errors
docker compose logs -f n8n | grep -i "import\|workflow"
# 2. Check init script logs
docker exec smart-home-assistant-n8n-1 cat /tmp/n8n-init.log
# 3. Force reimport the workflow
./start.sh --reimport
# 4. If still failing, manually import via n8n UI:
# - Click Menu (β°) β Workflows β Import
# - Select smart_home_assistant.json
# - Click ImportCommon causes:
- n8n didn't fully start before init script tried to import
- n8n API was not responding
- Workflow file not found in container (check docker-compose.yml volumes)
Symptom: Data disappears after ./stop.sh and ./start.sh
Cause: Using docker compose down instead of docker compose stop
Solution:
# CORRECT - preserves data
./stop.sh # Uses docker compose stop
# WRONG - deletes data
docker compose down # Deletes containers and volumes!
# Always use ./stop.sh for stopping
# Only use 'docker compose down' if you want to RESET everythingError message: "ECONNREFUSED 127.0.0.1:5432"
Solution:
# Verify PostgreSQL is running
docker compose logs postgres_memory
# Check connection from n8n credential setup:
# - Host: postgres_memory (NOT localhost)
# - Port: 5432 (internal Docker port, NOT 5444)
# - User: pguser
# - Password: pgpass
# - Database: memorydbError: "bind: address already in use"
Solution:
# Check what's using port 5678
lsof -i :5678
# Kill the process (if it's old n8n)
kill -9 <PID>
# Or change the port in docker-compose.ymlCommon errors:
| Error | Cause | Fix |
|---|---|---|
| "Invalid API key" | Wrong key or expired | Check OpenAI API key in n8n credentials |
| "Rate limit exceeded" | Too many requests | Wait or upgrade OpenAI account |
| "Quota exceeded" | No credits | Add credit card to OpenAI account |
| "Model not available" | Account doesn't have GPT-4 | Use gpt-3.5-turbo or upgrade account |
Error: "Invalid redirect URI"
Solution:
- Check your ngrok URL is correct in
.env - In Google Cloud Console, verify redirect URI matches exactly:
https://YOUR-NGROK-URL.ngrok-free.app/rest/oauth2-credential/callback - If ngrok URL changed, update Google Cloud Console
- Delete old credential in n8n and create new one
-
Restart everything:
./stop.sh && sleep 5 && ./start.sh
-
Check all logs:
docker compose logs -f
-
Test ngrok tunnel:
curl https://YOUR-NGROK-URL.ngrok-free.app # Should return: 404 Bad Request (this is normal) -
Test Telegram API:
curl https://api.telegram.org/botYOUR_BOT_TOKEN/getMe # Should return bot information -
Clear n8n cache (if things are stuck):
docker compose exec n8n rm -rf /home/node/.n8n/cache docker compose restart n8n
# Check logs
docker-compose logs
# Remove and recreate
docker-compose down
docker-compose up -ddocker-compose down -v
docker-compose up -dIf ports 5678 or 5444 are already in use, edit docker-compose.yml:
ports:
- "YOUR_PORT:5678" # Change YOUR_PORT- Make changes in n8n UI
- Export workflow: Workflows > ... > Download
- Replace
smart_home_assistant.json - Commit to version control
docker-compose pull
docker-compose up -d- n8n runs on port
5678 - PostgreSQL runs on port
5444(mapped from internal 5432) - Data persists in Docker volumes:
n8n_dataandpgdata - Webhooks require a public URL (ngrok or domain)
Here's a complete list of all credentials you need:
| Variable | Description | Example |
|---|---|---|
N8N_USER |
n8n admin username | admin |
N8N_PASS |
n8n admin password | your_secure_password |
NGROK_URL |
Public webhook URL | https://abc123.ngrok-free.app |
PG_USER |
PostgreSQL username | pguser |
PG_PASS |
PostgreSQL password | your_db_password |
PG_DB |
PostgreSQL database name | memorydb |
oauth_redirect_uri |
OAuth callback URL | https://abc123.ngrok-free.app/rest/oauth2-credential/callback |
| Credential Type | Where to Get | Used By Nodes |
|---|---|---|
| Telegram Bot Token | @BotFather on Telegram | Telegram Trigger, Send a text message |
| OpenAI API Key | platform.openai.com/api-keys | OpenAI Chat Model |
| PostgreSQL Connection | Self-hosted (Docker) | Postgres Chat Memory |
| Google OAuth (Client ID + Secret) | Google Cloud Console | All Google Sheets & Calendar nodes |
| Google Sheet IDs | From Google Sheets URLs | Get/Append Google Sheets nodes |
| Google Calendar Email | From Google Calendar | Get/Create Calendar Event nodes |
CRITICAL: Before publishing to GitHub:
- NEVER commit
.envfile with real credentials .envis already in.gitignore- verify this before committing- Change default passwords (
N8N_PASS,PG_PASS) to strong, unique passwords - For production:
- Use environment variable management (AWS Secrets Manager, etc.)
- Enable HTTPS with proper SSL certificates
- Restrict PostgreSQL port access (remove port mapping or use firewall)
- Use strong, randomly generated passwords (20+ characters)
- Enable 2FA on Google account used for OAuth
- Regularly rotate API keys
- Monitor OpenAI API usage to prevent unexpected costs
- Set up rate limiting on Telegram bot if needed
Workflow Export Note: The exported JSON (smart_home_assistant.json) does NOT contain credential values - only references to credential names. It's safe to share publicly.
For issues with:
- n8n: n8n Documentation
- Docker: Docker Documentation
[Your License Here]