n8n / Dockerfile
keflag's picture
Update Dockerfile
1a073c7 verified
FROM n8nio/n8n:latest
USER root
# ==============================
# 1. 覆盖 license-state.js(你提供的原版 + 全功能解锁)
# ==============================
RUN cat > /usr/local/lib/node_modules/n8n/node_modules/@n8n/backend-common/dist/license-state.js <<'EOF'
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LicenseState = void 0;
const constants_1 = require("@n8n/constants");
const di_1 = require("@n8n/di");
const n8n_workflow_1 = require("n8n-workflow");
class ProviderNotSetError extends n8n_workflow_1.UnexpectedError {
constructor() {
super('Cannot query license state because license provider has not been set');
}
}
let LicenseState = class LicenseState {
constructor() {
this.licenseProvider = null;
}
setLicenseProvider(provider) { this.licenseProvider = provider; }
assertProvider() {}
isLicensed(feature) { return true; }
getValue(feature) { return 99999999; }
isCustomRolesLicensed() { return true; }
isDynamicCredentialsLicensed() { return true; }
isPersonalSpacePolicyLicensed() { return true; }
isSharingLicensed() { return true; }
isLogStreamingLicensed() { return true; }
isLdapLicensed() { return true; }
isSamlLicensed() { return true; }
isOidcLicensed() { return true; }
isMFAEnforcementLicensed() { return true; }
isApiKeyScopesLicensed() { return true; }
isAiAssistantLicensed() { return true; }
isAskAiLicensed() { return true; }
isAiCreditsLicensed() { return true; }
isAdvancedExecutionFiltersLicensed() { return true; }
isAdvancedPermissionsLicensed() { return true; }
isDebugInEditorLicensed() { return true; }
isBinaryDataS3Licensed() { return true; }
isMultiMainLicensed() { return true; }
isVariablesLicensed() { return true; }
isSourceControlLicensed() { return true; }
isExternalSecretsLicensed() { return true; }
isAPIDisabled() { return false; }
isWorkerViewLicensed() { return true; }
isProjectRoleAdminLicensed() { return true; }
isProjectRoleEditorLicensed() { return true; }
isProjectRoleViewerLicensed() { return true; }
isCustomNpmRegistryLicensed() { return true; }
isFoldersLicensed() { return true; }
isInsightsSummaryLicensed() { return true; }
isInsightsDashboardLicensed() { return true; }
isInsightsHourlyDataLicensed() { return true; }
isWorkflowDiffsLicensed() { return true; }
isDataRedactionLicensed() { return true; }
isProvisioningLicensed() { return true; }
getMaxUsers() { return 99999999; }
getMaxActiveWorkflows() { return 99999999; }
getMaxVariables() { return 99999999; }
getMaxAiCredits() { return 99999999; }
getWorkflowHistoryPruneQuota() { return 99999999; }
getInsightsMaxHistory() { return 3650; }
getInsightsRetentionMaxAge() { return 3650; }
getInsightsRetentionPruneInterval() { return 1; }
getMaxTeamProjects() { return 99999999; }
getMaxWorkflowsWithEvaluations() { return 99999999; }
};
exports.LicenseState = LicenseState;
exports.LicenseState = LicenseState = __decorate([
(0, di_1.Service)()
], LicenseState);
EOF
# ==============================
# 2. 覆盖 license.js(你提供的原版 + 只改一行 isLicensed 永久返回 true
# ==============================
RUN cat > /usr/local/lib/node_modules/n8n/dist/license.js <<'EOF'
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.License = void 0;
const backend_common_1 = require("@n8n/backend-common");
const config_1 = require("@n8n/config");
const constants_1 = require("@n8n/constants");
const db_1 = require("@n8n/db");
const decorators_1 = require("@n8n/decorators");
const di_1 = require("@n8n/di");
const license_sdk_1 = require("@n8n_io/license-sdk");
const n8n_core_1 = require("n8n-core");
const license_metrics_service_1 = require("./metrics/license-metrics.service");
const constants_2 = require("./constants");
const LICENSE_RENEWAL_DISABLED_WARNING = 'Automatic license renewal is disabled. The license will not renew automatically, and access to licensed features may be lost!';
let License = class License {
constructor(logger, instanceSettings, settingsRepository, licenseMetricsService, globalConfig) {
this.logger = logger;
this.instanceSettings = instanceSettings;
this.settingsRepository = settingsRepository;
this.licenseMetricsService = licenseMetricsService;
this.globalConfig = globalConfig;
this.isShuttingDown = false;
this.refreshCallbacks = [];
this.logger = this.logger.scoped('license');
}
async init({ forceRecreate = false, isCli = false, } = {}) {
if (this.manager && !forceRecreate) {
this.logger.warn('License manager already initialized or shutting down');
return;
}
if (this.isShuttingDown) {
this.logger.warn('License manager already shutting down');
return;
}
const { instanceType } = this.instanceSettings;
const isMainInstance = instanceType === 'main';
const server = this.globalConfig.license.serverUrl;
const offlineMode = !isMainInstance;
const autoRenewOffset = 72 * constants_1.Time.hours.toSeconds;
const saveCertStr = isMainInstance
? async (value) => await this.saveCertStr(value)
: async () => { };
const onFeatureChange = isMainInstance
? async () => await this.onFeatureChange()
: async () => { };
const onLicenseRenewed = isMainInstance
? async () => await this.onLicenseRenewed()
: async () => { };
const collectUsageMetrics = isMainInstance
? async () => await this.licenseMetricsService.collectUsageMetrics()
: async () => [];
const collectPassthroughData = isMainInstance
? async () => await this.licenseMetricsService.collectPassthroughData()
: async () => ({});
const onExpirySoon = !this.instanceSettings.isLeader ? () => this.onExpirySoon() : undefined;
const expirySoonOffsetMins = !this.instanceSettings.isLeader ? 120 : undefined;
const { isLeader } = this.instanceSettings;
const { autoRenewalEnabled } = this.globalConfig.license;
const eligibleToRenew = isCli || isLeader;
const shouldRenew = eligibleToRenew && autoRenewalEnabled;
if (eligibleToRenew && !autoRenewalEnabled) {
this.logger.warn(LICENSE_RENEWAL_DISABLED_WARNING);
}
try {
this.manager = new license_sdk_1.LicenseManager({
server,
tenantId: this.globalConfig.license.tenantId,
productIdentifier: `n8n-${constants_2.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,
onExpirySoon,
expirySoonOffsetMins,
});
await this.manager.initialize();
this.logger.debug('License initialized');
}
catch (error) {
if (error instanceof Error) {
this.logger.error('Could not initialize license manager sdk', { error });
}
}
}
async loadCertStr() {
const ephemeralLicense = this.globalConfig.license.cert;
if (ephemeralLicense) {
return ephemeralLicense;
}
const databaseSettings = await this.settingsRepository.findOne({
where: {
key: constants_2.SETTINGS_LICENSE_CERT_KEY,
},
});
return databaseSettings?.value ?? '';
}
async onFeatureChange() {
void this.broadcastReloadLicenseCommand();
await this.notifyRefreshCallbacks();
}
async onLicenseRenewed() {
void this.broadcastReloadLicenseCommand();
await this.notifyRefreshCallbacks();
}
async broadcastReloadLicenseCommand() {
if (this.globalConfig.executions.mode === 'queue' && this.instanceSettings.isLeader) {
const { Publisher } = await Promise.resolve().then(() => __importStar(require('./scaling/pubsub/publisher.service')));
await di_1.Container.get(Publisher).publishCommand({ command: 'reload-license' });
}
}
async saveCertStr(value) {
if (this.globalConfig.license.cert)
return;
await this.settingsRepository.upsert({
key: constants_2.SETTINGS_LICENSE_CERT_KEY,
value,
loadOnStartup: false,
}, ['key']);
}
onCertRefresh(refreshCallback) {
this.refreshCallbacks.push(refreshCallback);
return () => {
const index = this.refreshCallbacks.indexOf(refreshCallback);
if (index > -1) {
this.refreshCallbacks.splice(index, 1);
}
};
}
async notifyRefreshCallbacks() {
const cert = await this.loadCertStr();
for (const refreshCallback of this.refreshCallbacks) {
try {
refreshCallback(cert);
}
catch (error) {
this.logger.error('Error in license refresh callback', { error });
}
}
}
async activate(activationKey, eulaUri, userEmail) {
if (!this.manager) {
return;
}
await this.manager.activate(activationKey, { eulaUri, email: userEmail });
this.logger.debug('License activated');
}
async reload() {
if (!this.manager) {
return;
}
await this.manager.reload();
await this.notifyRefreshCallbacks();
this.logger.debug('License reloaded');
}
async renew() {
if (!this.manager) {
return;
}
await this.manager.renew();
this.logger.debug('License renewed');
}
async clear() {
if (!this.manager) {
return;
}
await this.manager.clear();
this.logger.info('License cleared');
}
async shutdown() {
this.isShuttingDown = true;
if (!this.manager) {
return;
}
await this.manager.shutdown();
this.logger.debug('License shut down');
}
isLicensed(feature) { return true; }
isDynamicCredentialsEnabled() { return true; }
isSharingEnabled() { return true; }
isLogStreamingEnabled() { return true; }
isLdapEnabled() { return true; }
isSamlEnabled() { return true; }
isAiAssistantEnabled() { return true; }
isAskAiEnabled() { return true; }
isAiCreditsEnabled() { return true; }
isAdvancedExecutionFiltersEnabled() { return true; }
isAdvancedPermissionsLicensed() { return true; }
isDebugInEditorLicensed() { return true; }
isBinaryDataS3Licensed() { return true; }
isMultiMainLicensed() { return true; }
isVariablesEnabled() { return true; }
isSourceControlLicensed() { return true; }
isExternalSecretsEnabled() { return true; }
isAPIDisabled() { return false; }
isWorkerViewLicensed() { return true; }
isProjectRoleAdminLicensed() { return true; }
isProjectRoleEditorLicensed() { return true; }
isProjectRoleViewerLicensed() { return true; }
isCustomNpmRegistryEnabled() { return true; }
isFoldersEnabled() { return true; }
getCurrentEntitlements() { return this.manager?.getCurrentEntitlements() ?? []; }
getValue(feature) { return 99999999; }
getManagementJwt() { return this.manager?.getManagementJwt() ?? ''; }
getMainPlan() {
if (!this.manager) return undefined;
const entitlements = this.getCurrentEntitlements();
if (!entitlements.length) return undefined;
entitlements.sort((a, b) => b.validFrom.getTime() - a.validFrom.getTime());
return entitlements.find((entitlement) => entitlement.productMetadata?.terms?.isMainPlan);
}
getConsumerId() { return this.manager?.getConsumerId() ?? 'unknown'; }
getUsersLimit() { return 99999999; }
getTriggerLimit() { return 99999999; }
getVariablesLimit() { return 99999999; }
getAiCredits() { return 99999999; }
getWorkflowHistoryPruneLimit() { return 99999999; }
getTeamProjectLimit() { return 99999999; }
getPlanName() { return "Enterprise"; }
getExpiryDate() { return new Date('3099-12-31'); }
getTerminationDate() { return new Date('3099-12-31'); }
getExpiringInDays() { return 36500; }
getTerminatingInDays() { return 36500; }
getInfo() { return 'Enterprise License (Unlimited)'; }
isWithinUsersLimit() { return true; }
enableAutoRenewals() {}
disableAutoRenewals() {}
onExpirySoon() {}
};
exports.License = License;
__decorate([
(0, decorators_1.OnPubSubEvent)('reload-license'),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], License.prototype, "reload", null);
__decorate([
(0, decorators_1.OnShutdown)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], License.prototype, "shutdown", null);
__decorate([
(0, decorators_1.OnLeaderTakeover)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], License.prototype, "enableAutoRenewals", null);
__decorate([
(0, decorators_1.OnLeaderStepdown)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], License.prototype, "disableAutoRenewals", null);
exports.License = License = __decorate([
(0, di_1.Service)(),
__metadata("design:paramtypes", [backend_common_1.Logger,
n8n_core_1.InstanceSettings,
db_1.SettingsRepository,
license_metrics_service_1.LicenseMetricsService,
config_1.GlobalConfig])
], License);
EOF
# ==============================
# 启动 n8n
# ==============================
USER node