gplx/docs/DEPLOYMENT_IONOS_VPS_RUNBOO...

352 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GPLX Deployment Runbook: IONOS VPS (native Apache)
This document records the **exact steps taken** to deploy GPLX on an IONOS VPS on 2026-06-05.
It replaces a broken Docker-based MediaWiki install with a native Apache + PHP + MariaDB stack.
Use it verbatim for a repeat deployment or hand it to another AI assistant.
---
## Environment
| Item | Value |
|-----------------|-------------------------------|
| Server IP | `31.70.94.35` |
| OS | Ubuntu 24.04 LTS |
| Web root | `/var/www/gplx/mediawiki` |
| Git bare repo | `/var/repo/gplx.git` |
| DB name/user | `gplx` / `gplx` |
| MW admin user | `Gxplex_admin` |
| MW admin pass | `TempAdmin123`**change this** |
| HTTP Basic Auth user | `testUser` |
---
## Starting situation
- Two Docker containers were running on the server:
- `mediawiki:1.41` on `0.0.0.0:8080->80`
- `mysql:8.0` on `3306/tcp`
- `nginx` was running on port 80 (served something else, now disabled)
- `/var/www/gplx` did **not** exist
- Git remote `ionos` pointed at `ssh://root@31.70.94.35/var/www/gplx` (wrong — no bare repo)
---
## Step 1 Create bare git repo on the server
Run locally:
```powershell
ssh root@31.70.94.35 "git init --bare /var/repo/gplx.git && mkdir -p /var/www/gplx && printf '#!/bin/bash\nGIT_WORK_TREE=/var/www/gplx git checkout -f main\n' > /var/repo/gplx.git/hooks/post-receive && chmod +x /var/repo/gplx.git/hooks/post-receive && echo 'Done'"
```
This creates a bare repo at `/var/repo/gplx.git` and a `post-receive` hook that checks out
the code into `/var/www/gplx` on every push.
---
## Step 2 Fix local git remote and push
```powershell
git remote set-url ionos ssh://root@31.70.94.35/var/repo/gplx.git
git push ionos main
```
The hook fires automatically: output shows `Switched to branch 'main'`.
---
## Step 3 Install system packages
All packages were already present on this server. If doing a fresh install:
```bash
ssh root@<ip>
apt update && apt install -y apache2 php8.3 php8.3-mysql php8.3-xml \
php8.3-mbstring php8.3-intl php8.3-curl php8.3-gd php8.3-zip \
mariadb-server git apache2-utils
```
---
## Step 4 Stop nginx (was holding port 80)
```bash
systemctl stop nginx
systemctl disable nginx
```
---
## Step 5 Create database and user
```bash
mysql -u root <<'SQL'
CREATE DATABASE IF NOT EXISTS gplx CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'gplx'@'localhost' IDENTIFIED BY 'YOUR_DB_PASSWORD';
GRANT ALL PRIVILEGES ON gplx.* TO 'gplx'@'localhost';
FLUSH PRIVILEGES;
SQL
```
If the user already exists with a different password, reset it:
```bash
mysql -u root <<'SQL'
ALTER USER 'gplx'@'localhost' IDENTIFIED BY 'YOUR_DB_PASSWORD';
FLUSH PRIVILEGES;
SQL
```
---
## Step 6 Configure Apache vhost with HTTP Basic Auth
```bash
cat > /etc/apache2/sites-available/gplx.conf << 'EOF'
<VirtualHost *:80>
ServerName 31.70.94.35
DocumentRoot /var/www/gplx/mediawiki
<Directory /var/www/gplx/mediawiki>
AllowOverride All
AuthType Basic
AuthName "GxPlex restricted access"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
</VirtualHost>
EOF
a2enmod rewrite
a2ensite gplx
a2dissite 000-default
systemctl start apache2
```
> **Important:** Do NOT include `Require all granted` alongside `Require valid-user` —
> they act as OR, which lets anonymous traffic through.
Create the htpasswd file:
```bash
htpasswd -c /etc/apache2/.htpasswd testUser
# enter password at the prompt
```
---
## Step 7 Install Composer dependencies
MediaWiki core:
```bash
cd /var/www/gplx/mediawiki
composer install --no-dev
```
SemanticMediaWiki (has its own vendor tree):
```bash
composer install --no-dev -d extensions/SemanticMediaWiki
```
---
## Step 8 Deploy LocalSettings.php
`LocalSettings.php` is gitignored and must be transferred separately.
**On your local machine**, edit `mediawiki/LocalSettings.php` and set:
```php
$wgServer = "http://31.70.94.35"; // or https://yourdomain.de once TLS is live
$wgDBserver = "localhost";
$wgDBname = "gplx";
$wgDBuser = "gplx";
$wgDBpassword = "YOUR_DB_PASSWORD";
$wgSecretKey = "<output of: openssl rand -hex 32>";
$wgShowExceptionDetails = false;
// in the ExtensionFunctions hook:
enableSemantics( '31.70.94.35' ); // change to domain once live
```
Then copy to the server:
```powershell
scp mediawiki/LocalSettings.php root@31.70.94.35:/var/www/gplx/mediawiki/LocalSettings.php
```
Or patch it in-place on the server with `sed`:
```bash
sed -i \
-e 's|$wgServer = "http://127.0.0.1:8080";|$wgServer = "http://31.70.94.35";|' \
-e 's|$wgDBserver = "127.0.0.1";|$wgDBserver = "localhost";|' \
-e 's|$wgDBname = "gflex_test";|$wgDBname = "gplx";|' \
-e 's|$wgDBuser = "root";|$wgDBuser = "gplx";|' \
-e "s|\$wgDBpassword = \"\";|\$wgDBpassword = \"YOUR_DB_PASSWORD\";|" \
-e "s|enableSemantics( '127.0.0.1:8080' );|enableSemantics( '31.70.94.35' );|" \
-e 's|$wgShowExceptionDetails = true;|$wgShowExceptionDetails = false;|' \
/var/www/gplx/mediawiki/LocalSettings.php
```
---
## Step 9 Create images directory
```bash
mkdir -p /var/www/gplx/mediawiki/images
chown -R www-data:www-data /var/www/gplx/mediawiki/images
```
---
## Step 10 Install MediaWiki database tables
Because the database is empty, `update.php` fails with "Can not upgrade from versions older
than 1.35". Use `install.php` instead, temporarily hiding `LocalSettings.php`:
```bash
cd /var/www/gplx/mediawiki
mv LocalSettings.php LocalSettings.php.bak
php maintenance/run.php install \
--dbuser gplx \
--dbpass YOUR_DB_PASSWORD \
--dbname gplx \
--dbserver localhost \
--server 'http://31.70.94.35' \
--scriptpath '' \
--lang en \
--pass TempAdmin123 \
'GxPlex' 'Gxplex_admin'
mv LocalSettings.php.bak LocalSettings.php
```
Then run update to pick up extension schema changes:
```bash
php maintenance/run.php update --quick
```
---
## Step 11 Set up SMW tables
```bash
php extensions/SemanticMediaWiki/maintenance/setupStore.php --nochecks
```
---
## Step 12 Smoke test
```bash
# Should return 401 (Basic Auth gate)
curl -s -o /dev/null -w '%{http_code}' http://31.70.94.35/
# Should return 200 with correct credentials
curl -sL -o /dev/null -w '%{http_code}' -u testUser:YOUR_HTPASSWD_PASSWORD http://31.70.94.35/
```
Open in browser: `http://31.70.94.35` → login prompt → MediaWiki main page.
---
## Step 13 Import local database dump
The local MediaWiki DB was exported as `gflex_test.sql` (≈280 MB) and contains all user
accounts, pages, and content from the dev instance.
Upload the dump to the server:
```powershell
scp D:\Work\Projekte\gplx\gflex_test.sql root@31.70.94.35:/root/gflex_test.sql
```
The `gplx` DB already had tables from the fresh install (Step 10), so drop and recreate it
before importing — otherwise MySQL errors with "Table already exists":
```bash
mysql -u root <<'SQL'
DROP DATABASE gplx;
CREATE DATABASE gplx CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON gplx.* TO 'gplx'@'localhost';
FLUSH PRIVILEGES;
SQL
```
Import the dump:
```bash
mysql -ugplx -pYOUR_DB_PASSWORD gplx < /root/gflex_test.sql
```
Run update to apply any schema differences between the dump and the current MW version:
```bash
cd /var/www/gplx/mediawiki
php maintenance/run.php update --quick
```
All local user accounts and wiki content are now available on the server.
---
## Step 14 Nutzeraccounts
Die Accounts aus dem SQL-Import (Step 13) sind direkt nutzbar — lokale Zugangsdaten
funktionieren ohne weitere Schritte.
**Vorhandene User prüfen:**
```bash
mysql -ugplx -pYOUR_DB_PASSWORD gplx \
-e 'SELECT user_name, user_registration FROM user ORDER BY user_registration DESC LIMIT 20;'
```
**Neuen Account anlegen** (Passwort wird interaktiv abgefragt):
```bash
cd /var/www/gplx/mediawiki
php maintenance/run.php createAndPromote NeuUser
# mit Bureaucrat-Rechten:
php maintenance/run.php createAndPromote --bureaucrat NeuUser
```
**Passwort zurücksetzen:**
```bash
php maintenance/run.php changePassword --user="Benutzername" --password="NeuesPasswort"
```
**Account im Browser anlegen:** `http://31.70.94.35/index.php/Special:CreateAccount`
(nur sichtbar wenn `$wgGroupPermissions['*']['createaccount'] = true`, was der Standard ist).
---
## Next steps (not yet done)
- [ ] Change `Gxplex_admin` password via `Special:ChangePassword`
- [ ] Point domain DNS A-record to `31.70.94.35`
- [ ] Add TLS via Certbot: `certbot --apache -d yourdomain.de`
- [ ] Update `$wgServer` and `enableSemantics()` to use the domain
- [ ] Push wiki page templates: `Get-Content scripts/templates/<file>.wiki -Raw | php mediawiki/maintenance/run.php edit ...`
- [ ] Run `npm run a11y:all` against the live URL
---
## Gotchas encountered
| Problem | Cause | Fix |
|---------|-------|-----|
| `git push ionos main` failed (exit 1) | Remote pointed at non-bare working dir | Created bare repo at `/var/repo/gplx.git` with post-receive hook |
| `/var/www/gplx/mediawiki` not found after push | Directory was checked out by hook — actually worked, just needed to look again | `ls /var/www/gplx/mediawiki` confirmed it was there |
| SMW fatal: `Class "Onoi\Cache\NullCache" not found` | SMW vendor deps not installed | `composer install --no-dev -d extensions/SemanticMediaWiki` |
| `update.php`: "Can not upgrade from versions older than 1.35" | Completely empty DB — MW misreads it | Use `install.php` with `LocalSettings.php` temporarily moved away |
| `install.php`: "A LocalSettings.php file has been detected" | Installer refuses when file exists | `mv LocalSettings.php LocalSettings.php.bak` before install, restore after |
| Apache won't start | nginx was holding port 80 | `systemctl stop nginx && systemctl disable nginx` |
| Basic Auth not blocking (returns 200 for anonymous) | `Require all granted` + `Require valid-user` = OR logic | Remove `Require all granted`; only keep `Require valid-user` |
| DB "Access denied for user gplx" | Password in LocalSettings.php didn't match DB | `ALTER USER 'gplx'@'localhost' IDENTIFIED BY '...'` to sync them |
| `ERROR 1050: Table 'actor' already exists` on SQL import | Fresh MW install already created tables; importing on top fails | `DROP DATABASE gplx` + recreate, then import |