Activepieces: Die echte Open-Source-Alternative zu n8n für SaaS-Entwickler

In 30 Sekunden
- Das Problem: n8n ist mächtig, aber die "Fair-Code"-Lizenz und der Ressourcenhunger limitieren SaaS-Projekte.
- Die Lösung: Activepieces ist MIT-lizenziert, schlanker und setzt konsequent auf TypeScript.
- Der Clou: Native npm-Pakete in Code-Nodes machen komplexe Workflows zum Kinderspiel.
- Praxis: Mit einem Browserless-Sidecar bauen wir in 5 Minuten einen vollautomatischen Web-Scraper.
Warum Activepieces?
N8n ist der Platzhirsch im Self-Hosted-Bereich. Keine Frage. Aber wenn du SaaS-Produkte baust, stößt du oft auf Lizenz-Hürden. Activepieces ist die Antwort für alle, die TypeScript lieben und keine Lust auf Boilerplate haben.
1. Warum Activepieces besser für SaaS-Devs ist als n8n
Ich mag n8n. Aber Activepieces gewinnt in drei entscheidenden Punkten, wenn du Software als Service baust:
- Die Lizenz (The Big One): Activepieces läuft unter der MIT-Lizenz. Du kannst es forken, verändern, in dein Produkt einbauen und kommerziell nutzen – ohne Rechtsabteilung. n8n nutzt eine eigene Lizenz, die "echte" kommerzielle Konkurrenzprodukte einschränkt.
- TypeScript First: Die "Code Node" ist kein Nachgedanke. Du importierst npm-Pakete, und die Engine installiert sie zur Laufzeit in der Sandbox. Es fühlt sich nach "Managed Scripts" an, nicht nach Low-Code-Gefrickel.
- Weniger Bloat: Das Interface ist minimalistischer. Für Devs eine Wohltat, da weniger visuelles Rauschen die Arbeit ablenkt.
2. Die Installation: Der "fehlerfreie" Docker-Weg
Hier bin ich ehrlich: Die Standard-Installation von Activepieces per Docker ist oft zickig. Die Dokumentation verschweigt gerne, dass bestimmte Umgebungsvariablen für die Produktion zwingend sind oder dass man ohne spezielle Flags in einem "Invitation Loop" feststeckt.
Damit du dir 2 Stunden Debugging sparst, nutze diese docker-compose.yml. Sie enthält bereits den Browserless-Container für unser Scraper-Tutorial und umgeht die Registrierungssperre.
services:
activepieces:
image: activepieces/activepieces:latest
container_name: activepieces
restart: always
ports:
- "8080:80"
environment:
# --- System & Edition ---
- AP_ENVIRONMENT=prod # Wichtig: Prod erzwingt korrekte Flags
- AP_EDITION=ce # Community Editon
- AP_SIGN_UP_TERMINATED=false # Erlaubt Registrierung (Fix Invitation-Bug)
- AP_NODE_EXECUTABLE_PATH=/usr/local/bin/node
# --- URLs ---
- AP_FRONTEND_URL=http://localhost:8080
- AP_WEBHOOK_URL=http://localhost:8080
# --- Security ---
- AP_JWT_SECRET=super_secret_jwt_token_fuer_local_dev_12345
- AP_ENCRYPTION_KEY=00112233445566778899aabbccddeeff
# --- Database (PostgreSQL) ---
- AP_POSTGRES_HOST=postgres
- AP_POSTGRES_PORT=5432
- AP_POSTGRES_DATABASE=activepieces
- AP_POSTGRES_USERNAME=activepieces
- AP_POSTGRES_PASSWORD=password
# --- Redis & Queue ---
- AP_REDIS_HOST=redis
- AP_REDIS_PORT=6379
- AP_QUEUE_MODE=REDIS
# --- Execution ---
- AP_ENGINE_EXECUTOR=SANDBOXED # isoliert Code für die Sicherheit
depends_on:
- postgres
- redis
postgres:
image: postgres:15-alpine
container_name: postgres
environment:
- POSTGRES_USER=activepieces
- POSTGRES_PASSWORD=password
- POSTGRES_DB=activepieces
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
container_name: redis
volumes:
- redis_data:/data
# --- browserless optional, für das Tutorial
browserless:
image: browserless/chrome:latest
container_name: browserless
restart: always
ports:
- "3000:3000"
environment:
- MAX_CONCURRENT_SESSIONS=10
volumes:
postgres_data:
redis_data:Starte das Ganze mit docker-compose up -d.
Wichtig
Falls du vorher mit einer kaputten Config experimentiert hast, führe erst docker-compose down -v aus, um die alten DB-Volumes zu löschen.
3. Tutorial: Einen robusten Blog-Scraper bauen
Jetzt bauen wir etwas Nützliches: Wir scrapen promptbard.de/blog/, analysieren die Kategorien und speichern die Statistiken in ein Google Sheet.
Dank Browserless (einem Headless Chromium) können wir auch Seiten scrapen, die stark auf JavaScript setzen.
Schritt 1: Der Scheduler
Wer mit n8n Erfahrung hat, der bewegt sich auch in Activepieces sofort selbstständig, da bekannt.
Wir fügen einen Scheudler hinzu.
Schritt 2: Die Code Node (Puppeteer)
Vergiss simple HTML-Parser. Wir brauchen puppeteer-core.
- Erstelle eine Code Node.
- Gehe oben auf den Reiter package.json.
- Füge
puppeteer-corehinzu. Activepieces holt automatisch die aktuelle Version.
Die Nodes oder Pieces sind ähnlich wie in n8n aufgebaut.
Activepieces zieht die Abhängigkeiten automatisch in aktueller Version.
Füge dann folgenden Code in die Node ein:
import puppeteer from 'puppeteer-core';
export const code = async (inputs) => {
// Verbindung zum Sidecar-Container
// Im Docker-Netzwerk heißt der Host 'browserless'
const browser = await puppeteer.connect({
browserWSEndpoint: 'ws://browserless:3000'
});
try {
const page = await browser.newPage();
// Wir faken einen echten User-Agent
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36');
await page.goto('https://promptbard.de/blog/', {
waitUntil: 'networkidle2',
timeout: 60000
});
// Warten, bis die Badges im DOM sind (wichtig für JS-Rendering!)
await page.waitForSelector('.font-black.tracking-widest', { timeout: 10000 });
const stats = await page.evaluate(() => {
// Wir selektieren nach Struktur, nicht nach Farbe (Tailwind-Best-Practice)
const badges = Array.from(document.querySelectorAll('span.font-black.tracking-widest'));
const counts: Record<string, number> = {};
badges.forEach(badge => {
const text = badge.textContent?.trim() || 'Unkategorisiert';
counts[text] = (counts[text] || 0) + 1;
});
return {
total_categories: Object.keys(counts).length,
total_articles: badges.length,
breakdown: counts
};
});
await browser.close();
// --- Transformation für Google Sheets ---
// Wir flachen das Objekt hier direkt ab, um Mapping-Chaos zu vermeiden
const d = new Date();
const dateStr = `${d.getDate().toString().padStart(2, '0')}.${(d.getMonth() + 1).toString().padStart(2, '0')}.${d.getFullYear()}`;
return {
datum: dateStr,
gesamt: stats.total_articles,
kategorien_anzahl: stats.total_categories,
// Mapping der spezifischen Kategorien
development: stats.breakdown['Development'] || 0,
ki_ressourcen: stats.breakdown['Künstliche Intelligenz'] || 0,
saas_tipps: stats.breakdown['SaaS-Marketing'] || 0
};
} catch (error) {
if (browser) await browser.close();
return { error: error.message };
}
};
Ergebnis: Das sammelt der Scraper.
Schritt 2: Google Sheets Integration
Hier scheitern viele, weil Activepieces keine Spalten für dich erstellt.
- Sheet vorbereiten: Erstelle ein neues Google Sheet und schreibe in die erste Zeile die Header: Datum, Gesamt, Kategorien Count, Development, KI-Ressourcen, SaaS-Tipps.
Wir müssen die Sheet vorbereiten.
- Node hinzufügen: Wähle
Google Sheets -> Insert Row.
So sollte unser Flow mittlerweile aussehen.
- Verbindung: Logge dich ein und wähle dein Sheet.
- Der Trick: Klicke jetzt auf "Refresh Headers" (oder "Load Data"). Erst dann sieht Activepieces deine Spalten.
- Mapping: Klicke in die Felder und weise die Werte aus
step_1(unserem Code) zu.
Die Rows zuweisen in Sheets-Node.
So sollte das Endergebnis aussehen.
Was können wir damit jetzt machen? Vielleicht:
- Scrape deine Wettbewerber und beobachte ihre Content-Strategie.
- Baue den Workflow so weit aus, dass KI Einschätzungen zu den Ergebnissen gibt (oder gleich Entwürfe schreibt).
4. Fazit: Kontrolle statt Komfort-Falle
Activepieces ist (noch) nicht so poliert wie n8n. Manche Integrations fehlen noch. Aber für SaaS-Entwickler, die volle Kontrolle über den Code und die Lizenz wollen, ist es die bessere Wahl.
Du tauschst ein paar Klick-Bunti-Features gegen volle Lizenzfreiheit und echte TypeScript-Power. Mit der obigen Config umgehst du die größten Hürden beim Start.
Häufige Fragen zu Activepieces
Für die Produktion: Ja. Activepieces nutzt Redis als Queue für Background-Jobs. Ohne Redis (Memory Mode) verlierst du Tasks bei einem Neustart des Containers.
Absolut. Activepieces bietet Helm Charts an. Da es stateless ist (bis auf DB/Redis), skaliert es horizontal sehr gut.
Durch die Variable AP_ENGINE_EXECUTOR=SANDBOXED laufen Node-Skripte in isolierten Umgebungen. Das ist deutlich sicherer, als alles direkt auf dem Host-System auszuführen.
Ja. Du trägst sie einfach im 'package.json'-Tab der Code Node ein. Activepieces installiert sie automatisch zur Laufzeit in der Sandbox.
Auch spannend für dich
n8n vs. Open Source: Warum die Lizenz dein SaaS killt (und was du stattdessen nimmst)

n8n für Entwickler: Dein lokaler Automatisierungs-Stack
