* @author timm2k <timm2k@gmx.de>
* @author Timo Förster <tfoerster@webfoersterei.de>
* @author Valdnet <47037905+Valdnet@users.noreply.github.com>
+ * @author MichaIng <micha@dietpi.com>
*
* @license AGPL-3.0
*
}
/**
- * Check if the used SSL lib is outdated. Older OpenSSL and NSS versions do
+ * Check if the used SSL lib is outdated. Older OpenSSL and NSS versions do
* have multiple bugs which likely lead to problems in combination with
* functionality required by ownCloud such as SNI.
*
}
/**
- * Checks whether a PHP opcache is properly set up
- * @return bool
+ * Checks whether a PHP OPcache is properly set up
+ * @return string[] The list of OPcache setup recommendations
*/
- protected function isOpcacheProperlySetup() {
- if (!$this->iniGetWrapper->getBool('opcache.enable')) {
- return false;
+ protected function getOpcacheSetupRecommendations(): array {
+ // If the module is not loaded, return directly to skip inapplicable checks
+ if (!extension_loaded('Zend OPcache')) {
+ return ['The PHP OPcache module is not loaded. <a target="_blank" rel="noreferrer noopener" class="external" href="' . $this->urlGenerator->linkToDocs('admin-php-opcache') . '">For better performance it is recommended</a> to load it into your PHP installation.'];
}
- if (!$this->iniGetWrapper->getBool('opcache.save_comments')) {
- return false;
- }
+ $recommendations = [];
- if ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') < 10000) {
- return false;
+ // Check whether Nextcloud is allowed to use the OPcache API
+ $isPermitted = true;
+ $permittedPath = $this->iniGetWrapper->getString('opcache.restrict_api');
+ if (isset($permittedPath) && $permittedPath !== '' && !str_starts_with(\OC::$SERVERROOT, $permittedPath)) {
+ $isPermitted = false;
}
- if ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') < 128) {
- return false;
- }
+ if (!$this->iniGetWrapper->getBool('opcache.enable')) {
+ $recommendations[] = 'OPcache is disabled. For better performance, it is recommended to apply <code>opcache.enable=1</code> to your PHP configuration.';
- if ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') < 8) {
- return false;
+ // Check for saved comments only when OPcache is currently disabled. If it was enabled, opcache.save_comments=0 would break Nextcloud in the first place.
+ if (!$this->iniGetWrapper->getBool('opcache.save_comments')) {
+ $recommendations[] = 'OPcache is configured to remove code comments. With OPcache enabled, <code>opcache.save_comments=1</code> must be set for Nextcloud to function.';
+ }
+
+ if (!$isPermitted) {
+ $recommendations[] = 'Nextcloud is not allowed to use the OPcache API. With OPcache enabled, it is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades.';
+ }
+ } elseif (!$isPermitted) {
+ $recommendations[] = 'Nextcloud is not allowed to use the OPcache API. It is highly recommended to include all Nextcloud directories with <code>opcache.restrict_api</code> or unset this setting to disable OPcache API restrictions, to prevent errors during Nextcloud core or app upgrades.';
+ } else {
+ // Check whether opcache_get_status has been explicitly disabled an in case skip usage based checks
+ $disabledFunctions = $this->iniGetWrapper->getString('disable_functions');
+ if (isset($disabledFunctions) && str_contains($disabledFunctions, 'opcache_get_status')) {
+ return [];
+ }
+
+ $status = opcache_get_status(false);
+
+ // Recommend to raise value, if more than 90% of max value is reached
+ if ($status['opcache_statistics']['num_cached_keys'] / $status['opcache_statistics']['max_cached_keys'] > 0.9) {
+ $recommendations[] = 'The maximum number of OPcache keys is nearly exceeded. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.max_accelerated_files</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.max_accelerated_files') ?: 'currently') . '</code>.';
+ }
+
+ if ($status['memory_usage']['used_memory'] / $status['memory_usage']['free_memory'] > 9) {
+ $recommendations[] = 'The OPcache buffer is nearly full. To assure that all scripts can be hold in cache, it is recommended to apply <code>opcache.memory_consumption</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.memory_consumption') ?: 'currently') . '</code>.';
+ }
+
+ if ($status['interned_strings_usage']['used_memory'] / $status['interned_strings_usage']['free_memory'] > 9) {
+ $recommendations[] = 'The OPcache interned strings buffer is nearly full. To assure that repeating strings can be effectively cached, it is recommended to apply <code>opcache.interned_strings_buffer</code> to your PHP configuration with a value higher than <code>' . ($this->iniGetWrapper->getNumeric('opcache.interned_strings_buffer') ?: 'currently') . '</code>.';
+ }
}
- return true;
+ return $recommendations;
}
/**
return [];
}
- protected function hasOpcacheLoaded(): bool {
- return extension_loaded('Zend OPcache');
- }
-
private function isTemporaryDirectoryWritable(): bool {
try {
if (!empty($this->tempManager->getTempBaseDir())) {
'isCorrectMemcachedPHPModuleInstalled' => $this->isCorrectMemcachedPHPModuleInstalled(),
'hasPassedCodeIntegrityCheck' => $this->checker->hasPassedCheck(),
'codeIntegrityCheckerDocumentation' => $this->urlGenerator->linkToDocs('admin-code-integrity'),
- 'isOpcacheProperlySetup' => $this->isOpcacheProperlySetup(),
- 'hasOpcacheLoaded' => $this->hasOpcacheLoaded(),
- 'phpOpcacheDocumentation' => $this->urlGenerator->linkToDocs('admin-php-opcache'),
+ 'OpcacheSetupRecommendations' => $this->getOpcacheSetupRecommendations(),
'isSettimelimitAvailable' => $this->isSettimelimitAvailable(),
'hasFreeTypeSupport' => $this->hasFreeTypeSupport(),
'missingPrimaryKeys' => $this->hasMissingPrimaryKeys(),
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: false,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: false,
hasFreeTypeSupport: true,
missingIndexes: [],
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
phpSupported: {eol: true, version: '5.4.0'},
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: false,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: ['recommendation1', 'recommendation2'],
phpOpcacheDocumentation: 'https://example.org/link/to/doc',
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
async.done(function( data, s, x ){
expect(data).toEqual([{
- msg: 'The PHP OPcache module is not properly configured. <a target="_blank" rel="noreferrer noopener" class="external" href="https://example.org/link/to/doc">For better performance it is recommended ↗</a> to use the following settings in the <code>php.ini</code>:' + "<pre><code>opcache.enable=1\nopcache.interned_strings_buffer=8\nopcache.max_accelerated_files=10000\nopcache.memory_consumption=128\nopcache.save_comments=1\nopcache.revalidate_freq=1</code></pre>",
- type: OC.SetupChecks.MESSAGE_TYPE_INFO
- }]);
- done();
- });
- });
-
- it('should return an info if server has no opcache at all', function(done) {
- var async = OC.SetupChecks.checkSetup();
-
- suite.server.requests[0].respond(
- 200,
- {
- 'Content-Type': 'application/json'
- },
- JSON.stringify({
- hasFileinfoInstalled: true,
- isGetenvServerWorking: true,
- isReadOnlyConfig: false,
- hasWorkingFileLocking: true,
- hasValidTransactionIsolationLevel: true,
- suggestedOverwriteCliURL: '',
- isRandomnessSecure: true,
- securityDocs: 'https://docs.nextcloud.com/myDocs.html',
- isFairUseOfFreePushService: true,
- serverHasInternetConnectionProblems: false,
- isMemcacheConfigured: true,
- forwardedForHeadersWorking: true,
- isCorrectMemcachedPHPModuleInstalled: true,
- hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: false,
- phpOpcacheDocumentation: 'https://example.org/link/to/doc',
- isSettimelimitAvailable: true,
- hasFreeTypeSupport: true,
- missingIndexes: [],
- missingPrimaryKeys: [],
- missingColumns: [],
- cronErrors: [],
- cronInfo: {
- diffInSeconds: 0
- },
- isMemoryLimitSufficient: true,
- appDirsWithDifferentOwner: [],
- recommendedPHPModules: [],
- pendingBigIntConversionColumns: [],
- isMysqlUsedWithoutUTF8MB4: false,
- isDefaultPhoneRegionSet: true,
- isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
- reverseProxyGeneratedURL: 'https://server',
- temporaryDirectoryWritable: true,
- })
- );
-
- async.done(function( data, s, x ){
- expect(data).toEqual([{
- msg: 'The PHP OPcache module is not loaded. <a target="_blank" rel="noreferrer noopener" class="external" href="https://example.org/link/to/doc">For better performance it is recommended ↗</a> to load it into your PHP installation.',
+ msg: 'The PHP OPcache module is not properly configured:<ul><li>recommendation1</li><li>recommendation2</li></ul>',
type: OC.SetupChecks.MESSAGE_TYPE_INFO
}]);
done();
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
phpOpcacheDocumentation: 'https://example.org/link/to/doc',
isSettimelimitAvailable: true,
hasFreeTypeSupport: false,
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],
forwardedForHeadersWorking: true,
isCorrectMemcachedPHPModuleInstalled: true,
hasPassedCodeIntegrityCheck: true,
- isOpcacheProperlySetup: true,
- hasOpcacheLoaded: true,
+ OpcacheSetupRecommendations: [],
isSettimelimitAvailable: true,
hasFreeTypeSupport: true,
missingIndexes: [],