noisebridge-wiki/modules/wiki-primary/mediawiki.nix
Jet 8cfede9f57
Some checks failed
CI / check (push) Has been cancelled
CI / deploy (push) Has been cancelled
feat: init
2026-03-17 04:07:44 -07:00

123 lines
4.2 KiB
Nix

{ config, pkgs, lib, ... }:
{
services.mediawiki.extraConfig = lib.mkAfter ''
# ----- Invite-only accounts -----
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['bureaucrat']['createaccount'] = true;
# ----- File cache for anonymous readers -----
$wgUseFileCache = true;
$wgFileCacheDirectory = "/var/cache/mediawiki";
$wgShowIPinHeader = false;
# ----- Rate limit exemption for logged-in users -----
$wgGroupPermissions['user']['noratelimit'] = true;
# ----- Email -----
$wgEnableEmail = true;
$wgEnableUserEmail = true;
$wgEmergencyContact = "wiki@noisebridge.net";
$wgPasswordSender = "wiki@noisebridge.net";
# Mail sent via local Postfix, which relays through m3.noisebridge.net
# ----- ReCaptcha (login brute-force only) -----
wfLoadExtension( 'ConfirmEdit/ReCaptchaNoCaptcha' );
$wgReCaptchaSiteKey = '6Le_REPLACE_SITE_KEY';
$wgReCaptchaSecretKey = trim(file_get_contents('${config.age.secrets.mediawiki-recaptcha.path}'));
$wgCaptchaTriggers['badlogin'] = true;
$wgCaptchaTriggers['createaccount'] = false;
$wgCaptchaTriggers['edit'] = false;
$wgCaptchaTriggers['create'] = false;
'';
# PHP-FPM: static pool for maximum performance
# Use individual mkForce to override defaults without clobbering
# required settings (listen, user, group) set by the mediawiki module
services.phpfpm.pools.mediawiki.settings = {
"pm" = lib.mkForce "static";
"pm.max_children" = lib.mkForce 30;
"pm.max_requests" = lib.mkForce 500;
"request_terminate_timeout" = lib.mkForce "30s";
"catch_workers_output" = lib.mkForce true;
"pm.status_path" = "/fpm-status";
# OPcache
"php_admin_value[opcache.enable]" = 1;
"php_admin_value[opcache.memory_consumption]" = 256;
"php_admin_value[opcache.max_accelerated_files]" = 10000;
"php_admin_value[opcache.revalidate_freq]" = 60;
"php_admin_value[opcache.jit]" = 1255;
"php_admin_value[opcache.jit_buffer_size]" = "64M";
# Memory & execution
"php_admin_value[memory_limit]" = "256M";
"php_admin_value[max_execution_time]" = 30;
"php_admin_value[upload_max_filesize]" = "10M";
"php_admin_value[post_max_size]" = "12M";
};
# File cache directory
systemd.tmpfiles.rules = [
"d /var/cache/mediawiki 0755 mediawiki mediawiki -"
];
# MediaWiki job runner (since wgJobRunRate=0)
systemd.services.mediawiki-jobrunner = {
description = "MediaWiki job runner";
after = [ "mysql.service" "phpfpm-mediawiki.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "simple";
User = "mediawiki";
Group = "mediawiki";
ExecStart = "${pkgs.php}/bin/php ${config.services.mediawiki.finalPackage}/share/mediawiki/maintenance/runJobs.php --wait --maxjobs=10";
Restart = "always";
RestartSec = "30s";
};
};
# Sync uploaded images to replica over Tailscale (hourly)
# Writes textfile metrics so Prometheus can alert on stale syncs
systemd.services.wiki-image-sync = {
description = "Sync wiki images to replica";
after = [ "tailscale-autoconnect.service" ];
path = [ pkgs.rsync ];
serviceConfig = {
Type = "oneshot";
User = "root";
};
script = ''
TEXTFILE_DIR="/var/lib/prometheus-node-exporter/textfile"
if rsync -az --delete /var/lib/mediawiki/images/ wiki-replica:/var/lib/mediawiki/images/; then
SYNC_OK=1
else
SYNC_OK=0
fi
cat > "$TEXTFILE_DIR/imagesync.prom" <<EOF
# HELP imagesync_latest_timestamp_seconds Unix timestamp of latest image sync attempt
# TYPE imagesync_latest_timestamp_seconds gauge
imagesync_latest_timestamp_seconds $(date +%s)
# HELP imagesync_success Whether the last image sync succeeded (1=success, 0=failure)
# TYPE imagesync_success gauge
imagesync_success $SYNC_OK
EOF
'';
};
systemd.timers.wiki-image-sync = {
description = "Hourly wiki image sync to replica";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "hourly";
Persistent = true;
};
};
age.secrets.mediawiki-recaptcha = {
file = ../../secrets/mediawiki-recaptcha.age;
owner = "mediawiki";
group = "mediawiki";
};
}