[Side-Hustle Guide] Building a Zero-Cost Automated Cash-Generating Site with n8n & DeepSeek
Stop manual posting. Learn how to use n8n and DeepSeek to create a 24/7 autonomous website that earns passive income for you.
What You’ll Build
Follow all 7 steps in this tutorial and you will have a fully autonomous content production pipeline running 24/7:
- Auto-fetching — Continuously monitor target websites for new content via RSS feeds
- AI Rewriting — Call the DeepSeek API to transform raw source material into original articles
- SEO Optimization — Automatically generate search-engine-friendly titles, meta descriptions, and tags
- One-click Publishing — Push finished articles directly to your WordPress site through the REST API
- Error Alerting — Receive instant notifications whenever any step in the pipeline fails
The entire system runs on your own server. You own the data, and monthly operating costs stay under $5.
Prerequisites
| Item | Requirement | Notes |
|---|---|---|
| Server | VPS with 1+ CPU core and 1 GB+ RAM | Ubuntu 22.04 recommended; any cloud provider works |
| Docker | v20.10 or higher | Used to deploy n8n |
| WordPress Site | Installed and accessible | REST API must be enabled (on by default) |
| DeepSeek Account | Registered | Needed for API key |
| Basic Skills | Comfortable with an SSH terminal; familiar with JSON | No programming experience required |
Estimated completion time: 90-120 minutes (including server configuration)
Architecture Overview
Here is the end-to-end automation flow:
RSS Feed (content source)
|
n8n Cron Trigger (scheduled execution)
|
RSS Feed Read Node (fetch article list)
|
HTTP Request -> DeepSeek API (AI content rewrite)
|
Function Node (SEO title / meta generation)
|
HTTP Request -> WordPress REST API (auto-publish)
|
Email / Telegram Notification (publish result alert)
n8n acts as the central orchestrator. All nodes are connected visually in the workflow editor — no backend code required.
Step 1: Install & Configure n8n (Docker Compose)
We use Docker Compose to deploy n8n for easy management and upgrades.
1.1 Create a Working Directory
mkdir -p ~/n8n-docker && cd ~/n8n-docker
1.2 Write the docker-compose.yml
version: "3.8"
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: always
ports:
- "5678:5678"
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=YourStrongPassword123
- N8N_HOST=n8n.yourdomain.com
- N8N_PROTOCOL=https
- WEBHOOK_URL=https://n8n.yourdomain.com/
- GENERIC_TIMEZONE=America/New_York
- TZ=America/New_York
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
Replace
N8N_BASIC_AUTH_PASSWORDwith your own strong password andN8N_HOSTwith your actual domain name. Adjust the timezone to match your location.
1.3 Start the Service
docker compose up -d
Verify the container is running:
docker ps --filter name=n8n
1.4 Configure a Reverse Proxy (Nginx Example)
server {
listen 443 ssl;
server_name n8n.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/n8n.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/n8n.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
}
}
After saving, reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
✅ Expected Result: Open https://n8n.yourdomain.com in your browser. After entering the username and password, you should see the n8n visual workflow editor interface.
Step 2: Get DeepSeek API Key
2.1 Register an Account
Go to the DeepSeek Open Platform and create an account.
2.2 Create an API Key
- Log in and navigate to Console -> API Keys
- Click Create API Key
- Copy the generated key. It will look like:
sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Store this key securely. You will not be able to view it again after closing the dialog.
2.3 Save the Credential in n8n
- Open the n8n interface and go to Settings -> Credentials
- Click Add Credential -> Header Auth
- Configure as follows:
| Field | Value |
|---|---|
| Name | DeepSeek API |
| Header Name | Authorization |
| Header Value | Bearer sk-YOUR_ACTUAL_KEY_HERE |
Click Save to store the credential.
✅ Expected Result: You can see a credential named “DeepSeek API” in the n8n Credentials list with a saved status.
Step 3: Create RSS Feed Workflow
3.1 Create a New Workflow
In n8n, click New Workflow and name it Auto Content Pipeline.
3.2 Add an RSS Feed Read Node
Drag an RSS Feed Read node onto the canvas and configure it:
| Parameter | Value |
|---|---|
| URL | https://techcrunch.com/feed/ |
| Output Format | JSON |
You can replace this with any RSS feed URL. To aggregate multiple sources, use a Merge node to combine them.
3.3 Add an Item Lists Node for Deduplication
Connect an Item Lists node after the RSS Read node:
| Parameter | Value |
|---|---|
| Operation | Limit |
| Max Items | 5 |
This ensures only the 5 most recent articles are processed per run, preventing duplicates and excessive API consumption.
3.4 Add a Function Node to Extract Key Fields
Connect a Function node and add the following code:
const items = $input.all();
return items.map(item => ({
json: {
title: item.json.title,
content: item.json['content:encoded'] || item.json.description || '',
link: item.json.link,
pubDate: item.json.pubDate
}
}));
This normalizes the RSS output into a clean structure with only the fields we need downstream.
✅ Expected Result: Click Execute Node. The output panel displays 5 JSON objects, each containing title, content, link, and pubDate fields.
Step 4: Configure DeepSeek AI Content Rewrite Node
This is the core of the entire system — calling the DeepSeek API to rewrite fetched content into original articles.
4.1 Add an HTTP Request Node
Drag an HTTP Request node after the Function node and configure it:
| Parameter | Value |
|---|---|
| Method | POST |
| URL | https://api.deepseek.com/chat/completions |
| Authentication | Predefined Credential -> Header Auth -> DeepSeek API |
| Send Headers | Content-Type: application/json |
4.2 Configure the Request Body
Select JSON mode and enter the following:
{
"model": "deepseek-chat",
"messages": [
{
"role": "system",
"content": "You are an experienced tech blogger. Your task is to rewrite the provided article into a fresh, original blog post that is engaging and SEO-friendly. Requirements: 1) Completely rewrite in your own words -- do not copy the original text; 2) Preserve the core technical insights and data points; 3) Use clear structure with H2/H3 headings; 4) Keep the word count between 1200-1800 words; 5) End with a concise summary paragraph."
},
{
"role": "user",
"content": "Please write an original blog post based on the following source material:\n\nTitle: {{ $json.title }}\n\nOriginal content: {{ $json.content }}"
}
],
"temperature": 0.7,
"max_tokens": 4096
}
Prompt Engineering Tips: The system prompt explicitly defines the output format, word count range, and rewriting rules. A
temperatureof 0.7 balances creativity with consistency.
4.3 Parse the Response
Connect a Function node after the HTTP Request to extract the AI-generated article:
const items = $input.all();
return items.map(item => {
const response = item.json;
const aiContent = response.choices[0].message.content;
return {
json: {
...item.json,
rewrittenContent: aiContent,
originalTitle: item.json.title
}
};
});
✅ Expected Result: After executing the node, the output contains a new rewrittenContent field with the full article rewritten by DeepSeek.
Step 5: Connect WordPress Auto-Publishing
5.1 Generate a WordPress Application Password
- Log in to your WordPress admin dashboard -> Users -> Profile
- Scroll to the bottom and find Application Passwords
- Enter the name
n8n-auto-publishand click Add New Application Password - Copy the generated password (format:
xxxx xxxx xxxx xxxx xxxx xxxx)
This password is shown only once. Save it somewhere secure before closing the dialog.
5.2 Create a WordPress Credential in n8n
Go to Settings -> Credentials -> Add Credential -> HTTP Basic Auth:
| Field | Value |
|---|---|
| Name | WordPress API |
| User | Your WordPress username |
| Password | The application password from the previous step |
5.3 Add an HTTP Request Node to Publish Articles
| Parameter | Value |
|---|---|
| Method | POST |
| URL | https://yourdomain.com/wp-json/wp/v2/posts |
| Authentication | Predefined Credential -> HTTP Basic Auth -> WordPress API |
| Send Headers | Content-Type: application/json |
Request Body (JSON mode):
{
"title": "{{ $json.seoTitle }}",
"content": "{{ $json.rewrittenContent }}",
"status": "draft",
"categories": [8],
"tags": "{{ $json.seoTags }}",
"slug": "{{ $json.slug }}",
"meta": {
"_yoast_wpseo_metadesc": "{{ $json.seoDescription }}"
}
}
Tip: Set
statustodraftinitially so you can manually review articles for quality. Once you are confident in the output, change it topublish. Thecategoriesvalue is a WordPress category ID — adjust it to match your site.
✅ Expected Result: After execution, navigate to your WordPress admin -> Posts -> Drafts. You should see the new article with the AI-rewritten content.
Step 6: Add SEO Optimization Node
Insert a dedicated SEO optimization node between the DeepSeek content rewrite step and the WordPress publishing step.
6.1 SEO Generation Request
Add a new HTTP Request node calling the DeepSeek API:
| Parameter | Value |
|---|---|
| Method | POST |
| URL | https://api.deepseek.com/chat/completions |
| Authentication | Predefined Credential -> Header Auth -> DeepSeek API |
| Send Headers | Content-Type: application/json |
Request Body:
{
"model": "deepseek-chat",
"messages": [
{
"role": "system",
"content": "You are an SEO expert. Based on the given article content, generate the following and return as JSON (do not include markdown code block markers): {\"seoTitle\": \"SEO title under 60 characters\", \"seoDescription\": \"Meta description under 155 characters\", \"seoTags\": [\"tag1\", \"tag2\", \"tag3\"], \"slug\": \"english-url-slug\"}"
},
{
"role": "user",
"content": "{{ $json.rewrittenContent }}"
}
],
"temperature": 0.3,
"max_tokens": 512
}
Setting
temperatureto 0.3 produces more stable and consistently formatted SEO output.
6.2 Parse the SEO Data
Connect a Function node after the SEO request:
const items = $input.all();
return items.map(item => {
const raw = item.json.choices[0].message.content;
let seoData;
try {
seoData = JSON.parse(raw);
} catch (e) {
// Attempt to extract JSON block if parsing fails
const match = raw.match(/\{[\s\S]*\}/);
seoData = match ? JSON.parse(match[0]) : {
seoTitle: item.json.originalTitle,
seoDescription: '',
seoTags: [],
slug: ''
};
}
return {
json: {
...item.json,
seoTitle: seoData.seoTitle,
seoDescription: seoData.seoDescription,
seoTags: seoData.seoTags,
slug: seoData.slug
}
};
});
The try/catch block provides fault tolerance — if DeepSeek returns the JSON wrapped in markdown code fences, the regex fallback will still extract it correctly.
✅ Expected Result: The output data now contains seoTitle, seoDescription, seoTags, and slug fields with SEO-optimized values.
Step 7: Schedule & Monitor
7.1 Set Up the Cron Trigger
Replace the workflow’s start node with a Cron Trigger node:
| Parameter | Value |
|---|---|
| Mode | Every Day |
| Hour | 8 |
| Minute | 30 |
| Timezone | America/New_York |
This runs the pipeline automatically every day at 8:30 AM. For more frequent execution, use a custom cron expression:
| Parameter | Value |
|---|---|
| Mode | Custom (Cron) |
| Cron Expression | 0 */6 * * * |
The expression above triggers every 6 hours (at midnight, 6 AM, noon, and 6 PM).
7.2 Add Error Handling
Enable the Error Workflow feature in your workflow settings:
- Create a new workflow and name it
Error Handler - Add an Error Trigger node as the start
- Connect a Send Email node (or a Telegram Bot node) after it
Send Email node configuration:
| Parameter | Value |
|---|---|
| From | alert@yourdomain.com |
| To | your@email.com |
| Subject | n8n Workflow Execution Failed |
| Body | Workflow "{{ $json.workflow.name }}" failed at node "{{ $json.execution.error.node }}": {{ $json.execution.error.message }} |
- Go back to your main workflow -> Settings -> Error Workflow and select
Error Handler
7.3 Activate the Workflow
Click the Active toggle in the top-right corner to enable the workflow.
✅ Expected Result: The workflow status turns green (active). Wait for the next scheduled trigger time and confirm that the workflow executes automatically, creating a new draft in WordPress. To test error handling, temporarily invalidate the API key and verify that you receive an alert email.
Cost Analysis
Based on publishing 5 articles per day (150 per month):
| Item | Monthly Cost | Details |
|---|---|---|
| VPS Server | $5-10 | Any cloud provider, 1 CPU / 1 GB RAM tier |
| DeepSeek API | $1-3 | ~3,000 input tokens + ~2,000 output tokens per article, 150 articles/month |
| Domain Name | $1-2 | Amortized monthly from annual registration |
| WordPress Hosting | $0 | Can share the same VPS as n8n |
| Total | $7-15 | Less than a single freelance article |
Compared to hiring freelance writers ($20-80 per article), producing 150 articles per month with this pipeline reduces content costs by over 99%.
DeepSeek API pricing is significantly lower than comparable models (e.g., GPT-4o), making it one of the most cost-effective options available today.
FAQ
Q1: What if the target website blocks my RSS requests?
Use an RSS proxy service such as RSSHub to generate feeds, or set a custom User-Agent header and add a random delay in a Function node before the HTTP request:
// Add a random delay between 3-10 seconds
await new Promise(resolve =>
setTimeout(resolve, Math.random() * 7000 + 3000)
);
Q2: DeepSeek API output quality is inconsistent?
- Refine your system prompt with more specific output format requirements and examples
- Lower
temperatureto 0.5 or below for more predictable results - Add a word count validation step in a Function node that re-triggers the API call if the output is too short or too long
Q3: WordPress API returns a 401 error?
Check the following:
- The Application Passwords feature is enabled (some security plugins disable it)
- The username and application password are correctly paired
- Your WordPress site uses HTTPS (Application Passwords may be rejected over plain HTTP)
- The REST API is not blocked by a firewall or security plugin (test with
curl -I https://yourdomain.com/wp-json/wp/v2/posts)
Q4: How do I prevent duplicate articles from being published?
Add a Function node after the RSS Read node that checks existing WordPress posts by title:
// Query WP API to check if an article with this title already exists
const searchUrl = `https://yourdomain.com/wp-json/wp/v2/posts?search=${encodeURIComponent($json.title)}&per_page=1`;
const response = await this.helpers.httpRequest({
method: 'GET',
url: searchUrl,
});
if (response.length > 0) {
return []; // Already exists, skip this item
}
return [$input.item];
Q5: How many workflows can a single server handle?
A 1 CPU / 1 GB RAM VPS can comfortably run 3-5 similar workflows simultaneously. If you need more, upgrade to a 2 CPU / 2 GB instance, or switch the n8n database from the default SQLite to PostgreSQL for better concurrency performance:
# Add to your docker-compose.yml environment section
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=localhost
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=n8n
- DB_POSTGRESDB_USER=n8n
- DB_POSTGRESDB_PASSWORD=your_db_password
Next Steps
Once your base pipeline is running smoothly, consider these enhancements:
-
Multi-source Aggregation — Add more RSS feeds and use Merge nodes to combine them before processing. This lets you cover multiple niches from a single workflow.
-
Automated Images — Integrate the Unsplash API or an AI image generation tool to automatically attach featured images to every article.
-
Multi-platform Distribution — After publishing to WordPress, syndicate content to Medium, LinkedIn, or a Substack newsletter using additional HTTP Request nodes.
-
Analytics Dashboard — Use n8n to periodically fetch data from Google Analytics or Search Console and populate a Google Sheet or Airtable base with traffic reports.
-
Intelligent Scheduling — Analyze historical traffic data with AI to determine optimal publishing times, then dynamically adjust the Cron schedule.
-
Content Review Gate — Insert an AI review node before publishing that checks for factual accuracy, readability score, and flagged terms. Only articles that pass all checks proceed to WordPress.
After completing these steps, you will have a fully automated content production system. From RSS fetching to AI rewriting, from SEO optimization to scheduled publishing — the entire pipeline runs without manual intervention. All that remains is to continuously refine your prompts, expand your content sources, and let this content engine run faster every day.
Related Manuals
Building an Autonomous Content Factory with n8n and Claude 3.5 Sonnet
A comprehensive guide to scaling your content operations using n8n workflows and the high-reasoning capabilities of Claude 3.5, from research to automated publishing.
Building a Multi-modal AI Agent on n8n (Voice, PDF, and Vision)
A comprehensive guide to constructing versatile n8n agents that can process voice notes via Deepgram, analyze PDFs with RAG, and 'see' images using latest LLMs.