Skip to content

Support self-signed SSL certificates#126

Open
gifflet wants to merge 1 commit intoczlonkowski:mainfrom
gifflet:main
Open

Support self-signed SSL certificates#126
gifflet wants to merge 1 commit intoczlonkowski:mainfrom
gifflet:main

Conversation

@gifflet
Copy link

@gifflet gifflet commented Aug 6, 2025

This PR introduces support for self-signed SSL certificates when connecting to an n8n instance. Users can now specify a certificate path using the new N8N_CERT_PATH environment variable. Key changes include:

  • Extended environment configuration (.env.example) to include N8N_CERT_PATH.
  • Enhanced API client to load and use a custom certificate.
  • Updated Docker-related docs and compose files with instructions and examples.
  • README and deployment docs now include detailed usage and troubleshooting for self-signed certs.

@codecov
Copy link

codecov bot commented Aug 6, 2025

Codecov Report

❌ Patch coverage is 34.09091% with 29 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/config/n8n-api.ts 36.00% 16 Missing ⚠️
src/services/n8n-api-client.ts 31.57% 13 Missing ⚠️

📢 Thoughts on this report? Let us know!

@czlonkowski
Copy link
Owner

Thank you for this valuable contribution! 🎉

First, I want to thank you for adding self-signed SSL certificate support to n8n-mcp. This is a much-needed feature that will help users working with n8n instances using self-signed certificates. Your documentation is particularly impressive - comprehensive and well-structured across all the relevant files.

Required Changes

I've reviewed the PR and identified a few critical issues that need to be addressed before we can merge:

🚨 Critical Security Fix

File: src/services/n8n-api-client.ts (lines 55-58)

The current implementation disables SSL verification entirely with rejectUnauthorized: false. This creates a security vulnerability. Here's the fix:

// Current (insecure):
this.httpsAgent = new https.Agent({
  ca: cert,
  rejectUnauthorized: false  // ❌ Remove this line
});

// Fixed (secure):
this.httpsAgent = new https.Agent({
  ca: cert
  // rejectUnauthorized remains true by default
});

📝 Schema Validation Fix

File: src/config/n8n-api.ts (line 13)

Add the missing schema validation for N8N_CERT_PATH:

const n8nApiConfigSchema = z.object({
  N8N_API_URL: z.string().url().optional(),
  N8N_API_KEY: z.string().min(1).optional(),
  N8N_API_TIMEOUT: z.coerce.number().positive().default(30000),
  N8N_API_MAX_RETRIES: z.coerce.number().positive().default(3),
  N8N_CERT_PATH: z.string().optional(), // ✅ Add this line
});

🔧 TypeScript Interface Update

File: src/services/n8n-api-client.ts (line 34)

Update the interface to include the cert property:

export interface N8nApiClientConfig {
  baseUrl: string;
  apiKey: string;
  timeout?: number;
  maxRetries?: number;
  cert?: string; // ✅ Add this line
}

Suggested Improvements (Optional but Recommended)

Enhanced Error Handling

Consider improving the certificate loading error handling in src/config/n8n-api.ts:

if (config.N8N_CERT_PATH) {
  try {
    const certPath = path.resolve(config.N8N_CERT_PATH);
    
    // Check if file exists
    if (\!fs.existsSync(certPath)) {
      throw new Error(`Certificate file not found: ${certPath}`);
    }
    
    // Verify it's a file
    const stats = fs.statSync(certPath);
    if (\!stats.isFile()) {
      throw new Error(`Certificate path is not a file: ${certPath}`);
    }
    
    // Read certificate
    cert = fs.readFileSync(certPath, 'utf-8');
    
    // Basic PEM format validation
    if (\!cert.includes('-----BEGIN CERTIFICATE-----')) {
      throw new Error(`Invalid certificate format. Expected PEM format in: ${certPath}`);
    }
    
    logger.info(`Custom SSL certificate loaded from: ${certPath}`);
  } catch (error) {
    logger.error(`Failed to load certificate: ${error.message}`);
    throw error;
  }
}

Test Coverage

Adding tests would be valuable, especially for:

  • Certificate loading success/failure scenarios
  • Invalid certificate paths
  • Certificate format validation
  • HTTPS agent configuration

What Works Great ✅

  • Documentation: Excellent, comprehensive documentation across README, Docker, and deployment guides
  • Docker Integration: Well-thought-out compose examples with proper volume mounting
  • Backward Compatibility: Feature is optional and doesn't break existing setups
  • Path Handling: Good use of path.resolve() for cross-platform compatibility

Next Steps

Once you've made the critical fixes (especially removing rejectUnauthorized: false), this will be ready to merge. The security fix is the most important - it ensures that the certificate validation actually works as intended.

Feel free to ask if you need any clarification or help with these changes. Thanks again for your contribution! 🙏

@gifflet
Copy link
Author

gifflet commented Aug 8, 2025

@czlonkowski, the rejectUnauthorized: false line was removed. Also, the environment variable N8N_SKIP_SSL_VERIFICATION was introduced, which allows us to connect to an n8n instance without a configured certificate in a development environment.

@PyroFilmsFX
Copy link

why do you need to handle self signed certs when a certbot / lets encrypt is 100% free and a domain is 5-10$/year... i guess local hosted instances?

@gifflet
Copy link
Author

gifflet commented Sep 3, 2025

@PyroFilmsFX , depending on how a certificate is generated, we may need to add it to the whitelist — for example, due to a missing root certificate or certificate authority. If the user only has access to the application through a web browser, and not to the server or n8n configuration, it would be more convenient to simply add the n8n certificate to the whitelist to get the connection working.

@tchellomello
Copy link

@gifflet are you considering to extend this feature to also support mTLS?

@Catsofsuffering
Copy link

@czlonkowski When will this PR be merged into the main branch? I really need this feature, thanks a lot!!!

…fication skip

- Enhance SSL/TLS configuration with support for custom CA or self-signed certificates via N8N_CERT_PATH.
- Introduce N8N_SKIP_SSL_VERIFICATION environment variable to optionally disable SSL cert verification (for development only).
- Add detailed SSL/TLS troubleshooting guide documentation with common errors, fixes, and best practices.
- Update n8n API client to use custom cert and conditionally disable SSL verification with proper warnings.
- Improve logging to warn about insecure SSL skip usage.
@gifflet
Copy link
Author

gifflet commented Dec 8, 2025

@czlonkowski @Catsofsuffering Merge conflicts resolved. Ready for review!

@czlonkowski
Copy link
Owner

PR Review Summary

Thank you for this valuable contribution! Self-signed SSL certificate support is an important feature for enterprise deployments. After thorough review by both code and deployment reviewers, we've identified several issues that need to be addressed.


Critical Issues (Must Fix)

1. Duplicate path.resolve() Call

File: src/config/n8n-api.ts

// Current (problematic):
const certPath = path.resolve(config.N8N_CERT_PATH);
if (!fs.existsSync(certPath)) { ... }
cert = fs.readFileSync(path.resolve(config.N8N_CERT_PATH)); // ❌ Duplicate resolve

// Should be:
const certPath = path.resolve(config.N8N_CERT_PATH);
if (!fs.existsSync(certPath)) { ... }
cert = fs.readFileSync(certPath); // ✅ Use already-resolved path

2. Missing SSL Support in getN8nApiConfigFromContext()

File: src/config/n8n-api.ts

The context-based configuration function doesn't include the new SSL fields. This is critical because multi-tenant HTTP mode uses this function. Users configuring n8n instances dynamically won't be able to use SSL certificates.

// Need to add these fields to the context interface:
n8nCertPath?: string;
n8nSkipSslVerification?: boolean;

3. Git Merge Conflict Marker

File: docs/DOCKER_README.md (line 290)

There's a leftover merge conflict marker that must be resolved:

<<<<<<< HEAD

High Priority Issues

4. Low Test Coverage (34%)

Both source files have significant uncovered lines. Please add tests for:

  • Certificate loading success/failure scenarios
  • File not found errors
  • HTTPS agent creation with certificate
  • HTTPS agent creation with skipSslVerification

5. N8N_SKIP_SSL_VERIFICATION Allowed in Production

Security Concern: This should be blocked in production environments:

if (skipSslVerification) {
  if (process.env.NODE_ENV === 'production') {
    logger.error('N8N_SKIP_SSL_VERIFICATION is not allowed in production');
    throw new Error('SSL verification skip is disabled in production');
  }
  agentOptions.rejectUnauthorized = false;
}

Medium Priority (Recommended)

6. No File vs Directory Validation

fs.existsSync() returns true for directories. Add validation:

const stats = fs.statSync(certPath);
if (!stats.isFile()) {
  throw new Error(`Certificate path is not a file: ${certPath}`);
}

7. No Certificate Format Validation

Consider adding basic PEM format validation:

const certStr = cert.toString('utf-8');
if (!certStr.includes('-----BEGIN CERTIFICATE-----')) {
  logger.warn(`Certificate file may not be in PEM format: ${certPath}`);
}

Deployment Considerations

Concern Status
Docker volume mounting ✅ Correctly uses :ro flag
Kubernetes documentation ❌ Missing - please add Secret/ConfigMap examples
Certificate rotation ⚠️ Requires container restart - document this
File permissions check ❌ Consider warning if cert is world-readable

What Works Well 👍

  • ✅ Two-tier security model (cert path vs skip verification)
  • ✅ Appropriate warning logging when SSL disabled
  • ✅ HTTPS agent correctly shared across client, health check, and webhook
  • ✅ Excellent documentation (345-line troubleshooting guide!)
  • ✅ Fully backward compatible (opt-in only)
  • ✅ Docker examples with read-only volume flag

Summary

Status: Changes Requested

Please address:

  1. Fix duplicate path.resolve() call
  2. Add SSL support to getN8nApiConfigFromContext()
  3. Resolve merge conflict marker in docs
  4. Add unit tests (target 70%+ coverage)
  5. Block N8N_SKIP_SSL_VERIFICATION in production

The feature itself is well-designed and the documentation is excellent. Once these issues are fixed, this will be ready to merge!


Review conducted by code-reviewer and deployment-engineer agents

@pjaol
Copy link

pjaol commented Jan 6, 2026

Adding

"NODE_TLS_REJECT_UNAUTHORIZED": "0"

To the env in mcp config will allow self signed certs to work, no need for code changes, just update docs

e.g.

{
  "mcpServers": {
    "n8n-mcp": {
      "command": "npx",
      "args": ["n8n-mcp"],
      "env": {
        "MCP_MODE": "stdio",
        "LOG_LEVEL": "error",
        "DISABLE_CONSOLE_OUTPUT": "true",
        "N8N_API_URL": "https://yyyyyy.home.arpa",
        "N8N_API_KEY": "xxxxxx",
        "NODE_TLS_REJECT_UNAUTHORIZED": "0"
      }
    }
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants