This commit is contained in:
Samuel 2025-06-18 10:44:00 +00:00
commit 2b9cb0a254
12 changed files with 433 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/n8n*

66
build.sh Executable file
View File

@ -0,0 +1,66 @@
#!/bin/bash
VERSION=1.98.1
REPO_DIR="n8n-$VERSION"
if [ -d "$REPO_DIR" ]; then
echo "---- Removing old directory of $VERSION ----"
rm -Rf $REPO_DIR
fi
echo "---- Cloning n8n for version $VERSION ----"
git -c advice.detachedHead=false clone --depth 1 --branch "n8n@$VERSION" --single-branch https://github.com/n8n-io/n8n.git $REPO_DIR
echo "---- Verifying patches for $VERSION ----"
cd $REPO_DIR
PATCH_VERSION=$VERSION
if [ ! -d "../patches/$PATCH_VERSION/" ]; then
echo " Direct patches for $PATCH_VERSION couldn't be found trying default patches"
PATCH_VERSION="default"
fi
has_patch_error=0
for patch_filename in ../patches/$PATCH_VERSION/*.patch; do
git apply --check $patch_filename;
if [ $? -eq 0 ]; then
echo " - Dryrun for \"$patch_filename\" successful"
else
echo " - Dryrun for \"$patch_filename\" was unsuccessful, please check the patch file"
has_patch_error=1
fi
done
if [ $has_patch_error -ne 0 ]; then
echo " Found error while patching. Exiting"
exit 1
fi
for patch_filename in ../patches/$PATCH_VERSION/*.patch; do
echo " - Applying \"$patch_filename\""
git apply --whitespace=nowarn $patch_filename;
done
echo "---- Building base image for $VERSION ----"
docker image rm n8n-license-patched-base:22 2>/dev/null
docker build -t n8n-license-patched-base:22 -f docker/images/n8n-base/Dockerfile .
if [ $? -ne 0 ]; then
echo "Build unsuccessful. Exiting"
fi
echo "---- Patching and building main image for $VERSION ----"
sed -i 's/n8nio\/base/n8n-license-patched-base/g' docker/images/n8n/Dockerfile
if [ $? -ne 0 ]; then
echo "Base image tag patch unsuccessful. Exiting"
fi
docker image rm n8n-license-patched:$VERSION 2>/dev/null
docker build -t n8n-license-patched:$VERSION -f docker/images/n8n/Dockerfile .
if [ $? -ne 0 ]; then
echo "Build unsuccessful. Exiting"
fi

View File

@ -0,0 +1,28 @@
diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts
index bea302dbb..394e12a28 100644
--- a/packages/@n8n/config/test/config.test.ts
+++ b/packages/@n8n/config/test/config.test.ts
@@ -263,7 +263,7 @@ describe('GlobalConfig', () => {
gracefulShutdownTimeout: 30,
},
license: {
- serverUrl: 'https://license.n8n.io/v1',
+ serverUrl: 'https://0.0.0.0',
autoRenewalEnabled: true,
detachFloatingOnShutdown: true,
activationKey: '',
@@ -289,11 +289,11 @@ describe('GlobalConfig', () => {
},
diagnostics: {
enabled: true,
- frontendConfig: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io',
- backendConfig: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io',
+ frontendConfig: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://0.0.0.0',
+ backendConfig: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://0.0.0.0',
posthogConfig: {
apiKey: 'phc_4URIAm1uYfJO7j8kWSe0J8lc8IqnstRLS7Jx8NcakHo',
- apiHost: 'https://ph.n8n.io',
+ apiHost: 'https://0.0.0.0',
},
},
aiAssistant: {

View File

@ -0,0 +1,31 @@
diff --git a/packages/@n8n/config/src/configs/diagnostics.config.ts b/packages/@n8n/config/src/configs/diagnostics.config.ts
index 5ff6abf83..c89777372 100644
--- a/packages/@n8n/config/src/configs/diagnostics.config.ts
+++ b/packages/@n8n/config/src/configs/diagnostics.config.ts
@@ -8,22 +8,22 @@ class PostHogConfig {
/** API host for PostHog. */
@Env('N8N_DIAGNOSTICS_POSTHOG_API_HOST')
- apiHost: string = 'https://ph.n8n.io';
+ apiHost: string = 'https://0.0.0.0';
}
@Config
export class DiagnosticsConfig {
/** Whether diagnostics are enabled. */
@Env('N8N_DIAGNOSTICS_ENABLED')
- enabled: boolean = true;
+ enabled: boolean = false;
/** Diagnostics config for frontend. */
@Env('N8N_DIAGNOSTICS_CONFIG_FRONTEND')
- frontendConfig: string = '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io';
+ frontendConfig: string = '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://0.0.0.0';
/** Diagnostics config for backend. */
@Env('N8N_DIAGNOSTICS_CONFIG_BACKEND')
- backendConfig: string = '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io';
+ backendConfig: string = '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://0.0.0.0';
@Nested
posthogConfig: PostHogConfig;

View File

@ -0,0 +1,40 @@
diff --git a/packages/@n8n/backend-common/src/license-state.ts b/packages/@n8n/backend-common/src/license-state.ts
index b2ad56f84..4db90066e 100644
--- a/packages/@n8n/backend-common/src/license-state.ts
+++ b/packages/@n8n/backend-common/src/license-state.ts
@@ -4,6 +4,8 @@ import { UnexpectedError } from 'n8n-workflow';
import type { FeatureReturnType, LicenseProvider } from './types';
+import { LICENSE_FEATURES, LICENSE_QUOTAS } from '@n8n/constants';
+
class ProviderNotSetError extends UnexpectedError {
constructor() {
super('Cannot query license state because license provider has not been set');
@@ -27,15 +29,20 @@ export class LicenseState {
// --------------------
isLicensed(feature: BooleanLicenseFeature) {
- this.assertProvider();
-
- return this.licenseProvider.isLicensed(feature);
+ if(feature == "feat:showNonProdBanner") { return false; }
+ if(feature == "feat:apiDisabled") { return false; }
+ return true;
}
getValue<T extends keyof FeatureReturnType>(feature: T): FeatureReturnType[T] {
- this.assertProvider();
-
- return this.licenseProvider.getValue(feature);
+ if(feature == "planName") { return "PatchedLicenseCheck" as FeatureReturnType[T]; }
+ if(feature in LICENSE_FEATURES || feature.startsWith("feat:")) {
+ return this.isLicensed(feature as BooleanLicenseFeature) as FeatureReturnType[T];
+ }
+ if(feature in LICENSE_QUOTAS || feature.startsWith("quota:")) {
+ return UNLIMITED_LICENSE_QUOTA as FeatureReturnType[T];
+ }
+ return undefined;
}
// --------------------

View File

@ -0,0 +1,18 @@
diff --git a/packages/@n8n/config/src/configs/license.config.ts b/packages/@n8n/config/src/configs/license.config.ts
index 005b5f5dc..b513fb6a2 100644
--- a/packages/@n8n/config/src/configs/license.config.ts
+++ b/packages/@n8n/config/src/configs/license.config.ts
@@ -4,11 +4,11 @@ import { Config, Env } from '../decorators';
export class LicenseConfig {
/** License server URL to retrieve license. */
@Env('N8N_LICENSE_SERVER_URL')
- serverUrl: string = 'https://license.n8n.io/v1';
+ serverUrl: string = 'https://0.0.0.0/';
/** Whether autorenewal for licenses is enabled. */
@Env('N8N_LICENSE_AUTO_RENEW_ENABLED')
- autoRenewalEnabled: boolean = true;
+ autoRenewalEnabled: boolean = false;
/** Activation key to initialize license. */
@Env('N8N_LICENSE_ACTIVATION_KEY')

View File

@ -0,0 +1,66 @@
diff --git a/packages/cli/src/license.ts b/packages/cli/src/license.ts
index eec82fe9e..2dd0429e3 100644
--- a/packages/cli/src/license.ts
+++ b/packages/cli/src/license.ts
@@ -89,34 +89,6 @@ export class License implements LicenseProvider {
this.logger.warn(LICENSE_RENEWAL_DISABLED_WARNING);
}
- try {
- this.manager = new LicenseManager({
- server,
- tenantId: this.globalConfig.license.tenantId,
- productIdentifier: `n8n-${N8N_VERSION}`,
- autoRenewEnabled: shouldRenew,
- renewOnInit: shouldRenew,
- autoRenewOffset,
- detachFloatingOnShutdown: this.globalConfig.license.detachFloatingOnShutdown,
- offlineMode,
- logger: this.logger,
- loadCertStr: async () => await this.loadCertStr(),
- saveCertStr,
- deviceFingerprint: () => this.instanceSettings.instanceId,
- collectUsageMetrics,
- collectPassthroughData,
- onFeatureChange,
- onLicenseRenewed,
- });
-
- await this.manager.initialize();
-
- this.logger.debug('License initialized');
- } catch (error: unknown) {
- if (error instanceof Error) {
- this.logger.error('Could not initialize license manager sdk', { error });
- }
- }
}
async loadCertStr(): Promise<TLicenseBlock> {
@@ -213,7 +185,9 @@ export class License implements LicenseProvider {
}
isLicensed(feature: BooleanLicenseFeature) {
- return this.manager?.hasFeatureEnabled(feature) ?? false;
+ if(feature == "feat:showNonProdBanner") { return false; }
+ if(feature == "feat:apiDisabled") { return false; }
+ return true;
}
/** @deprecated Use `LicenseState.isSharingLicensed` instead. */
@@ -341,7 +315,14 @@ export class License implements LicenseProvider {
}
getValue<T extends keyof FeatureReturnType>(feature: T): FeatureReturnType[T] {
- return this.manager?.getFeatureValue(feature) as FeatureReturnType[T];
+ if(feature == "planName") { return "PatchedLicenseCheck" as FeatureReturnType[T]; }
+ if(feature in LICENSE_FEATURES || feature.startsWith("feat:")) {
+ return this.isLicensed(feature as BooleanLicenseFeature) as FeatureReturnType[T];
+ }
+ if(feature in LICENSE_QUOTAS || feature.startsWith("quota:")) {
+ return UNLIMITED_LICENSE_QUOTA as FeatureReturnType[T];
+ }
+ return undefined;
}
getManagementJwt(): string {

View File

@ -0,0 +1,28 @@
diff --git a/packages/@n8n/config/test/config.test.ts b/packages/@n8n/config/test/config.test.ts
index bea302dbb..394e12a28 100644
--- a/packages/@n8n/config/test/config.test.ts
+++ b/packages/@n8n/config/test/config.test.ts
@@ -263,7 +263,7 @@ describe('GlobalConfig', () => {
gracefulShutdownTimeout: 30,
},
license: {
- serverUrl: 'https://license.n8n.io/v1',
+ serverUrl: 'https://0.0.0.0',
autoRenewalEnabled: true,
detachFloatingOnShutdown: true,
activationKey: '',
@@ -289,11 +289,11 @@ describe('GlobalConfig', () => {
},
diagnostics: {
enabled: true,
- frontendConfig: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io',
- backendConfig: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io',
+ frontendConfig: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://0.0.0.0',
+ backendConfig: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://0.0.0.0',
posthogConfig: {
apiKey: 'phc_4URIAm1uYfJO7j8kWSe0J8lc8IqnstRLS7Jx8NcakHo',
- apiHost: 'https://ph.n8n.io',
+ apiHost: 'https://0.0.0.0',
},
},
aiAssistant: {

View File

@ -0,0 +1,31 @@
diff --git a/packages/@n8n/config/src/configs/diagnostics.config.ts b/packages/@n8n/config/src/configs/diagnostics.config.ts
index 5ff6abf83..c89777372 100644
--- a/packages/@n8n/config/src/configs/diagnostics.config.ts
+++ b/packages/@n8n/config/src/configs/diagnostics.config.ts
@@ -8,22 +8,22 @@ class PostHogConfig {
/** API host for PostHog. */
@Env('N8N_DIAGNOSTICS_POSTHOG_API_HOST')
- apiHost: string = 'https://ph.n8n.io';
+ apiHost: string = 'https://0.0.0.0';
}
@Config
export class DiagnosticsConfig {
/** Whether diagnostics are enabled. */
@Env('N8N_DIAGNOSTICS_ENABLED')
- enabled: boolean = true;
+ enabled: boolean = false;
/** Diagnostics config for frontend. */
@Env('N8N_DIAGNOSTICS_CONFIG_FRONTEND')
- frontendConfig: string = '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io';
+ frontendConfig: string = '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://0.0.0.0';
/** Diagnostics config for backend. */
@Env('N8N_DIAGNOSTICS_CONFIG_BACKEND')
- backendConfig: string = '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io';
+ backendConfig: string = '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://0.0.0.0';
@Nested
posthogConfig: PostHogConfig;

View File

@ -0,0 +1,40 @@
diff --git a/packages/@n8n/backend-common/src/license-state.ts b/packages/@n8n/backend-common/src/license-state.ts
index b2ad56f84..4db90066e 100644
--- a/packages/@n8n/backend-common/src/license-state.ts
+++ b/packages/@n8n/backend-common/src/license-state.ts
@@ -4,6 +4,8 @@ import { UnexpectedError } from 'n8n-workflow';
import type { FeatureReturnType, LicenseProvider } from './types';
+import { LICENSE_FEATURES, LICENSE_QUOTAS } from '@n8n/constants';
+
class ProviderNotSetError extends UnexpectedError {
constructor() {
super('Cannot query license state because license provider has not been set');
@@ -27,15 +29,20 @@ export class LicenseState {
// --------------------
isLicensed(feature: BooleanLicenseFeature) {
- this.assertProvider();
-
- return this.licenseProvider.isLicensed(feature);
+ if(feature == "feat:showNonProdBanner") { return false; }
+ if(feature == "feat:apiDisabled") { return false; }
+ return true;
}
getValue<T extends keyof FeatureReturnType>(feature: T): FeatureReturnType[T] {
- this.assertProvider();
-
- return this.licenseProvider.getValue(feature);
+ if(feature == "planName") { return "PatchedLicenseCheck" as FeatureReturnType[T]; }
+ if(feature in LICENSE_FEATURES || feature.startsWith("feat:")) {
+ return this.isLicensed(feature as BooleanLicenseFeature) as FeatureReturnType[T];
+ }
+ if(feature in LICENSE_QUOTAS || feature.startsWith("quota:")) {
+ return UNLIMITED_LICENSE_QUOTA as FeatureReturnType[T];
+ }
+ return undefined;
}
// --------------------

View File

@ -0,0 +1,18 @@
diff --git a/packages/@n8n/config/src/configs/license.config.ts b/packages/@n8n/config/src/configs/license.config.ts
index 005b5f5dc..b513fb6a2 100644
--- a/packages/@n8n/config/src/configs/license.config.ts
+++ b/packages/@n8n/config/src/configs/license.config.ts
@@ -4,11 +4,11 @@ import { Config, Env } from '../decorators';
export class LicenseConfig {
/** License server URL to retrieve license. */
@Env('N8N_LICENSE_SERVER_URL')
- serverUrl: string = 'https://license.n8n.io/v1';
+ serverUrl: string = 'https://0.0.0.0/';
/** Whether autorenewal for licenses is enabled. */
@Env('N8N_LICENSE_AUTO_RENEW_ENABLED')
- autoRenewalEnabled: boolean = true;
+ autoRenewalEnabled: boolean = false;
/** Activation key to initialize license. */
@Env('N8N_LICENSE_ACTIVATION_KEY')

View File

@ -0,0 +1,66 @@
diff --git a/packages/cli/src/license.ts b/packages/cli/src/license.ts
index eec82fe9e..2dd0429e3 100644
--- a/packages/cli/src/license.ts
+++ b/packages/cli/src/license.ts
@@ -89,34 +89,6 @@ export class License implements LicenseProvider {
this.logger.warn(LICENSE_RENEWAL_DISABLED_WARNING);
}
- try {
- this.manager = new LicenseManager({
- server,
- tenantId: this.globalConfig.license.tenantId,
- productIdentifier: `n8n-${N8N_VERSION}`,
- autoRenewEnabled: shouldRenew,
- renewOnInit: shouldRenew,
- autoRenewOffset,
- detachFloatingOnShutdown: this.globalConfig.license.detachFloatingOnShutdown,
- offlineMode,
- logger: this.logger,
- loadCertStr: async () => await this.loadCertStr(),
- saveCertStr,
- deviceFingerprint: () => this.instanceSettings.instanceId,
- collectUsageMetrics,
- collectPassthroughData,
- onFeatureChange,
- onLicenseRenewed,
- });
-
- await this.manager.initialize();
-
- this.logger.debug('License initialized');
- } catch (error: unknown) {
- if (error instanceof Error) {
- this.logger.error('Could not initialize license manager sdk', { error });
- }
- }
}
async loadCertStr(): Promise<TLicenseBlock> {
@@ -213,7 +185,9 @@ export class License implements LicenseProvider {
}
isLicensed(feature: BooleanLicenseFeature) {
- return this.manager?.hasFeatureEnabled(feature) ?? false;
+ if(feature == "feat:showNonProdBanner") { return false; }
+ if(feature == "feat:apiDisabled") { return false; }
+ return true;
}
/** @deprecated Use `LicenseState.isSharingLicensed` instead. */
@@ -341,7 +315,14 @@ export class License implements LicenseProvider {
}
getValue<T extends keyof FeatureReturnType>(feature: T): FeatureReturnType[T] {
- return this.manager?.getFeatureValue(feature) as FeatureReturnType[T];
+ if(feature == "planName") { return "PatchedLicenseCheck" as FeatureReturnType[T]; }
+ if(feature in LICENSE_FEATURES || feature.startsWith("feat:")) {
+ return this.isLicensed(feature as BooleanLicenseFeature) as FeatureReturnType[T];
+ }
+ if(feature in LICENSE_QUOTAS || feature.startsWith("quota:")) {
+ return UNLIMITED_LICENSE_QUOTA as FeatureReturnType[T];
+ }
+ return undefined;
}
getManagementJwt(): string {