diff --git a/README.md b/README.md index 49401aa..7c4dbfd 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,15 @@ # mediawiki -Config for wiki.ctbk.de and the upcoming Orgawiki deployment. +Config for [wiki.ctbk.de](https://wiki.ctbk.de) and the upcoming Orgawiki deployment. For deployment documentation refer to [the Wiki](https://wiki.ctbk.de/Dienste/Wiki). -Files for the wiki.ctbk.de public deployment are found in `public_mediawiki`. Files for the internal deployment (not yet in production) are found in `orga_mediawiki`. Some common files are found in the root directory. +Files for the [wiki.ctbk.de](https://wiki.ctbk.de) public deployment are found in `public_mediawiki`. Files for the internal deployment (not yet in production) are found in `orga_mediawiki`. Some common files are found in the root directory. Note that while some files may look identical between the deployments, they are not shared to allow easier modifications to both deployments independently. + +The [`install.sh`](install.sh) script replaces all relevant system files with symlinks to the files in this repository. + +## License + +The files in this repository are licensed under the BSD 2-clause license. The contents of the Wiki have different license(s), [see here](https://wiki.ctbk.de/Wiki:Urheberrechte). diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..c2561e3 --- /dev/null +++ b/install.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +scriptdir=$(dirname $(realpath $0)) + +set +e + +ln -fs "$scriptdir/smw-jobs.sh" /usr/local/bin/smw-jobs +ln -fs "$scriptdir/nginx.conf" /etc/nginx/nginx.conf +ln -fs "$scriptdir/fastcgi.conf" /etc/nginx/fastcgi.conf +ln -fs "$scriptdir/robots.txt" /etc/nginx/robots.txt +ln -fs "$scriptdir/public_mediawiki/public_mediawiki.conf" /etc/nginx/sites-enabled/public_mediawiki.conf +ln -fs "$scriptdir/orga_mediawiki/orga_mediawiki.conf" /etc/nginx/sites-enabled/orga_mediawiki.conf +ln -fs "$scriptdir/pgtune.conf" "/etc/postgresql/15/main/conf.d/pgtune.conf" + +for file in "$scriptdir/system"/*; do + filename=$(basename "$file") + ln -fs "$file" "/etc/systemd/system/$filename" +done + +for file in "$scriptdir/public_mediawiki"/*; do + filename=$(basename "$file") + ln -fs "$file" "/etc/public_mediawiki/$filename" +done + +for file in "$scriptdir/orga_mediawiki"/*; do + filename=$(basename "$file") + ln -fs "$file" "/etc/orga_mediawiki/$filename" +done + diff --git a/nginx.conf b/nginx.conf index bac1998..4532678 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,7 +1,6 @@ user www-data; worker_processes auto; pid /run/nginx.pid; -error_log /var/log/nginx/error.log; include /etc/nginx/modules-enabled/*.conf; events { @@ -37,7 +36,12 @@ http { # Logging Settings ## - access_log /var/log/nginx/access.log; + log_format main '$http_x_forwarded_for [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent"'; + + access_log /var/log/nginx/access.log main; + error_log /var/log/nginx/error.log; ## # Gzip Settings diff --git a/orga_mediawiki/LocalSettings.php b/orga_mediawiki/LocalSettings.php index ecda7c4..17aa4af 100644 --- a/orga_mediawiki/LocalSettings.php +++ b/orga_mediawiki/LocalSettings.php @@ -41,8 +41,8 @@ $wgScriptExtension = ".php"; ## The protocol and server name to use in fully-qualified URLs # TODO: should be the public domain eventually -#$wgServer = "https://orgawiki.ctbk.de"; -$wgServer = "http://wiki.chaos:81"; +$wgServer = "https://orgawiki.ctbk.de"; +#$wgServer = "http://wiki.chaos:81"; ## The URL path to static resources (images, scripts, etc.) $wgResourceBasePath = $wgScriptPath; @@ -185,8 +185,21 @@ $wgPluggableAuth_Config["Chaostreff Backnang IdP"] = [ ] ]; +# interwiki config +$wgGroupPermissions['sysop']['interwiki'] = true; +$wgInterwikiMagic = true; +$wgHideInterlanguageLinks = false; + # for better error reporting - disable while in production #error_reporting( -1 ); #ini_set( 'display_errors', 1 ); #$wgShowExceptionDetails = true; #$wgShowDBErrorBacktrace = true; + +$wgNamespacesWithSubpages[NS_MAIN] = true; +$wgNamespacesWithSubpages[NS_TEMPLATE] = true; + +# use proxy ip addresses -- we’re behind (at least) one reverse proxy that sets X-Forwarded-For +$wgUsePrivateIPs = true; +# ingress haproxy +$wgCdnServersNoPurge = [ '10.140.0.1' ]; diff --git a/orga_mediawiki/orga_mediawiki.conf b/orga_mediawiki/orga_mediawiki.conf index e7fb257..fa2a08f 100644 --- a/orga_mediawiki/orga_mediawiki.conf +++ b/orga_mediawiki/orga_mediawiki.conf @@ -9,9 +9,14 @@ server { client_body_timeout 60; index index.php index.html index.htm; - location ~ \.ht { - deny all; - } + location ~ \.ht { + deny all; + } + + location /robots.txt { + root /etc/nginx; + try_files /robots.txt =404; + } location / { try_files $uri $uri/ @rewrite; diff --git a/public_mediawiki/LocalSettings.php b/public_mediawiki/LocalSettings.php index ee29bf5..cabac03 100755 --- a/public_mediawiki/LocalSettings.php +++ b/public_mediawiki/LocalSettings.php @@ -159,14 +159,21 @@ wfLoadExtension( 'TemplateData' ); wfLoadExtension( 'TitleBlacklist' ); wfLoadExtension( 'VisualEditor' ); wfLoadExtension( 'WikiEditor' ); +wfLoadExtension( 'CodeMirror' ); +wfLoadExtension( 'TemplateStyles' ); +wfLoadExtension( 'TemplateStylesExtender' ); +wfLoadExtension( 'Widgets' ); wfLoadExtension( 'PluggableAuth' ); wfLoadExtension( 'OpenIDConnect' ); +$wgPFEnableStringFunctions = true; + +# SMW config wfLoadExtension( 'SemanticMediaWiki' ); enableSemantics( 'wiki.ctbk.de' ); - -# Add more configuration options below. +$smwgQueryResultCacheType = CACHE_ANYTHING; +$wgGroupPermissions['sysop']['smw-admin'] = true; # Disable account creation - we only use SSO accounts $wgGroupPermissions['*']['autocreateaccount'] = true; @@ -177,6 +184,10 @@ $wgGroupPermissions['sysop']['createaccount'] = true; # allow copy uploads by anyone $wgGroupPermissions['user']['upload_by_url'] = true; +# disallow widget editing by anyone except sysops +$wgGroupPermissions['*']['editwidgets'] = false; +$wgGroupPermissions['sysop']['editwidgets'] = true; + # SSO config # necessary to allow admin user(s) to login $wgPluggableAuth_EnableLocalLogin = true; @@ -185,10 +196,24 @@ $wgPluggableAuth_Config["Chaostreff Backnang IdP"] = [ 'data' => [ 'providerURL' => 'https://idp.ctbk.de/realms/ctbk/', 'clientID' => 'public_mediawiki', + 'scope' => [ 'openid', 'profile', 'email', 'groups' ], 'clientsecret' => $ctbkClientSecret + ], + # use Keycloak group definitions to manage groups centrally + 'groupsyncs' => [ + [ + 'type' => 'mapped', + 'map' => [ + 'sysop' => [ 'groups' => '/mediawiki/admins' ], + 'buerocrat' => [ 'groups' => '/mediawiki/admins' ], + 'interface-admin' => [ 'groups' => '/mediawiki/admins' ] + ] + ] ] ]; +$wgDefaultUserOptions['usecodemirror'] = 1; + # interwiki config $wgGroupPermissions['sysop']['interwiki'] = true; $wgInterwikiMagic = true; @@ -207,3 +232,18 @@ $wgHideInterlanguageLinks = false; $wgFileExtensions[] = 'svg'; # This extension will no longer be needed in MediaWiki >= 1.41, then $wgSVGNativeRendering can be used wfLoadExtension( 'NativeSvgHandler' ); + +# do not sanitize my CSS +#$wgTemplateStylesAutoParseContent = false; +$wgTemplateStylesExtenderEnablePrefersColorScheme = true; +$wgTemplateStylesExtenderEnableCssVars = true; + +# enable namespaces everywhere we need them +$wgNamespacesWithSubpages[NS_MAIN] = true; +$wgNamespacesWithSubpages[NS_TEMPLATE] = true; + +# use proxy ip addresses -- we’re behind (at least) one reverse proxy that sets X-Forwarded-For +$wgUsePrivateIPs = true; +# ingress haproxy +$wgCdnServersNoPurge = [ '10.140.0.1' ]; + diff --git a/public_mediawiki/composer.local.json b/public_mediawiki/composer.local.json index 489afd2..45dfb59 100644 --- a/public_mediawiki/composer.local.json +++ b/public_mediawiki/composer.local.json @@ -3,6 +3,42 @@ { "type": "vcs", "url": "https://gerrit.wikimedia.org/r/mediawiki/extensions/OpenIDConnect" + }, + { + "type": "package", + "package": { + "name": "mediawiki/codemirror", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror.git", + "reference": "REL1_39" + } + } + }, + { + "type": "package", + "package": { + "name": "mediawiki/templatestyles", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://gerrit.wikimedia.org/r/mediawiki/extensions/TemplateStyles", + "reference": "REL1_39" + } + } + }, + { + "type": "package", + "package": { + "name": "mediawiki/widgets", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://gerrit.wikimedia.org/r/mediawiki/extensions/Widgets", + "reference": "1.6.0" + } + } } ], "require": { @@ -12,7 +48,11 @@ "mediawiki/semantic-compound-queries": "^2.2", "mediawiki/semantic-extra-special-properties": "^3", "mediawiki/semantic-media-wiki": "^4.2", - "mediawiki/semantic-result-formats": "^4.2" + "mediawiki/semantic-result-formats": "^4.2", + "mediawiki/codemirror": "^6", + "mediawiki/templatestyles": "^1", + "octfx/template-styles-extender": "^1.2", + "mediawiki/widgets": "^1.6" }, "config": { "preferred-install": "source", diff --git a/public_mediawiki/public_mediawiki.conf b/public_mediawiki/public_mediawiki.conf index 8d36cb6..c89ff63 100644 --- a/public_mediawiki/public_mediawiki.conf +++ b/public_mediawiki/public_mediawiki.conf @@ -9,9 +9,14 @@ server { client_body_timeout 60; index index.php index.html index.htm; - location ~ \.ht { - deny all; - } + location ~ \.ht { + deny all; + } + + location /robots.txt { + root /etc/nginx; + try_files /robots.txt =404; + } location / { try_files $uri $uri/ @rewrite; diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..b93e3f5 --- /dev/null +++ b/robots.txt @@ -0,0 +1,3 @@ +User-Agent: * +Disallow: / + diff --git a/smw-jobs.sh b/smw-jobs.sh new file mode 100755 index 0000000..000cf0e --- /dev/null +++ b/smw-jobs.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +# ignore single script failures +set +e + +SMW_PATH=$1 + +set -x + +# not needed in our current config according to the documentation +#php "${SMW_PATH}/maintenance/updateSpecialPages.php" --quiet + +# recommended daily jobs +php "${SMW_PATH}/maintenance/rebuildData.php" --shallow-update +php "${SMW_PATH}/maintenance/disposeOutdatedEntities.php" +php "${SMW_PATH}/maintenance/rebuildPropertyStatistics.php" +php "${SMW_PATH}/maintenance/rebuildConceptCache.php" --update --create + +# recommended weekly jobs — we still run them daily to simplify the timers +php "${SMW_PATH}/maintenance/rebuildData.php" -d 100 +php "${SMW_PATH}/maintenance/setupStore.php" --skip-import + +# recommended monthly jobs +php "${SMW_PATH}/maintenance/removeDuplicateEntities.php" + diff --git a/system/mediawiki-jobrunner@.service b/system/mediawiki-jobrunner@.service new file mode 100644 index 0000000..4de5700 --- /dev/null +++ b/system/mediawiki-jobrunner@.service @@ -0,0 +1,18 @@ +[Unit] +Description=MediaWiki job runner %I +Documentation=https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:RunJobs.php + +[Service] +User=www-data +Group=www-data +ExecStart=/usr/bin/php /var/lib/%i/maintenance/runJobs.php --wait --maxjobs=50 +Restart=always +RestartSec=15 +RuntimeMaxSec=300 +PrivateDevices=true +PrivateTmp=true +ProtectHome=read-only + +[Install] +WantedBy=multi-user.target + diff --git a/system/semantic-mediawiki-jobs@.service b/system/semantic-mediawiki-jobs@.service new file mode 100644 index 0000000..ce8fcd9 --- /dev/null +++ b/system/semantic-mediawiki-jobs@.service @@ -0,0 +1,13 @@ +[Unit] +Description=Semantic MediaWiki job runner %I +Documentation=https://www.semantic-mediawiki.org/wiki/Help:Cron_jobs + +[Service] +User=www-data +Group=www-data +ExecStart=/usr/local/bin/smw-jobs /var/lib/%i/extensions/SemanticMediaWiki +RestartSec=15 +PrivateDevices=true +PrivateTmp=true +ProtectHome=read-only + diff --git a/system/semantic-mediawiki-jobs@.timer b/system/semantic-mediawiki-jobs@.timer new file mode 100644 index 0000000..9b15214 --- /dev/null +++ b/system/semantic-mediawiki-jobs@.timer @@ -0,0 +1,13 @@ +[Unit] +Description=Semantic MediaWiki job timer %I +Documentation=https://www.semantic-mediawiki.org/wiki/Help:Cron_jobs + +[Timer] +# run the jobs in the morning, after the backups happen +OnCalendar=*-*-* 04:00:00 +RandomizedDelaySec=1h +Unit=semantic-mediawiki-jobs@%i.service + +[Install] +WantedBy=timers.target +