First commit; not yet functional
This commit is contained in:
105
README.md
105
README.md
@ -1,2 +1,105 @@
|
|||||||
# mediawiki-appliance
|
# 📘 MediaWiki Appliance
|
||||||
|
|
||||||
|
**An Open Source Appliance from Robbie Ferguson**
|
||||||
|
(c) 2025 Robbie Ferguson. Licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
|
A ready-to-use MediaWiki appliance built for simplicity, performance, and security. This installer prepares a clean Debian system to serve MediaWiki at the root path with modern defaults, file uploads enabled, Redis caching, self-signed HTTPS, and preloaded core extensions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ How It Works
|
||||||
|
|
||||||
|
The appliance is built by running `installer.sh` on a clean Debian instance. It installs all required packages, downloads the latest stable version of MediaWiki, sets up MariaDB and Redis, configures NGINX with HTTPS, and preloads useful skins and extensions.
|
||||||
|
|
||||||
|
After installation, the wiki is fully functional at:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://your-server-ip/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 First-Time Setup
|
||||||
|
|
||||||
|
After installation, log into your wiki as:
|
||||||
|
|
||||||
|
- **Username**: `admin`
|
||||||
|
- **Password**: `changeme`
|
||||||
|
|
||||||
|
> 🔒 You must change this password immediately!
|
||||||
|
|
||||||
|
Visit:
|
||||||
|
```
|
||||||
|
https://your-server-ip/activate/
|
||||||
|
```
|
||||||
|
This setup screen allows you to securely define a new password. It is a **one-time activation process**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 What’s Included
|
||||||
|
|
||||||
|
- MediaWiki (latest stable)
|
||||||
|
- Skins: Vector (default), MonoBook, Timeless
|
||||||
|
- Extensions:
|
||||||
|
- Cite
|
||||||
|
- WikiEditor
|
||||||
|
- SyntaxHighlight_GeSHi
|
||||||
|
- CategoryTree
|
||||||
|
- File uploads enabled
|
||||||
|
- Redis server with MediaWiki cache integration
|
||||||
|
- PHP tuned for media uploads
|
||||||
|
- Self-signed HTTPS certificate for secure local access
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Enabling Let’s Encrypt (Optional)
|
||||||
|
|
||||||
|
The appliance includes **Certbot** and is preconfigured for HTTPS. If you plan to serve your wiki publicly with a real domain name:
|
||||||
|
|
||||||
|
1. Update `/etc/nginx/sites-available/mediawiki` to use your actual `server_name`
|
||||||
|
2. Then run:
|
||||||
|
```bash
|
||||||
|
certbot --nginx -d your.domain.name
|
||||||
|
```
|
||||||
|
|
||||||
|
This will obtain a valid SSL certificate and reload NGINX.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔁 Reinstalling or Removing
|
||||||
|
|
||||||
|
If the installer fails and you need to revert in order to try again, you can purge the appliance from your system:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer.sh --purge
|
||||||
|
```
|
||||||
|
|
||||||
|
This will:
|
||||||
|
- Stop all related services
|
||||||
|
- Remove MediaWiki files and NGINX config
|
||||||
|
- Uninstall MariaDB, PHP, Redis, and Certbot
|
||||||
|
- Leave the system clean for a rebuild
|
||||||
|
|
||||||
|
Note: This process assumes you are running the script on a dedicated appliance. Running this on anything but a dedicated appliance may destroy your system.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Backup Tips
|
||||||
|
|
||||||
|
To ensure your wiki can be restored, back up:
|
||||||
|
|
||||||
|
1. The database:
|
||||||
|
```bash
|
||||||
|
mysqldump -u root mediawiki > mediawiki.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
2. The uploaded files and configs:
|
||||||
|
```bash
|
||||||
|
tar czf uploads_backup.tar.gz /var/www/html/images /var/www/html/LocalSettings.php
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💬 Support
|
||||||
|
|
||||||
|
This appliance was built by Robbie Ferguson to provide a turn-key, modern MediaWiki experience. Contributions, forks, and enhancements are welcome.
|
||||||
|
67
activate/index.php
Normal file
67
activate/index.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
$flagFile = '/opt/mediawiki/.setup-complete';
|
||||||
|
|
||||||
|
if (file_exists($flagFile)) {
|
||||||
|
echo "<h2>Setup already completed</h2><p>The admin password has already been set. To change it, use the MediaWiki user interface or maintenance tools.</p>";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$password = $_POST['password'] ?? '';
|
||||||
|
$confirm = $_POST['confirm'] ?? '';
|
||||||
|
|
||||||
|
if ($password !== $confirm) {
|
||||||
|
$error = "Passwords do not match.";
|
||||||
|
} elseif (strlen($password) < 6) {
|
||||||
|
$error = "Password must be at least 6 characters.";
|
||||||
|
} else {
|
||||||
|
$safePassword = escapeshellarg($password);
|
||||||
|
$output = [];
|
||||||
|
$return = 0;
|
||||||
|
|
||||||
|
exec("php /var/www/html/maintenance/run.php changePassword --user=admin --password=$safePassword", $output, $return);
|
||||||
|
|
||||||
|
if ($return === 0) {
|
||||||
|
file_put_contents($flagFile, "Admin password set on " . date('c') . "\n");
|
||||||
|
echo "<h2>Success!</h2><p>The admin password has been updated. You can now log in and start using your wiki.</p>";
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
$error = "Failed to update password. Please check server permissions.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Set Admin Password - MediaWiki Appliance</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; margin: 2em; max-width: 500px; }
|
||||||
|
label { display: block; margin-top: 1em; }
|
||||||
|
input[type=password] { width: 100%; padding: 0.5em; }
|
||||||
|
input[type=submit] { margin-top: 1em; padding: 0.5em 1em; }
|
||||||
|
.error { color: red; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Set Admin Password</h1>
|
||||||
|
<p>This is a one-time setup page to secure your MediaWiki appliance. After submitting, this setup interface will be disabled.</p>
|
||||||
|
|
||||||
|
<?php if (!empty($error)): ?>
|
||||||
|
<p class="error"><?= htmlspecialchars($error) ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<label>New Admin Password:
|
||||||
|
<input type="password" name="password" required>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label>Confirm Password:
|
||||||
|
<input type="password" name="confirm" required>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input type="submit" value="Set Password">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
266
installer.sh
Executable file
266
installer.sh
Executable file
@ -0,0 +1,266 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# MediaWiki Server Appliance
|
||||||
|
# An Open Source Appliance from Robbie Ferguson
|
||||||
|
# (c) 2025 Robbie Ferguson. Licensed under the Apache License, Version 2.0
|
||||||
|
|
||||||
|
# This is the admin installer for building the appliance.
|
||||||
|
# Only to be run on a dedicated vanilla server to convert to this purpose.
|
||||||
|
# NEVER RUN THIS SCRIPT ON YOUR COMPUTER - it CONVERTS it to an appliance.
|
||||||
|
|
||||||
|
### HANDLE --purge ###
|
||||||
|
if [[ "$1" == "--purge" ]]; then
|
||||||
|
echo "[!] This will permanently remove all MediaWiki Appliance components."
|
||||||
|
echo " This will DESTROY a normal system; NEVER run this without exactly"
|
||||||
|
echo " understanding what the purpose is."
|
||||||
|
read -p "Are you sure you want to destory this system? [y/N]: " confirm
|
||||||
|
if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
|
||||||
|
echo "Aborted."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[*] Purging packages..."
|
||||||
|
|
||||||
|
systemctl stop nginx mariadb redis-server || true
|
||||||
|
apt purge -y nginx mariadb-server php* redis-server certbot python3-certbot-nginx
|
||||||
|
apt autoremove -y
|
||||||
|
rm -rf /var/www/html /etc/nginx/sites-available/mediawiki /etc/nginx/sites-enabled/default
|
||||||
|
rm -rf /etc/ssl/mediawiki
|
||||||
|
|
||||||
|
echo "[✓] Purge complete."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
### CONFIG ###
|
||||||
|
MW_DIR="/var/www/html"
|
||||||
|
DB_NAME="mediawiki"
|
||||||
|
DB_USER="wikiuser"
|
||||||
|
DB_PASS="$(openssl rand -base64 18)"
|
||||||
|
INSTALLER_DIR="$(pwd)"
|
||||||
|
|
||||||
|
### UPDATE SYSTEM AND INSTALL DEPENDENCIES ###
|
||||||
|
echo "[*] Installing system packages..."
|
||||||
|
apt update
|
||||||
|
apt install -y nginx mariadb-server php php-fpm php-mysql php-intl php-xml php-mbstring php-apcu php-gd php-curl php-zip unzip git curl redis-server php-redis certbot python3-certbot-nginx
|
||||||
|
|
||||||
|
### CONFIGURE DATABASE ###
|
||||||
|
echo "[*] Configuring MariaDB..."
|
||||||
|
mysql -e "CREATE DATABASE ${DB_NAME};"
|
||||||
|
mysql -e "CREATE USER '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';"
|
||||||
|
mysql -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';"
|
||||||
|
mysql -e "FLUSH PRIVILEGES;"
|
||||||
|
|
||||||
|
### DOWNLOAD MEDIAWIKI ###
|
||||||
|
echo "[*] Downloading latest MediaWiki..."
|
||||||
|
# A clever lil' way to detect the latest version of MediaWiki
|
||||||
|
MW_VERSION=$(curl -s https://releases.wikimedia.org/mediawiki/ | grep -oP 'href="([0-9]+\.[0-9]+(\.[0-9]+)?/)"' | cut -d'"' -f2 | sed 's:/$::' | sort -V | tail -n1)
|
||||||
|
# Now, git 'er!
|
||||||
|
DOWNLOAD_URL="https://releases.wikimedia.org/mediawiki/${MW_VERSION}/mediawiki-${MW_VERSION}.tar.gz"
|
||||||
|
FALLBACK_URL="https://releases.wikimedia.org/mediawiki/${MW_VERSION}/mediawiki-${MW_VERSION}.0.tar.gz"
|
||||||
|
|
||||||
|
echo "[*] Attempting to download MediaWiki version $MW_VERSION..."
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
# This method ensures if the file is .0, we append that to the version for the extraction and installation portion
|
||||||
|
if wget "$DOWNLOAD_URL"; then
|
||||||
|
TAR_FILE="mediawiki-${MW_VERSION}.tar.gz"
|
||||||
|
elif wget "$FALLBACK_URL"; then
|
||||||
|
MW_VERSION="${MW_VERSION}.0"
|
||||||
|
TAR_FILE="mediawiki-${MW_VERSION}.tar.gz"
|
||||||
|
else
|
||||||
|
echo "[!] Failed to download MediaWiki source."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
tar -xzf "mediawiki-${MW_VERSION}.tar.gz"
|
||||||
|
rm -rf "$MW_DIR"
|
||||||
|
mv "mediawiki-${MW_VERSION}" "$MW_DIR"
|
||||||
|
|
||||||
|
### AUTO-CONFIGURE MEDIAWIKI ###
|
||||||
|
echo "[*] Generating LocalSettings.php..."
|
||||||
|
|
||||||
|
WIKI_NAME="My Wiki"
|
||||||
|
ADMIN_USER="admin"
|
||||||
|
# WARNING: Default admin password is 'changeme'. User must change it immediately.
|
||||||
|
ADMIN_PASS="changeme"
|
||||||
|
|
||||||
|
### APPEND ADDITIONAL SETTINGS ###
|
||||||
|
LSETTINGS="$MW_DIR/LocalSettings.php"
|
||||||
|
|
||||||
|
echo "[*] Applying additional configuration..."
|
||||||
|
|
||||||
|
cat >> "$LSETTINGS" <<EOF
|
||||||
|
|
||||||
|
# Enable file uploads
|
||||||
|
\$wgEnableUploads = true;
|
||||||
|
|
||||||
|
# Set default skin
|
||||||
|
\$wgDefaultSkin = "vector";
|
||||||
|
|
||||||
|
# Enable Redis caching
|
||||||
|
\$wgMainCacheType = CACHE_REDIS;
|
||||||
|
\$wgMemCachedServers = ["127.0.0.1:6379"];
|
||||||
|
|
||||||
|
# Allow temporary simple admin password for first-run activation
|
||||||
|
\$wgMinimalPasswordLength = 6;
|
||||||
|
\$wgPasswordPolicy = [
|
||||||
|
'policies' => [
|
||||||
|
'default' => [
|
||||||
|
'MinimalPasswordLength' => 6,
|
||||||
|
'PasswordCannotBePopular' => false,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cd "$MW_DIR"
|
||||||
|
php maintenance/install.php \
|
||||||
|
--dbname="$DB_NAME" \
|
||||||
|
--dbuser="$DB_USER" \
|
||||||
|
--dbpass="$DB_PASS" \
|
||||||
|
--scriptpath="/" \
|
||||||
|
--server="https://localhost" \
|
||||||
|
--lang="en" \
|
||||||
|
"$WIKI_NAME" \
|
||||||
|
"$ADMIN_USER" --pass "$ADMIN_PASS"
|
||||||
|
|
||||||
|
### ENSURE DEFAULT SKIN IS VECTOR ###
|
||||||
|
if [[ -f "$LSETTINGS" ]]; then
|
||||||
|
if ! grep -q '$wgDefaultSkin' "$LSETTINGS"; then
|
||||||
|
echo "[*] Setting default skin to Vector in LocalSettings.php"
|
||||||
|
echo -e "\n# Set Vector as the default skin" >> "$LSETTINGS"
|
||||||
|
echo '$wgDefaultSkin = "vector";' >> "$LSETTINGS"
|
||||||
|
else
|
||||||
|
echo "[*] Default skin already configured in LocalSettings.php"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "[*] LocalSettings.php not found — skipping skin configuration"
|
||||||
|
fi
|
||||||
|
|
||||||
|
### INSTALL EXTENSIONS ###
|
||||||
|
echo "[*] Installing common extensions..."
|
||||||
|
cd "$MW_DIR/extensions"
|
||||||
|
|
||||||
|
for ext in Cite WikiEditor SyntaxHighlight_GeSHi CategoryTree; do
|
||||||
|
if [[ ! -d "$MW_DIR/extensions/$ext" ]]; then
|
||||||
|
echo "[*] Installing extension: $ext"
|
||||||
|
git clone "https://gerrit.wikimedia.org/r/mediawiki/extensions/${ext}.git" "$MW_DIR/extensions/$ext"
|
||||||
|
cd "$MW_DIR/extensions/$ext" && git checkout "REL${MW_VERSION//./_}"
|
||||||
|
else
|
||||||
|
echo "[*] Extension $ext already exists — skipping"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
### ENABLE REDIS ###
|
||||||
|
systemctl enable redis-server
|
||||||
|
systemctl start redis-server
|
||||||
|
|
||||||
|
### CONFIGURE PHP ###
|
||||||
|
echo "[*] Adjusting PHP settings..."
|
||||||
|
PHP_INI=$(php --ini | grep "Loaded Configuration" | awk '{print $4}')
|
||||||
|
sed -i 's/upload_max_filesize = .*/upload_max_filesize = 20M/' "$PHP_INI"
|
||||||
|
sed -i 's/post_max_size = .*/post_max_size = 24M/' "$PHP_INI"
|
||||||
|
systemctl restart php*-fpm
|
||||||
|
|
||||||
|
### SETUP ACTIVATION ###
|
||||||
|
cd "$INSTALLER_DIR"
|
||||||
|
cp -R ./activate /var/www/html/
|
||||||
|
chown -R www-data:www-data /var/www/html/activate
|
||||||
|
if [[ ! -e /opt/mediawiki ]]; then
|
||||||
|
rm -rf /opt/mediawiki
|
||||||
|
fi
|
||||||
|
mkdir -p /opt/mediawiki
|
||||||
|
chown www-data:www-data /opt/mediawiki
|
||||||
|
|
||||||
|
### CONFIGURE NGINX ###
|
||||||
|
echo "[*] Setting up NGINX..."
|
||||||
|
cat > /etc/nginx/sites-available/mediawiki <<EOF
|
||||||
|
server {
|
||||||
|
listen 443 ssl default_server;
|
||||||
|
listen [::]:443 ssl default_server;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root $MW_DIR;
|
||||||
|
index index.php;
|
||||||
|
|
||||||
|
ssl_certificate /etc/ssl/mediawiki/selfsigned.crt;
|
||||||
|
ssl_certificate_key /etc/ssl/mediawiki/selfsigned.key;
|
||||||
|
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
|
||||||
|
location = /activate {
|
||||||
|
return 301 /activate/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files \$uri \$uri/ @rewrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @rewrite {
|
||||||
|
rewrite ^/(.*)$ /index.php?title=\$1&\$args;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ^~ /maintenance/ {
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ \.php\$ {
|
||||||
|
include snippets/fastcgi-php.conf;
|
||||||
|
fastcgi_pass unix:/run/php/php-fpm.sock;
|
||||||
|
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|ttf|woff|woff2)$ {
|
||||||
|
try_files \$uri /index.php;
|
||||||
|
expires max;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80 default_server;
|
||||||
|
listen [::]:80 default_server;
|
||||||
|
server_name _;
|
||||||
|
return 301 https://\$host\$request_uri;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
rm -f /etc/nginx/sites-enabled/*
|
||||||
|
ln -sf /etc/nginx/sites-available/mediawiki /etc/nginx/sites-enabled/default
|
||||||
|
|
||||||
|
### SELF-SIGNED SSL ###
|
||||||
|
echo "[*] Generating self-signed HTTPS cert..."
|
||||||
|
mkdir -p /etc/ssl/mediawiki
|
||||||
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||||
|
-keyout /etc/ssl/mediawiki/selfsigned.key \
|
||||||
|
-out /etc/ssl/mediawiki/selfsigned.crt \
|
||||||
|
-subj "/C=US/ST=None/L=None/O=MediaWikiAppliance/CN=localhost"
|
||||||
|
|
||||||
|
### FINALIZE ###
|
||||||
|
nginx -t && systemctl reload nginx
|
||||||
|
|
||||||
|
### DONE ###
|
||||||
|
echo
|
||||||
|
echo "===================================================================="
|
||||||
|
echo "MediaWiki Appliance Installed!"
|
||||||
|
echo
|
||||||
|
echo "To complete setup, visit: https://your-server-ip/"
|
||||||
|
echo
|
||||||
|
echo "Use the following database settings during setup:"
|
||||||
|
echo " DB Name: $DB_NAME"
|
||||||
|
echo " DB User: $DB_USER"
|
||||||
|
echo " DB Password: $DB_PASS"
|
||||||
|
echo
|
||||||
|
echo "Admin login:"
|
||||||
|
echo " Username: $ADMIN_USER"
|
||||||
|
echo " Password: $ADMIN_PASS"
|
||||||
|
echo
|
||||||
|
echo "File uploads enabled, Vector skin and core extensions preloaded."
|
||||||
|
echo "Redis enabled for caching. PHP limits adjusted for media upload."
|
||||||
|
echo "Self-signed cert installed. Let's Encrypt ready but not configured."
|
||||||
|
echo
|
||||||
|
echo "Certbot is installed. See README.md to enable Let's Encrypt."
|
||||||
|
echo "===================================================================="
|
Reference in New Issue
Block a user