Saudações.
Vou ensinar como rodar o N8N direto no MacOS, sem Docker, sem container, sem dependências externas na Internet.
Antigamente a Nodemation (n8n) criava o aplicativo do N8N para desktop mas infelizmente descontinuaram o método, passando a operar somente em Docker e com foco em nuvem.
Nesse link você encontra como realizar o processo de compilação a partir dos fontes para construção da imagem OCI (Docker) do zero:
E nesse link você aprende sobre os modos de execução do N8N:
Aqui vou focar na execução baseada nos fontes para personalizações e tunings profundos.
Pré-requisitos:
- Computador Apple Silicon: Mac Mini ou notebook Apple com MacOS;
- Acesso à Internet durante os procedimentos.
1 – Preparação
Vou isolar a execução dentro da estrutura do brew.
Abra o Terminal do MacOS:
- Aplicativos => Utilitários => Terminal;
Execute os procedimentos de instalação do brew em:
- https://brew.sh/
- Arquivo install.sh de https://github.com/Homebrew/install
Após instalar o brew, feche o terminal e abra-o novamente.
Se preferir, alterne o shell padrão para o bash em vez do csh:
Requer senha para alterar o shell, após alterar feche o Terminal e abra novamente.
Personalizando formato do shell:
BASH (MacOS)
# Banco e cinza #export PS1='\[\033[0;99m\][\[\033[0;90m\]\u\[\033[0;99m\]@\[\033[0;99m\]\h\[\033[0;99m\]] \[\033[1;38m\]\w\[\033[0;99m\] \$\[\033[0m\] '; # Verde e Amarelo export PS1='\[\033[0;99m\][\[\033[0;92m\]\u\[\033[0;99m\]@\[\033[0;93m\]\h\[\033[0;99m\]] \[\033[1;38m\]\w\[\033[0;99m\] \$\[\033[0m\] '; # Colocar personalizacao sempre que iniciar um novo shell: egrep -q PS1 ~/.bash_profile 2>/dev/null || \ /bin/echo "export PS1='$PS1';" >> ~/.bash_profile;Feche o Terminal e abra novamente!
Atualizando brew antes de continuar:
BASH (MacOS)
# Atualizar brew: brew update; brew upgrade;Garantir os binários do brew no caminho de busca dos programas no Terminal:
BASH (MacOS)
# Colocar homebrew no PATH egrep -q '/opt/homebrew/bin' ~/.bash_profile 2>/dev/null || \ /bin/echo "export PATH='/opt/homebrew/bin:$PATH';" >> ~/.bash_profile;Feche o Terminal e abra novamente!
A pasta padrão do ecosistema brew é em: /opt/homebrew
Instalando programas necessários no brew:
BASH (MacOS)
# Uv brew install uv; # Git brew install git; # Python (necessário para algumas dependências, v3.14) brew install python3; # Jq - interpretador JSON brew install jq; #- Node.js - atual: 25 #- brew install node; # Node.js - versao 24 requerida pelo n8n brew install node@24; # Instalar Corepack (ignore erros) brew install corepack; brew unlink corepack; brew link --overwrite corepack;2 – Compilar N8N do zero
O N8N é escrito em TypeScript (NodeJS), logo vamos precisar da pilha TS para preparar os fontes para execução.
2.1 – Baixando código fonte do N8N
Observem bem a versão do N8N que você irá usar. Link para conferir versões disponíveis:
BASH (MacOS)
# Diretorio para rodar o programa: /opt/homebrew/n8n-current mkdir -p /opt/homebrew/n8n-current; # Entrar no diretorio: cd /opt/homebrew/n8n-current; # Baixar do git a versao desejada: N8N_VERSION="1.121.2"; git clone \ --branch release/$N8N_VERSION \ --single-branch https://github.com/n8n-io/n8n.git . || echo "Falhou no git";Crie a chave de criptografia do N8N, usada para proteger canais e credenciais internas:
BASH (MacOS)
# Config minima estatica: # tulipa ou md5(tulipa) = 52169089a52705298a67f2f8d9895c76 mkdir -p ~/.n8n; ( echo '{'; echo ' "encryptionKey": "tulipa"'; echo '}'; ) > ~/.n8n/config; # Permissoes fechadas: chmod 600 /Users/patrickbrandao/.n8n/config;2.2 – Preparando ambiente do projeto
Ajustes necessários para sincronizar as versões corretas do node e npm.
BASH (MacOS)
# Entrar no diretorio dos fontes: cd /opt/homebrew/n8n-current; # Ativar corepack: corepack enable; # Selecionar versao do pnpm ~ 10.18.3 (muda a cada update do n8n): corepack prepare pnpm@10.23.0 --activate; # Garantir versao 24 do node como padrão do sistema: brew unlink node 2>/dev/null; brew link node@24 2>/dev/null; brew link --overwrite node@24 2>/dev/null; # Conferindo node 24: # Conferindo versões dos programas: node --version; # v24.11.1 # Conferindo caminho dos binarios: which node; # /opt/homebrew/bin/node # Conferindo binário real do comando 'node': readlink -f /opt/homebrew/bin/node; # /opt/homebrew/Cellar/node@24/24.11.1/bin/node # Retirar node 25 instalado pelo corepack brew uninstall --ignore-dependencies node@25 2>/dev/null; # Apontar node do corepack para a versao 24 mkdir -p /opt/homebrew/opt/node/bin; ln -sf \ /opt/homebrew/Cellar/node@24/24.11.1/bin/node \ /opt/homebrew/opt/node/bin/node; # Colocar corepack no projeto: corepack up;2.3 – Compilando
Essa é a parte demorada, onde tod
BASH (MacOS)
# Entrar no diretorio dos fontes: cd /opt/homebrew/n8n-current; # Ajuste de permissoes: chmod -R u+rwX /opt/homebrew/n8n-current; # Instalar dependencias infinitas, essa é a parte que DEMORA MUITO ~5min: pnpm --loglevel verbose install; # Vai terminar com a mensagem na ultima linha: # "Done in 43s using pnpm v10.18.3" # (coloque aqui sua etapa de personalizacao dos fontes) # ... # Construindo projeto unificado, DEMORA MUITO ~15min: pnpm --loglevel verbose build; pnpm --loglevel verbose build:n8n;Após esse processo será produzida a pasta:
- ./compiled: /opt/homebrew/n8n-current/compiled
Esse é o diretório que deve ser exportado para adição em container Docker e enviado para produção.
2.4 – Exportando projeto compilado
Vamos usar a pasta “compiled” para instalar o n8n no local definitivo em /opt/homebrew/n8n-app
BASH (MacOS)
# Criar diretorio final: mkdir -p /opt/homebrew/n8n-app; # Entrar no diretorio final: cd /opt/homebrew/n8n-app; # Copiar projeto compilado para pasta atual: rsync -ravp /opt/homebrew/n8n-current/compiled/ /opt/homebrew/n8n-app/; # Rodando versão compilada para teste: # /opt/homebrew/n8n-app/bin/n8n start; # CONTROL+C para interromper o teste.2.5 – Compilando Task-Runner JavaScript
Nota: Etapa é opcional, faça somente se você precisar do Task-Runner para o MacOS.
BASH (MacOS)
# Entrar no diretorio dos fontes: cd /opt/homebrew/n8n-current; # Instalar task-runner Javascript mkdir -p /opt/homebrew/tmp/runners; rsync -ravp dist/task-runner-javascript /opt/homebrew/tmp/runners/; # Compilar Task-Runners cd /opt/homebrew/tmp/runners/task-runner-javascript; corepack enable pnpm; # Ajustar package.json node -e "const pkg = require('./package.json'); \ Object.keys(pkg.dependencies || {}).forEach(k => { \ const val = pkg.dependencies[k]; \ if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \ delete pkg.dependencies[k]; \ }); \ Object.keys(pkg.devDependencies || {}).forEach(k => { \ const val = pkg.devDependencies[k]; \ if (val === 'catalog:' || val.startsWith('catalog:') || val.startsWith('workspace:')) \ delete pkg.devDependencies[k]; \ }); \ delete pkg.devDependencies; \ require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));"; # Instalar pacoate 'moment' rm -f node_modules/.modules.yaml; pnpm add moment@2.30.1 --prod --no-lockfile; # Caminho do Task-Runner Javascript: ls -lah /opt/homebrew/tmp/runners/task-runner-javascript/dist/start.js; # Colocar Task-Runner junto com o N8N pronto rsync -ravp /opt/homebrew/tmp/runners /opt/homebrew/n8n-app/; # Remover diretorio temporario do runners rm -rf /opt/homebrew/tmp/runners;2.6 – Compilando Task-Runner Launcher
Nota: Etapa é opcional, faça somente se você precisar do Task-Runner para o MacOS.
O Task-Runner Launcher é responsável pelo gerenciamento da execução dos Task-Runners e pela comunicação com o processo worker do N8N.
BASH (MacOS)
# Pasta temporaria para compilacao # - Remover e recriar pasta temporaria rm -rf /opt/homebrew/tmp; mkdir -p /opt/homebrew/tmp; cd /opt/homebrew/tmp; # Instalar Go brew install go; # Converir versao do Go go version; # go version go1.25.4 darwin/arm64 # Obter codigo-fonte do Task-Runner-Launcher git clone https://github.com/n8n-io/task-runner-launcher.git; cd /opt/homebrew/tmp/task-runner-launcher; # Compilar (modo simples) #- go build -o task-runner-launcher ./cmd/launcher; # Compilar com otimizações GOOS=darwin GOARCH=arm64 go \ build -ldflags="-s -w" \ -o task-runner-launcher ./cmd/launcher; # Conferindo tipo do binario compilado: file ./task-runner-launcher; # ./task-runner-launcher: Mach-O 64-bit executable arm64 # Conferindo binario pronto (o erro abaixo significa que funcionou): ./task-runner-launcher --version; # 2025/11/25 01:21:20 ERROR Failed to load config: # AuthToken: missing required value: N8N_RUNNERS_AUTH_TOKEN # Distribuir binario TRL para estrutura do brew: mkdir -p /opt/homebrew/n8n-app/runners; rm -rf /opt/homebrew/n8n-app/runners/task-runner-launcher; cp -av ./task-runner-launcher /opt/homebrew/n8n-app/runners/task-runner-launcher; # Criar link simbolico no caminho oficial ln -sf \ /opt/homebrew/n8n-app/runners/task-runner-launcher \ /opt/homebrew/bin/task-runner-launcher; # Limpar diretorio usado na compilacao: cd /opt/homebrew; rm -rf /opt/homebrew/tmp;3 – Preparativos para o modo fila
Para rodar o N8N em modo fila vamos precisar do Redis e do PostgreSQL no nosso MacOS.
3.1 – PostgreApp
A melhor forma de provisionar um serviço de banco de dados no MacOS é com o PGAPP:
- Site: https://postgresapp.com/
- Download: https://postgresapp.com/downloads.html
Procedimentos:
- Garanta a existência de um serviço PostgreSQL 18
- Garanta que o serviço está marcado para iniciar automaticamente;
- Garanta que o PostgresApp está marcado para iniciar automaticamente no MacOS.
Tela do PGAPP:

O próximo passo é criar o banco de dados do N8N no serviço PostgreSQL 18. Conecte-se no banco de dados postgres com usuário postgres e execute:
psql -U postgres
-- Criar usuario exclusivo para o n8n chamado "n8n_local_user": CREATE USER n8n_local_user WITH PASSWORD 'n8nsql2025' CREATEDB LOGIN; -- criar db e usuario do n8n chamado "n8n_local_db": CREATE DATABASE n8n_local_db WITH OWNER = n8n_local_user ENCODING = 'UTF8' TABLESPACE = pg_default IS_TEMPLATE = False CONNECTION LIMIT = -1; -- Conectar no banco "n8n_local_db": \c n8n_local_db; -- Conceder todos os privilégios ao usuario "n8n_local_user" no banco "n8n_local_db" GRANT ALL PRIVILEGES ON DATABASE n8n_local_db TO n8n_local_user; -- Adicionar extensao (ignore alerta, se ja existir otimo): CREATE EXTENSION IF NOT EXISTS pg_stat_statements; -- Conceder privilégios no schema público GRANT ALL ON SCHEMA public TO n8n_local_user; -- Garantir privilégios em tabelas futuras ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO n8n_local_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO n8n_local_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO n8n_local_user; -- Verificar se o usuário foi criado \du n8n_local_user; -- Verificar se o banco foi criado \l n8n_local_db; -- Verificar privilégios no banco \l+ n8n_local_db; -- Sair \qServiço PostgreSQL criado:
- Endereço do servidor PostgreSQL: localhost (127.0.0.1 ou ::1) porta 5432
- Usuário e senha de acesso: n8n_local_user senha n8nsql2025
- Banco de dados chamado: n8n_local_db
Se desejar uma administração visual do banco de dados, instale o pgAdmin para MacOS:
3.2 – Redis Server
O Redis pode ser instalado usando o próprio brew:
BASH (MacOS)
# Entrar no diretorio do brew: cd /opt/homebrew/; # Remover redis nativo, se presente: brew uninstall redis 2>/dev/null; # Instalando Redis: brew tap redis/redis; brew install --cask redis; # Conferindo configuração padrão: cat /opt/homebrew/etc/redis.conf | egrep -v '^(#|$)'; # Garantir existencia do diretorio de dados: mkdir -p /opt/homebrew/var/db/redis;Nenhuma configuração especial é requerida no Redis.
Parar criar serviço do Redis no gestor de serviços do MacOS (Launcher) crie o arquivo:
- ~/Library/LaunchAgents/com.redis-server.plist
Com o seguinte conteúdo:
~/Library/LaunchAgents/com.redis-server.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.redis-server</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/redis-server</string> <string>--bind '0.0.0.0 ::'</string> <string>--port 6379</string> <string>--set-proc-title no</string> <string>--tcp-backlog 8192</string> <string>--tcp-keepalive 30</string> <string>--timeout 0</string> <string>--save 900 1</string> <string>--save 300 10</string> <string>--save 60 10000</string> <string>--dir /opt/homebrew/var/db/redis/</string> <string>--rdbcompression no</string> <string>--rdbchecksum yes</string> <string>--dbfilename data.rdb</string> <string>--appendonly yes</string> <string>--appendfsync everysec</string> <string>--appendfilename data.aof</string> </array> <key>WorkingDirectory</key> <string>/opt/homebrew/var/db/redis</string> <key>EnvironmentVariables</key> <dict> <key>TZ</key><string>America/Sao_Paulo</string> </dict> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/redis-server-stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/redis-server-error.log</string> </dict> </plist>Registrar serviço e iniciar:
BASH (MacOS)
# Parar o serviço: launchctl stop com.redis-server; # Descarregar: launchctl unload ~/Library/LaunchAgents/com.redis-server.plist; # Limpar logs echo > /tmp/redis-server-stdout.log; echo > /tmp/redis-server-error.log; # Carregar no cadastro de serviços: launchctl load ~/Library/LaunchAgents/com.redis-server.plist; # Parar o serviço (execute e aguarde uns 15s) launchctl stop com.redis-server; # Iniciar o serviço launchctl start com.redis-server; # Verificar status launchctl list | grep redis; # rodando: 59073 0 com.redis-server # parado.: - 0 com.redis-server # Ver logs tail -n 20 /tmp/redis-server-stdout.log; tail -n 20 /tmp/redis-server-error.log; # Acompanhar logs tail -f /tmp/redis-server-stdout.log /tmp/redis-server-error.log;Serviço Redis criado:
- Endereço do servidor Redis: localhost (127.0.0.1 ou ::1) porta 6379
- Usuário e senha de acesso: (sem senha)
Testando serviço Redis:
BASH (MacOS)
redis-cli -h localhost -p 6379; SET teste 123 # OK GET teste "123" DEL teste (integer) 1 GET teste (nil) exit4 – Rodando N8N no modo fila no MacOS
Antes de continuar é necessário entender as variáveis de ambiente envolvidas.
4.1 – Variáveis de ambiente
Variáveis de ambiente que devem estar presentes em todos os serviços do N8N:
| Variável | Objetivo |
| EXECUTIONS_MODE | Padrão “regular”, alterar para queue |
| N8N_ENCRYPTION_KEY | tulipa |
| TZ | America/Sao_Paulo |
| GENERIC_TIMEZONE | America/Sao_Paulo |
| DB_TYPE | Tipo de banco de dados, padrão “sqlite”, alterar para “postgresdb“. |
| DB_POSTGRESDB_HOST | Endereço IP/DNS do servidor PG, localhost |
| DB_POSTGRESDB_PORT | Porta TCP do servidor PG, 5432 |
| DB_POSTGRESDB_USER | Usuário de autenticação, n8n_local_user |
| DB_POSTGRESDB_PASSWORD | Senha de autenticação, n8nsql2025 |
| DB_POSTGRESDB_DATABASE | Nome do banco de dados, n8n_local_db |
| DB_POSTGRESDB_SCHEMA | Nome do esquema, public |
| QUEUE_BULL_REDIS_HOST | Endereço do servidor Redis, localhost |
| QUEUE_BULL_REDIS_PORT | Porta do servidor Redis, 6379 |
| QUEUE_BULL_REDIS_DB | Número do DB no Redis (0), mudar para 8 |
| QUEUE_BULL_REDIS_PASSWORD | Senha do Redis, deixar sem (padrão) |
| QUEUE_BULL_REDIS_DUALSTACK | Permitir IPv4 e IPv6 na conexão, true |
| QUEUE_HEALTH_CHECK_ACTIVE | Verificar serviço de filas, true |
Personalize sse precisar.
Variáveis que não podem repetir:
| Variável | Objetivo |
| N8N_PORT | Padrão 5678, mas cada serviço precisará da sua porta pois todos estão rodando juntos. |
Vou usar as seguintes portas:
- Editor: porta 5780;
- Webhook: porta 5690;
- Worker: porta 5500, embora ele não deva abrir porta, por algum motivo ele insiste em abrir.
4.2 – Criando serviços do N8N no Launcher
Serviço: n8n-editor – Editor e execuções do editor (execuções manuais):
- ~/Library/LaunchAgents/com.n8n-editor.plist
~/Library/LaunchAgents/com.n8n-editor.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.n8n-editor</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/n8n-app/bin/n8n</string> <string>start</string> </array> <key>WorkingDirectory</key> <string>/opt/homebrew</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/n8n-editor-stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/n8n-editor-error.log</string> <key>EnvironmentVariables</key> <dict> <key>N8N_PORT</key> <string>5780</string> <key>N8N_PROXY_HOPS</key> <string>1</string> <key>NODE_ENV</key> <string>production</string> <key>N8N_ENDPOINT_WEBHOOK</key> <string>v1</string> <key>N8N_ENDPOINT_WEBHOOK_TEST</key> <string>test</string> <key>N8N_ENDPOINT_WEBHOOK_WAIT</key> <string>ws-wait</string> <key>N8N_ENDPOINT_MCP</key> <string>mcp</string> <key>N8N_ENDPOINT_MCP_TEST</key> <string>mcp-test</string> <key>N8N_EDITOR_BASE_URL</key> <string>http://localhost:5780</string> <key>WEBHOOK_URL</key> <string>http://localhost:5690</string> <key>N8N_BASE_URL</key> <string>http://localhost:5780</string> <key>N8N_SECURE_COOKIE</key> <string>false</string> <key>N8N_DISABLE_PRODUCTION_MAIN_PROCESS</key> <string>true</string> <key>N8N_DIAGNOSTICS_ENABLED</key> <string>false</string> <key>N8N_BLOCK_ENV_ACCESS_IN_NODE</key> <string>false</string> <key>N8N_GIT_NODE_DISABLE_BARE_REPOS</key> <string>true</string> <key>N8N_USER_FOLDER</key> <string>/opt/homebrew/n8n-data</string> <key>N8N_CUSTOM_EXTENSIONS</key><string>/opt/homebrew/n8n-nodes</string> <key>N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE</key> <string>true</string> <key>N8N_COMMUNITY_PACKAGES_ENABLED</key> <string>true</string> <key>N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS</key> <string>true</string> <key>N8N_EMAIL_MODE</key> <string>smtp</string> <key>N8N_SMTP_HOST</key> <string>smtp.intranet.br</string> <key>N8N_SMTP_PORT</key> <string>587</string> <key>N8N_SMTP_USER</key> <string>username</string> <key>N8N_SMTP_PASS</key> <string>pass123x</string> <key>N8N_SMTP_SENDER</key> <string>root@intranet.br</string> <key>N8N_SMTP_SSL</key> <string>true</string> <key>EXECUTIONS_MODE</key> <string>queue</string> <key>N8N_ENCRYPTION_KEY</key> <string>tulipa</string> <key>TZ</key> <string>America/Sao_Paulo</string> <key>GENERIC_TIMEZONE</key> <string>America/Sao_Paulo</string> <key>DB_TYPE</key> <string>postgresdb</string> <key>DB_POSTGRESDB_HOST</key> <string>localhost</string> <key>DB_POSTGRESDB_PORT</key> <string>5432</string> <key>DB_POSTGRESDB_USER</key> <string>n8n_local_user</string> <key>DB_POSTGRESDB_PASSWORD</key> <string>n8nsql2025</string> <key>DB_POSTGRESDB_DATABASE</key> <string>n8n_local_db</string> <key>DB_POSTGRESDB_SCHEMA</key> <string>public</string> <key>QUEUE_BULL_REDIS_HOST</key> <string>localhost</string> <key>QUEUE_BULL_REDIS_PORT</key> <string>6379</string> <key>QUEUE_BULL_REDIS_DB</key> <string>8</string> <key>QUEUE_BULL_REDIS_DUALSTACK</key> <string>true</string> <key>QUEUE_HEALTH_CHECK_ACTIVE</key> <string>true</string> <key>EXECUTIONS_TIMEOUT</key> <string>1800</string> <key>EXECUTIONS_TIMEOUT_MAX</key> <string>1800</string> <key>EXECUTIONS_DATA_PRUNE</key> <string>true</string> <key>EXECUTIONS_DATA_MAX_AGE</key> <string>336</string> <key>EXECUTIONS_DATA_PRUNE_MAX_COUNT</key> <string>2048</string> <key>EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL</key> <string>15</string> <key>EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL</key> <string>60</string> <key>EXECUTIONS_DATA_SAVE_ON_ERROR</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_SUCCESS</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_PROGRESS</key> <string>true</string> <key>EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS</key> <string>true</string> <key>OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS</key> <string>true</string> </dict> </dict> </plist>Serviço: n8n-webhook – Servidor HTTP para escuta de Webhooks (chamadas HTTP)
- Arquivo: ~/Library/LaunchAgents/com.n8n-webhook.plist
~/Library/LaunchAgents/com.n8n-webhook.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.n8n-webhook</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/n8n-app/bin/n8n</string> <string>webhook</string> </array> <key>WorkingDirectory</key> <string>/opt/homebrew</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/n8n-webhook-stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/n8n-webhook-error.log</string> <key>EnvironmentVariables</key> <dict> <key>N8N_PORT</key> <string>5690</string> <key>N8N_PROXY_HOPS</key> <string>1</string> <key>NODE_ENV</key> <string>production</string> <key>N8N_ENDPOINT_WEBHOOK</key> <string>v1</string> <key>N8N_ENDPOINT_WEBHOOK_TEST</key> <string>test</string> <key>N8N_ENDPOINT_WEBHOOK_WAIT</key> <string>ws-wait</string> <key>N8N_ENDPOINT_MCP</key> <string>mcp</string> <key>N8N_ENDPOINT_MCP_TEST</key> <string>mcp-test</string> <key>N8N_EDITOR_BASE_URL</key> <string>http://localhost:5780</string> <key>WEBHOOK_URL</key> <string>http://localhost:5690</string> <key>N8N_BASE_URL</key> <string>http://localhost:5780</string> <key>N8N_DIAGNOSTICS_ENABLED</key> <string>false</string> <key>N8N_BLOCK_ENV_ACCESS_IN_NODE</key> <string>false</string> <key>N8N_GIT_NODE_DISABLE_BARE_REPOS</key> <string>true</string> <key>N8N_USER_FOLDER</key> <string>/opt/homebrew/n8n-data</string> <key>N8N_CUSTOM_EXTENSIONS</key><string>/opt/homebrew/n8n-nodes</string> <key>N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE</key> <string>true</string> <key>N8N_COMMUNITY_PACKAGES_ENABLED</key> <string>true</string> <key>N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS</key> <string>true</string> <key>EXECUTIONS_MODE</key> <string>queue</string> <key>N8N_ENCRYPTION_KEY</key> <string>tulipa</string> <key>TZ</key> <string>America/Sao_Paulo</string> <key>GENERIC_TIMEZONE</key> <string>America/Sao_Paulo</string> <key>DB_TYPE</key> <string>postgresdb</string> <key>DB_POSTGRESDB_HOST</key> <string>localhost</string> <key>DB_POSTGRESDB_PORT</key> <string>5432</string> <key>DB_POSTGRESDB_USER</key> <string>n8n_local_user</string> <key>DB_POSTGRESDB_PASSWORD</key> <string>n8nsql2025</string> <key>DB_POSTGRESDB_DATABASE</key> <string>n8n_local_db</string> <key>DB_POSTGRESDB_SCHEMA</key> <string>public</string> <key>QUEUE_BULL_REDIS_HOST</key> <string>localhost</string> <key>QUEUE_BULL_REDIS_PORT</key> <string>6379</string> <key>QUEUE_BULL_REDIS_DB</key> <string>8</string> <key>QUEUE_BULL_REDIS_DUALSTACK</key> <string>true</string> <key>QUEUE_HEALTH_CHECK_ACTIVE</key> <string>true</string> <key>EXECUTIONS_TIMEOUT</key> <string>1800</string> <key>EXECUTIONS_TIMEOUT_MAX</key> <string>1800</string> <key>EXECUTIONS_DATA_PRUNE</key> <string>true</string> <key>EXECUTIONS_DATA_MAX_AGE</key> <string>336</string> <key>EXECUTIONS_DATA_PRUNE_MAX_COUNT</key> <string>2048</string> <key>EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL</key> <string>15</string> <key>EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL</key> <string>60</string> <key>EXECUTIONS_DATA_SAVE_ON_ERROR</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_SUCCESS</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_PROGRESS</key> <string>true</string> <key>EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS</key> <string>true</string> <key>OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS</key> <string>true</string> </dict> </dict> </plist>Serviço: n8n-worker – Processo responsável pela execução dos Workflows
- Arquivo: ~/Library/LaunchAgents/com.n8n-worker.plist
~/Library/LaunchAgents/com.n8n-worker.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.n8n-worker</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/n8n-app/bin/n8n</string> <string>worker</string> <string>--concurrency=32</string> </array> <key>WorkingDirectory</key> <string>/opt/homebrew</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/n8n-worker-stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/n8n-worker-error.log</string> <key>EnvironmentVariables</key> <dict> <key>N8N_PORT</key> <string>5500</string> <key>NODE_ENV</key> <string>production</string> <key>N8N_BASE_URL</key> <string>http://localhost:5780</string> <key>N8N_DIAGNOSTICS_ENABLED</key> <string>false</string> <key>N8N_BLOCK_ENV_ACCESS_IN_NODE</key> <string>false</string> <key>N8N_GIT_NODE_DISABLE_BARE_REPOS</key> <string>true</string> <key>N8N_USER_FOLDER</key> <string>/opt/homebrew/n8n-data</string> <key>N8N_CUSTOM_EXTENSIONS</key><string>/opt/homebrew/n8n-nodes</string> <key>N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE</key> <string>true</string> <key>N8N_COMMUNITY_PACKAGES_ENABLED</key> <string>true</string> <key>N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS</key> <string>true</string> <key>EXECUTIONS_MODE</key> <string>queue</string> <key>N8N_ENCRYPTION_KEY</key> <string>tulipa</string> <key>TZ</key> <string>America/Sao_Paulo</string> <key>GENERIC_TIMEZONE</key> <string>America/Sao_Paulo</string> <key>DB_TYPE</key> <string>postgresdb</string> <key>DB_POSTGRESDB_HOST</key> <string>localhost</string> <key>DB_POSTGRESDB_PORT</key> <string>5432</string> <key>DB_POSTGRESDB_USER</key> <string>n8n_local_user</string> <key>DB_POSTGRESDB_PASSWORD</key> <string>n8nsql2025</string> <key>DB_POSTGRESDB_DATABASE</key> <string>n8n_local_db</string> <key>DB_POSTGRESDB_SCHEMA</key> <string>public</string> <key>QUEUE_BULL_REDIS_HOST</key> <string>localhost</string> <key>QUEUE_BULL_REDIS_PORT</key> <string>6379</string> <key>QUEUE_BULL_REDIS_DB</key> <string>8</string> <key>QUEUE_BULL_REDIS_DUALSTACK</key> <string>true</string> <key>QUEUE_HEALTH_CHECK_ACTIVE</key> <string>true</string> <key>EXECUTIONS_TIMEOUT</key> <string>1800</string> <key>EXECUTIONS_TIMEOUT_MAX</key> <string>1800</string> <key>EXECUTIONS_DATA_PRUNE</key> <string>true</string> <key>EXECUTIONS_DATA_MAX_AGE</key> <string>336</string> <key>EXECUTIONS_DATA_PRUNE_MAX_COUNT</key> <string>2048</string> <key>EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL</key> <string>15</string> <key>EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL</key> <string>60</string> <key>EXECUTIONS_DATA_SAVE_ON_ERROR</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_SUCCESS</key> <string>all</string> <key>EXECUTIONS_DATA_SAVE_ON_PROGRESS</key> <string>true</string> <key>EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS</key> <string>true</string> <key>OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS</key> <string>true</string> </dict> </dict> </plist>Registrar e executar serviços:
BASH (MacOS)
# Criar pasta para community-nodes: mkdir -p /opt/homebrew/n8n-nodes; # Criar pasta de arquivos do processo: mkdir -p /opt/homebrew/n8n-data; #------------------------------------------- Parar # Parar os serviços launchctl stop com.n8n-editor; launchctl stop com.n8n-webhook; launchctl stop com.n8n-worker; # Desregistrar (para atualizar) launchctl unload ~/Library/LaunchAgents/com.n8n-editor.plist 2>/dev/null; launchctl unload ~/Library/LaunchAgents/com.n8n-webhook.plist 2>/dev/null; launchctl unload ~/Library/LaunchAgents/com.n8n-worker.plist 2>/dev/null; # Limpar logs echo -n > /tmp/n8n-editor-error.log; echo -n > /tmp/n8n-editor-stdout.log; echo -n > /tmp/n8n-webhook-error.log; echo -n > /tmp/n8n-webhook-stdout.log; echo -n > /tmp/n8n-worker-error.log; echo -n > /tmp/n8n-worker-stdout.log; #------------------------------------------- Iniciar # Carregar no cadastro de serviços: launchctl load ~/Library/LaunchAgents/com.n8n-editor.plist; launchctl load ~/Library/LaunchAgents/com.n8n-webhook.plist; launchctl load ~/Library/LaunchAgents/com.n8n-worker.plist; # Iniciar os serviços launchctl start com.n8n-editor; launchctl start com.n8n-webhook; launchctl start com.n8n-worker; # Verificar status launchctl list | grep n8n; # 26377 0 com.n8n-webhook # 26080 0 com.n8n-editor # 26077 1 com.n8n-worker # Ver logs tail -n 20 /tmp/n8n*; # Acompanhar logs tail -f /tmp/n8n*;O editor está na porta 5780 – http://localhost:5780/
O servidor HTTP de API (webhook) está na porta 5090 – http://localhost:5690/
O N8N está pronto. Use a vontade!
5 – Executar N8N com Task-Runner
Avançando rumo a perfeição, vamos compilar o Task-Runner (TR) para que ele se responsabilize pela execução de código Javascript/TypeScript e Python fora do Worker, criando no TR um ambiente Sandbox seguro para execuções de códigos de origem duvidosa (usuário, IA).
Vantagens:
- Maior resiliência na execução de código estrangeiro
- Segregação de execução de código estrangeiro em CPUs e servidores diferentes;
Desvantagens:
- Mais lento, workflows que acionam node Code ficam mais lentos;
- Latência de rede entre worker e task-runner afeta o tempo total de execução do worker;
Se você não quiser usar o Task-Runner, rode vários workers e crie rotinas que reiniciam os workers periodicamente para evitar memory-leak (acumulo de memória).
Pre-requisitos:
- Task-Runner-Launcher;
- Task-Runner-Javascript;
O Task-Runner-Python é opcional.
Configurar runners:
- /etc/n8n-task-runners.json
/etc/n8n-task-runners.json
{ "task-runners": [ { "runner-type": "javascript", "workdir": "/opt/homebrew/n8n-app/runners/task-runner-javascript", "command": "/opt/homebrew/opt/node/bin/node", "args": [ "--disallow-code-generation-from-strings", "--disable-proto=delete", "/opt/homebrew/n8n-app/runners/task-runner-javascript/dist/start.js" ], "health-check-server-port": "5681", "allowed-env": [ "PATH", "GENERIC_TIMEZONE", "NODE_OPTIONS", "N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT", "N8N_RUNNERS_TASK_TIMEOUT", "N8N_RUNNERS_MAX_CONCURRENCY", "N8N_SENTRY_DSN", "N8N_VERSION", "ENVIRONMENT", "DEPLOYMENT_NAME" ], "env-overrides": { "NODE_FUNCTION_ALLOW_BUILTIN": "crypto", "NODE_FUNCTION_ALLOW_EXTERNAL": "moment", "N8N_RUNNERS_HEALTH_CHECK_SERVER_HOST": "0.0.0.0" } } ] }Variáveis que devem ser configuradas nas instâncias (editor, worker e webhook):
| Variável | Valor |
| N8N_RUNNERS_ENABLED | true |
| N8N_RUNNERS_MODE | external |
| N8N_RUNNERS_AUTH_TOKEN | tulipa |
| N8N_RUNNERS_MAX_CONCURRENCY | 32 |
| N8N_RUNNERS_TASK_TIMEOUT | 300 |
| N8N_RUNNERS_HEARTBEAT_INTERVAL | 30 |
| N8N_RUNNERS_INSECURE_MODE | false |
| N8N_RUNNERS_TASK_REQUEST_TIMEOUT | 20 |
Variáveis que devem ser configuradas no Task-Runner-Launcher:
| Variável | Valor |
| N8N_RUNNERS_AUTH_TOKEN | tulipa |
| N8N_RUNNERS_MAX_CONCURRENCY | 32 |
| N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT | 5588 |
| N8N_RUNNERS_TASK_BROKER_URI | http://127.0.0.1:5679 |
| N8N_RUNNERS_LAUNCHER_LOG_LEVEL | info |
| N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT | 15 |
Declare as seguintes variáveis de ambiente nos serviços editor, webhook e worker:
LaunchAgents ENVs (part)
<key>N8N_RUNNERS_ENABLED</key><string>true</string> <key>N8N_RUNNERS_PATH</key><string>/runners</string> <key>N8N_RUNNERS_MODE</key><string>external</string> <key>N8N_RUNNERS_AUTH_TOKEN</key><string>tulipa</string> <key>N8N_RUNNERS_MAX_CONCURRENCY</key><string>32</string> <key>N8N_RUNNERS_TASK_TIMEOUT</key><string>300</string> <key>N8N_RUNNERS_HEARTBEAT_INTERVAL</key><string>30</string> <key>N8N_RUNNERS_INSECURE_MODE</key><string>false</string> <key>N8N_RUNNERS_TASK_REQUEST_TIMEOUT</key><string>20</string>É preciso adicionar a variável N8N_RUNNERS_BROKER_PORT com cuidado para não conflitar as portas na loopback:
- Editor: N8N_RUNNERS_BROKER_PORT deve mudar da porta padrão para a porta 5501. O editor abre a porta mesmo no modo fila, mudar para não conflitar com a porta 5679 que deve ser exclusiva do worker;
- Webhook: não abre porta broker, não precisa declarar;
- Worker: N8N_RUNNERS_BROKER_PORT na porta 5679 oficial.
Agora é necessário criar o serviço do Task-Runner-Launcher no Launcher do MacOS:
- ~/Library/LaunchAgents/com.task-runner-launcher.plist
~/Library/LaunchAgents/com.task-runner-launcher.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.task-runner-launcher</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/n8n-app/runners/task-runner-launcher</string> <string>javascript</string> </array> <key>WorkingDirectory</key> <string>/opt/homebrew/n8n-app/runners</string> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/tmp/task-runner-launcher-stdout.log</string> <key>StandardErrorPath</key> <string>/tmp/task-runner-launcher-error.log</string> <key>EnvironmentVariables</key> <dict> <key>N8N_RUNNERS_AUTH_TOKEN</key><string>tulipa</string> <key>N8N_RUNNERS_MAX_CONCURRENCY</key><string>32</string> <key>N8N_RUNNERS_LAUNCHER_HEALTH_CHECK_PORT</key><string>5588</string> <key>N8N_RUNNERS_TASK_BROKER_URI</key><string>http://127.0.0.1:5679</string> <key>N8N_RUNNERS_LAUNCHER_LOG_LEVEL</key><string>info</string> <key>N8N_RUNNERS_AUTO_SHUTDOWN_TIMEOUT</key><string>15</string> </dict> </dict> </plist>Registrar e iniciar serviço TRL:
BASH (MacOS)
#------------------------------------------- Parar # Parar os serviços launchctl stop com.task-runner-launcher; # Desregistrar (para atualizar) launchctl unload ~/Library/LaunchAgents/com.task-runner-launcher.plist 2>/dev/null; # Limpar logs echo -n > /tmp/task-runner-launcher-stdout.log; echo -n > /tmp/task-runner-launcher-error.log; #------------------------------------------- Iniciar # Carregar no cadastro de serviços: launchctl load ~/Library/LaunchAgents/com.task-runner-launcher.plist; # Iniciar os serviços launchctl start com.task-runner-launcher; # Verificar status launchctl list | grep task-runner-launcher; # 26413 0 task-runner-launcher # Ver logs tail -n 20 /tmp/task-runner-launcher-*; # Acompanhar logs tail -f /tmp/task-runner-launcher-*;Após adicionar e iniciar o task-runner-launcher, reinicie os serviços do N8N:
BASH (MacOS)
# Recarregar os serviços do N8N: # - Parar launchctl stop com.n8n-editor; launchctl stop com.n8n-webhook; launchctl stop com.n8n-worker; # - Retirar registro launchctl unload ~/Library/LaunchAgents/com.n8n-editor.plist 2>/dev/null; launchctl unload ~/Library/LaunchAgents/com.n8n-webhook.plist 2>/dev/null; launchctl unload ~/Library/LaunchAgents/com.n8n-worker.plist 2>/dev/null; # - Aguardar desligamento sleep 5; # Carregar e iniciar automaticamente launchctl load ~/Library/LaunchAgents/com.n8n-editor.plist 2>/dev/null; launchctl load ~/Library/LaunchAgents/com.n8n-webhook.plist 2>/dev/null; launchctl load ~/Library/LaunchAgents/com.n8n-worker.plist 2>/dev/null;6 – Testes de execução e APIs internas
Testar para conferir se as APIs e serviços estão respondendo.
BASH (MacOS)
# Conferir PID nas portas abertas lsof -i tcp:5780; # editor, porta de servidor http lsof -i tcp:5690; # webhook, porta de servidor http lsof -i tcp:5588; # launcher server - health check lsof -i tcp:5678; # worker, porta padrao lsof -i tcp:5679; # worker, porta do Task Broker # Endpoints # - Editor curl http://localhost:5780/healthz; # {"status":"ok"} curl http://localhost:5780/healthz/readiness; # {"status":"ok"} # - Webhook curl http://localhost:5690/; # deve retornar 404/not-found/html # - Worker - porta padrao curl http://localhost:5678/healthz; # {"status":"ok"} curl http://localhost:5678/healthz/readiness; # {"status":"ok"} # - Worker - porta do Task Broker curl http://localhost:5679/healthz; # {"status":"ok"} # - Task-Runner Launcher curl -s -X POST \ -H "Content-Type: application/json" \ -d '{"token":"tulipa"}' \ http://localhost:5679/runners/auth; #{ # "data": # { # "token":"50dac5034e737597bd358e99e31073d049bc60d0d0422415b55df0d48260a5ed" # } #}“Paris so é Paris se você vai de vez em quando, quando você vai todo dia Paris perde o seu encanto” Autor: Ricardo Thome
Terminamos por hoje,
Patrick Brandão <patrickbrandao@gmail.com>
.png)
há 1 mês
25
English (US) ·
Portuguese (BR) ·