Host Your Own Mediawiki Online - In Ubuntu 22.04 LXC Container

From CompleteNoobs
Jump to navigation Jump to search
Please Select a Licence from the LICENCE_HEADERS page
And place at top of your page
If no Licence is Selected/Appended, Default will be CC0

Default Licence IF there is no Licence placed below this notice! When you edit this page, you agree to release your contribution under the CC0 Licence

LICENCE: More information about the cc0 licence can be found here:
https://creativecommons.org/share-your-work/public-domain/cc0

The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.

You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.

Licence:

Statement of Purpose

The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").

Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.

For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.

1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:

   the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
   moral rights retained by the original author(s) and/or performer(s);
   publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
   rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
   rights protecting the extraction, dissemination, use and reuse of data in a Work;
   database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
   other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.

2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.

3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.

4. Limitations and Disclaimers.

   No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
   Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
   Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
   Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.


Installing LXD

sudo snap install lxd
lxd init
Selecting all defaults, apart from "Size in GB of the new loop device (1GB minimum) [default=6GB]:" increasing to 30GB:

lxd init selected options:

Would you like to use LXD clustering? (yes/no) [default=no]:
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Name of the new storage pool [default=default]:
Name of the storage backend to use (btrfs, dir, lvm, zfs, ceph) [default=zfs]:
Create a new ZFS pool? (yes/no) [default=yes]:
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:
Size in GB of the new loop device (1GB minimum) [default=6GB]:30GB
Would you like to connect to a MAAS server? (yes/no) [default=no]:
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]:
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like the LXD server to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:

Create Ubuntu:22.04 Container for MediaWiki

lxc launch ubuntu:22.04 mediawiki

lxc list

+-----------+---------+--------------------+------+-----------+-----------+
|   NAME    |  STATE  |        IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+-----------+---------+--------------------+------+-----------+-----------+
| mediawiki | RUNNING | 10.194.171.251(eth0) |      | CONTAINER | 0         |
+-----------+---------+--------------------+------+-----------+-----------+

Login to Container

lxc exec mediawiki bash

Basic Firewall UFW for Container

NOTE:Add Link to a UFW page for more info

Blocking IPv6
$EDITOR /etc/default/ufw

Change the line
IPV6=yes
To
IPV6=no
Save and Exit

Allow port 80
ufw allow 80/tcp
Allow port 443
ufw allow 443/tcp
Start/Enable UFW firewall
ufw enable
Check UFW status
ufw status

If you Entered wrong port number and would like to change/delete rule:

delete a UFW rule you made by mistake.
ufw delete allow 433/tcp
Or you can use a numbered rule list.
ufw status numbered
Will list rules by number.
ufw delete <RULE_NUMBER>
ufw delete 2

Now re-enter rule to allow correct port number and protocol.


Update system

apt update && apt upgrade -y


ssmtp setup

NOTE: need link to ssmtp page - showing how to use other email providers that allow smtp Link to ssmtp wiki page
You can use a number of email providers for sending emails from server using ssmtp.
I am going to use smtp2go.com they do provide a free service if you wish to try.

smtp2go details:

https://www.smtp2go.com/
Has a Free Plan

  1. 1000 emails per month
  2. 5 days of email reporting
  3. Ticket support only


Do not use you username and password you used to sign up!
Go to https://app.smtp2go.com/sending/smtp_users/
Or 'Sending' > 'SMTP Users'
And create/add a SMTP User account.
The User created will be given a good password by default.
Use this username and password for ssmtp.
In this example i have the username "noobwiki" and the password "N0tTelinu"

ssmtp

apt install ssmtp -y

$EDITOR /etc/ssmtp/ssmtp.conf

mailhub=mail.smtp2go.com:587
AuthUser=noobwiki
AuthPass=N0tTelinu
UseSTARTTLS=YES
FromLineOverride=YES
hostname=completenoobs.com

Why use hostname=completenoobs.com

"hostname" needed for ubuntu unattended upgrades to send email.
If missing: will get "(550 unable to verify sender address.)"
If using hostname=localhost "(550 "Localhost" unnaceptable, you must use a public domain-name.)"
If using hostname=admin@completenoobs.com "501 <root@admin@completenoobs.com>: malformed address: @completenoobs.com> may not follow <root@admin"


Do not use user@smtp2go.com as the sender address! you need an email address that has an MX record(mail exchanger record) at its domain name.
$EDITOR /etc/ssmtp/revaliases

root:admin@completenoobs.com:mail.smtp2go.com:587

usermod


usermod can be used to change the email senders name/address.
Instead of your mail coming from 'root' or 'ubuntu' or any other user account.
usermod -c "emailSenderName" <account_sending>
usermod -c "completenoobslxc" root

Send Test eMail
Create a file and add subject header and some content.
$EDITOR test-mail.txt

Subject:test email

Hello You.


Save and Exit
Now send the email:
sendmail email@address2receive.mail < test-mail.txt
Don't forget to check your spam folder if you don't see email
Once tested and email sent, you can delete test-mail.txt.
rm test-mail.txt

sendmail notes

If the sendmail command locks your terminal and CTRL+c does not work

Use CTRL+z which will send a SIGTSTP signal which will put the process to sleep.
use jobs to see the sleeping process.
jobs
and kill %<JOBNUMBER>
kill %1
you can also use ps ax to list processes running on your computer and kill -9 <PROCESS-NUMBER> to kill process.

sendmail in verbose mode for more details:

More info can be found in the man page man sendmail
Use the verbose flag -v
sendmail -v email@address2receive.mail < test-mail.txt

Check mail logs for errors:

send mail error log can be found in
/var/log/mail.err
and sendmail log can be found:
/var/log/mail.log

auto update container config

$EDITOR /etc/apt/apt.conf.d/50unattended-upgrades

Uncomment
// "${distro_id}:${distro_codename}-updates";
"${distro_id}:${distro_codename}-updates";

Dont need auto reboot on container - no kernel - kernel shared with host.



email on update

$EDITOR /etc/apt/apt.conf.d/50unattended-upgrades
Add email address to send email to:

//Unattended-Upgrade::Mail "";
Unattended-Upgrade::Mail "email@tosendto.com";

We are going to test are send mail, so for now change MailReport to "always"

//Unattended-Upgrade::MailReport "on-change";
Unattended-Upgrade::MailReport "always";

Once i needed 'apticron' to get emails working with unattended upgrades:

Notes here just incase

Install apticron
apt install apticron -y

Create apticron.conf file containing email to send email to:
If you dont then 'apticron' will by default sent to root@localhost.
echo 'EMAIL="email@tosendto.com"' > /etc/apticron/apticron.conf

Test with debug flag -d
unattended-upgrade -d

Once email alerts from auto updates has been tested and working, change MailReport back from 'always' to 'on-change', unless you want to be emailed at every update.


Install MediaWiki

apt install apache2 mysql-server php php-mysql libapache2-mod-php php-xml php-mbstring php-intl -y

wget https://releases.wikimedia.org/mediawiki/1.39/mediawiki-1.39.2.tar.gz

tar -xvf mediawiki-1.39.2.tar.gz

mv mediawiki-1.39.2 /var/www/html/mediawiki

Create Database

Will be prompted to set a root password!
mysql -u root -p

CREATE USER 'green'@'localhost' IDENTIFIED BY 'THISpasswordSHOULDbeCHANGED';

CREATE DATABASE mywiki_database;

use mywiki_database;

GRANT ALL ON mywiki_database.* TO 'green'@'localhost';

quit;

Make note of your: database name, username, userpassword

CREATE USER 'green'@'localhost' IDENTIFIED BY 'THISpasswordSHOULDbeCHANGED';
Database Username:green
Database host/location:localhost Database User Password:THISpasswordSHOULDbeCHANGED

CREATE DATABASE mywiki_database;
Database Name:mywiki_database

Create self-signed https certs

openssl req -x509 -newkey rsa:4096 -keyout key.pem -nodes -out cert.pem -days 365
Note: can leave blank; just press enter.

mv cert.pem /etc/ssl/certs/cn-selfsigned.crt
mv key.pem /etc/ssl/private/cn-selfsigned.key

Create ssl-params.conf

$EDITOR /etc/apache2/conf-available/ssl-params.conf

Remember to turn stapling on after letsencrypt cert

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
# Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
# Requires Apache >= 2.4
SSLCompression off
# May want to turn stapling off when using self-signed to avoid receiving errors in log
SSLUseStapling off
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Requires Apache >= 2.4.11
SSLSessionTickets Off

Create Apache2 config

cd /etc/apache2/sites-available/

rm 000-default.conf default-ssl.conf

$EDITOR /etc/apache2/sites-available/completenoobs.com.conf


Important Redirect note:
    # Redirect Requests to SSL
    Redirect permanent "/" "https://IPADDRESS"

Change to your Container IP!
Redirect permanent "/" "https://10.194.171.251"

<VirtualHost *:80>

    ServerName completenoobs.com
    ServerAdmin admin@

    # Redirect Requests to SSL
    Redirect permanent "/" "https://IPADDRESS"

    ErrorLog ${APACHE_LOG_DIR}/completenoobs.com.error.log
    CustomLog ${APACHE_LOG_DIR}/completenoobs.com.access.log combined

</VirtualHost>

<IfModule mod_ssl.c>

    <VirtualHost _default_:443>

            ServerName completenoobs.com
            ServerAdmin admin@completenoobs.com
            DocumentRoot /var/www/html/mediawiki
            # According MWiki Manual:Security
            php_flag register_globals off

            ErrorLog ${APACHE_LOG_DIR}/completenoobs.com.error.log
            CustomLog ${APACHE_LOG_DIR}/completenoobs.com.access.log combined

            SSLEngine on
            SSLCertificateFile /etc/ssl/certs/cn-selfsigned.crt
            SSLCertificateKeyFile  /etc/ssl/private/cn-selfsigned.key
            # need to find out what SSLCertificateChainFile is? explain is in the default-ssl.conf file.
            #SSLCertificateChainFile /etc/ssl/certs/example.com.root-bundle.crt

            <FilesMatch "\.(cgi|shtml|phtml|php)$">
                    SSLOptions +StdEnvVars
            </FilesMatch>

            <Directory /usr/lib/cgi-bin>
                    SSLOptions +StdEnvVars
            </Directory>

            <Directory /var/www/html/wikimedia>
                    Options None FollowSymLinks
                    #Allow .htaccess
                    AllowOverride All
                    Require all granted
                    <IfModule security2_module>
                            SecRuleEngine Off
                            # or disable only problematic rules
                    </IfModule>
            </Directory>

            # According to MWiki Manual:Security
            <Directory /var/www/html/wikimedia/images>
                    # Ignore .htaccess files
                    AllowOverride None
                    # Serve HTML as plaintext, don't execute SHTML
                    AddType text/plain .html .htm .shtml .php .phtml .php5
                    # Don't run arbitrary PHP code.
                    php_admin_flag engine off
                    # If you've other scripting languages, disable them too.
            </Directory>

            #According to MWiki Manual:Security
            <Directory /var/www/html/wikimedia/images/deleted>
                    Deny from all
                    AllowOverride AuthConfig Limit
                    Require local
            </Directory>

    </VirtualHost>

</IfModule>

Reload Apache2

a2enmod ssl

a2enmod headers

a2ensite completenoobs.com

a2enconf ssl-params

apache2ctl configtest

systemctl restart apache2

MediaWiki Basic Setup

Landing page

Open a web browser and go to your containers private ip address (you can get ip address by running lxc list on host).

https://10.194.171.251

Are certs are self-signed and you may/will get warning "your connection is not private"
Click "Advance" and "Proceed to 10.194.171.251 (unsafe)"

You will now find yourself on the mediawiki setup landing page.

MediaWiki 1.35.0
LocalSettings.php not found.
Please set up the wiki first.

Click set up the wiki to be taken to the "mw-config/index.php" page.


Basic Configure MediaWiki

Language Page

Just pick a language mate

Welcome to MediaWiki!

read and click Continue

Connect to database - going to need the details from when you created the database.

Database host:localhost
Database name:mywiki_database
Database table prefix (no hyphens): LEAVE BLANK
Database username:green
Database password:THISpasswordSHOULDbeCHANGED

Database Settings

Database account for web access
[x]Use the same account as for installation
Leave ticked

Name

Name of wiki:CompleteNoobs
Project namespace:
[x]Same as the wiki name:
[ ]Project
[ ]Other (specify)
Administrator account Will be the admin account on the wiki.

Options

User rights profile:
[ ] Open wiki
[x] Account creation required
[ ] Authorised editors only
[ ] Private wiki

Copyright and licence:
[ ] Creative Commons Attribution
[ ] Creative Commons Attribution-ShareAlike
[ ] Creative Commons Attribution-NonCommercial-ShareAlike
[ ] Creative Commons Zero (Public Domain)
[ ] GNU Free Documentation Licence 1.3 or later
[x] No licence footer
[ ] Select a custom Creative Commons licence


Email settings
[ ] Enable outbound email
Return email address:apache@🌻.invalid
[ ]Enable user-to-user email
[ ]Enable user talk page notification
[ ]Enable watchlist notification
[ ]Enable email authentication


Skins Pick a skin


Extensions
Special pages
[ ]CiteThisPage
[ ]Interwiki
[ ]Nuke
[ ]Renameuser
[ ]ReplaceText

Editors
[x]CodeEditor
[x]VisualEditor
[x]WikiEditor

Parser hooks
[ ]CategoryTree
[ ]Cite
[ ]ImageMap
[ ]InputBox
[ ]ParserFunctions
[ ]Poem
[ ]Scribunto
[x]SyntaxHighlight_GeSHi
[ ]TemplateData

Media handlers
[ ]PdfHandler

Spam prevention
[x]ConfirmEdit
[ ]SpamBlacklist
[ ]TitleBlacklist

API
[ ]PageImages

Other
[ ]Gadgets
[ ]LocalisationUpdate
[ ]MultimediaViewer
[ ]OATHAuth
[ ]SecureLinkFixer
[ ]TextExtracts


Images and file uploads
[ ]Enable file uploads
Logo URL:$wgResourceBasePath/resources/assets/wiki.png
[ ]Enable Instant Commons


Advanced configuration
Settings for object caching:
[x] No caching (no functionality is removed, but speed may be impacted on larger wiki sites)
[ ] Use Memcached (requires additional setup and configuration)

LocalSettings.php Launch Wiki

When the Basic configuration of mediawiki is done on the webpage.
You will have a LocalSettings.php which will be downloaded from your browser.
You need to place the LocalSettings.php file into your containers /var/www/html/mediawiki/ directory.
You can do this from host using the lxc file push command.
lxc file push /home/$USER/Downloads/LocalSettings.php mediawiki/var/www/html/mediawiki/

Do not refresh browser it will download the LocalSettings.php again! go to the IP address of your container or just trim the mw-config/index.php?page=Complete
Now on your browser visit the page again https://10.194.171.251


And welcome to your wiki.

You need a 135px by 135px image, in this example its named 'completenoobs-logo.png'
lxc file push completenoobs-logo.png mediawiki/var/www/html/mediawiki/resources/assets/
Back in container edit the LocalSettings.php file

## The URL paths to the logo.  Make sure you change this from the default,
## or else you'll overwrite your logo when you upgrade!
$wgLogos = [
        '1x' => "$wgResourceBasePath/resources/assets/change-your-logo.svg",
        'icon' => "$wgResourceBasePath/resources/assets/change-your-logo.svg",
];

Change to your new logo:

$wgLogos = [
        '1x' => "$wgResourceBasePath/resources/assets/completenoobs-logo.png",
        'icon' => "$wgResourceBasePath/resources/assets/completenoobs-logo.png",
];

Email Config

Warning i did get loads of spam bots, using this to send naughty emails everywhere!
Changed setting to block signups, requests only,and changed $wgEnableUserEmail to false and still the bots managed to send spam using my smtp account.
How they done this? Is beyond my understanding and i removed email from the wiki till i have more info on how to stop the spamming.
Was using mediawiki-1.35.0

$EDITOR /var/www/html/mediawiki/LocalSettings.php

Make sure $wgEnableEmail is set to true.
$wgEnableEmail = true;
https://www.mediawiki.org/wiki/Manual:$wgEnableEmail

$wgEmergencyContact = "";
$wgPasswordSender = "";
$wgEmergencyContact = "admin@completenoobs.com";
$wgPasswordSender = "admin@completenoobs.com";
$wgSMTP = [
    'host' => 'ssl://mail.smtp2go.com', // outbox server of the email account
    'IDHost' => 'completenoobs.com',
    'port' => 465,
    'username' => 'noobwiki', // user of the email account
    'password' => 'N0tTelinu', // app password of the email account
    'auth' => true
];


Request Account and Confirm Email to edit

In LocalSettings change $wgEmailAuthentication = false; to true

https://www.mediawiki.org/wiki/Manual:$wgEmailAuthentication
https://www.mediawiki.org/wiki/Extension:ConfirmAccount

wget https://extdist.wmflabs.org/dist/extensions/ConfirmAccount-REL1_39-2b96e90.tar.gz
tar xzf ConfirmAccount-REL1_39-2b96e90.tar.gz -C /var/www/html/mediawiki/extensions/

In LocalSettings.php
set $wgEmailAuthentication to true.

wfLoadExtension( 'ConfirmAccount' );  
$wgConfirmAccountContact = 'admin@completenoobs.com'; 

Run maintenance update
php /var/www/html/mediawiki/maintenance/update.php
use Special:ConfirmAccounts to see if anyone requested a account.
And yep, your gonna get spammed! Bots love a wiki.

CookieWarning Extension

https://www.mediawiki.org/wiki/Extension:CookieWarning
wget https://extdist.wmflabs.org/dist/extensions/CookieWarning-REL1_39-778fe72.tar.gz
tar -xzf CookieWarning-REL1_39-778fe72.tar.gz -C /var/www/html/mediawiki/extensions/
In LocalSettings.php add:

wfLoadExtension( 'CookieWarning' );
$wgCookieWarningEnabled = 'true';
# $wgCookieWarningMoreUrl allows to to select a link for your moreinfo button
$wgCookieWarningMoreUrl = 'https://www.completenoobs.com/link';
$wgCookieWarningEnabled = 'true';

To change message sign in with admin account and visit these pages of your wiki and edit.
MediaWiki:Cookiewarning-info Edit the display message.
https://10.194.171.251/index.php/MediaWiki:Cookiewarning-info
MediaWiki:Cookiewarning-moreinfo-label
Edit and change display of the moreinfo button: link can be made/changed at LocalSettings with:
$wgCookieWarningMoreUrl = 'https://www.completenoobs.com/link'
https://10.194.171.251/index.php/MediaWiki:Cookiewarning-moreinfo-label
MediaWiki:Cookiewarning-ok-label Edit and change the text on the OK button.
https://10.194.171.251/index.php/MediaWiki:Cookiewarning-ok-label

Contribution Scores Extension

https://www.mediawiki.org/wiki/Extension:Contribution_Scores
wget https://extdist.wmflabs.org/dist/extensions/ContributionScores-REL1_39-0e7e99d.tar.gz
tar -xzf ContributionScores-REL1_39-0e7e99d.tar.gz -C /var/www/html/mediawiki/extensions
In LocalSettings.php add:

wfLoadExtension( 'ContributionScores' );
// Exclude Bots from the reporting - Can be omitted.
$wgContribScoreIgnoreBots = true; 
// Exclude Blocked Users from the reporting - Can be omitted.
$wgContribScoreIgnoreBlockedUsers = true;
// Use real user names when available - Can be omitted. Only for MediaWiki 1.19 and later.
$wgContribScoresUseRealName = true;
// Set to true to disable cache for parser function and inclusion of table.
$wgContribScoreDisableCache = false;       
// Each array defines a report - 7,50 is "past 7 days" and "LIMIT 50" - Can be omitted.
$wgContribScoreReports = [
    [ 7, 50 ],
    [ 30, 50 ],
    [ 0, 50 ]
];


Add to Main Landing Page:

{{Special:ContributionScores/10/5}}



Place Notice at top of every new page created

Using the PageNotice Extension.

https://www.mediawiki.org/wiki/Extension:PageNotice#Configuration

Download PageNotice and extract to extensions directory.

in LocalSettings.php add the lines:

wfLoadExtension( 'PageNotice' );
$wgPageNoticeDisablePerPageNotices = 'true';

To have message in every name space go to your wiki's page
index.php/mediawiki:top-notice-ns-0
Only admin account can edit this page:
What you place in this page will be displayed at the top of every page created.


Privacy Policy

Holly $#$#$ this is a lot of work, looking into it
https://www.mediawiki.org/wiki/GDPR_(General_Data_Protection_Regulation)_and_MediaWiki_software

NewSignupPage

https://www.mediawiki.org/wiki/Extension:NewSignupPage
Big thanks to Shoutwiki.com or this would of been a very big pain.

Check for Latest link from the Download page https://www.mediawiki.org/wiki/Special:ExtensionDistributor/NewSignupPage
In mediawiki container:
wget https://extdist.wmflabs.org/dist/extensions/NewSignupPage-REL1_35-ecf00aa.tar.gz

tar xvf NewSignupPage-REL1_35-ecf00aa.tar.gz -C /var/www/html/mediawiki/extensions/

$EDITOR /var/www/html/mediawiki/LocalSettings.php
Add the Line:
wfLoadExtension( 'NewSignupPage' );
Change the Info given at signup at:
index.php/MediaWiki:Newsignuppage-loginform-tos

Default page will be:

I am over 13 years of age and I have read, understood and agree to be bound by the Terms of Service and Privacy Policy

"Terms of Service" and "Privacy Policy" are linked to there pages, so we need to create a few pages.

Need Privacy Policy Page

Create a 'Privacy_Policy' page and link on "MediaWiki:Newsignuppage-loginform-tos"

[[CompleteNoobs:Privacy_policy | Privacy Policy]]
Need Terms Of Service page

https://www.completenoobs.com/index.php/Terms_of_Service

once done change link on "MediaWiki:Newsignuppage-loginform-tos"

Content Policy Page

https://10.194.171.251/index.php/Content_Policy
Contains link to https://www.completenoobs.com/index.php/CompleteNoobs_Staff_Admins

Staff and Admin Page

https://10.194.171.251/index.php/CompleteNoobs_Staff_Admins

Linked from Content Policy Page! a place to contact by email staff, admins

General Disclaimer page

https://10.194.171.251/index.php/CompleteNoobs:General_disclaimer
This page shows/linked at bottom of wiki

Copyright Policy

https://10.194.171.251/index.php/CompleteNoobs:Copyrights
Copyrights page that shows in info box when making a post.

Fail2Ban

This Will Ban an IP who incorrectly enters wrong login details, a (you can select) amount of times for a (you can select) amount of time.

Fail2Log Extension

https://www.mediawiki.org/wiki/Extension:Fail2Log

Create Log file

Could not get PHP to create and set permissions for log file: So for now doing manually!
touch /var/log/Fail2Log.log
chown www-data:www-data /var/log/Fail2Log.log
chmod 0755 /var/log/Fail2Log.log
Failed login's with wrong user name and/or password should now be logged in:/var/log/Fail2Log.log

Log Format:
Failed:<IP_ADDRESS> <DATE>

Download and install extension

wget https://github.com/greenhatmonkey/Fail2Log/blob/main/Fail2Log.tar.gz?raw=true
tar xzvf Fail2Log.tar.gz?raw=true -C /var/www/html/mediawiki/extensions/
Add to your LocalSettings.php

wfLoadExtension( 'Fail2Log' );
$wgFail2LogFile = '/var/log/Fail2Log.log';

Install and Setup Fail2Ban

Fail2Ban works in a container. If using fail2ban on Host for container:
Just include log path: /var/snap/lxd/common/mntns/var/snap/lxd/common/lxd/storage-pools/default/containers/<CONTAINER_NAME>/rootfs/var/log/Fail2Log.log

apt install fail2ban

  • Fail2ban will use file.local over file.conf if file.local exists:
  • file.conf can be written over if file2ban gets updated.
  • Make a file.local of the file you are working on.


cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

$EDITOR /etc/fail2ban/jail.local

Default /etc/fail2ban/jail.conf file: Expand to view

#
# WARNING: heavily refactored in 0.9.0 release.  Please review and
#          customize settings for your setup.
#
# Changes:  in most of the cases you should not modify this
#           file, but provide customizations in jail.local file,
#           or separate .conf files under jail.d/ directory, e.g.:
#
# HOW TO ACTIVATE JAILS:
#
# YOU SHOULD NOT MODIFY THIS FILE.
#
# It will probably be overwritten or improved in a distribution update.
#
# Provide customizations in a jail.local file or a jail.d/customisation.local.
# For example to change the default bantime for all jails and to enable the
# ssh-iptables jail the following (uncommented) would appear in the .local file.
# See man 5 jail.conf for details.
#
# [DEFAULT]
# bantime = 1h
#
# [sshd]
# enabled = true
#
# See jail.conf(5) man page for more information



# Comments: use '#' for comment lines and ';' (following a space) for inline comments


[INCLUDES]

#before = paths-distro.conf
before = paths-debian.conf

# The DEFAULT allows a global definition of the options. They can be overridden
# in each jail afterwards.

[DEFAULT]

#
# MISCELLANEOUS OPTIONS
#

# "bantime.increment" allows to use database for searching of previously banned ip's to increase a 
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
#bantime.increment = true

# "bantime.rndtime" is the max number of seconds using for mixing with random time 
# to prevent "clever" botnets calculate exact time IP can be unbanned again:
#bantime.rndtime = 

# "bantime.maxtime" is the max number of seconds using the ban time can reach (don't grows further)
#bantime.maxtime = 

# "bantime.factor" is a coefficient to calculate exponent growing of the formula or common multiplier,
# default value of factor is 1 and with default value of formula, the ban time 
# grows by 1, 2, 4, 8, 16 ...
#bantime.factor = 1

# "bantime.formula" used by default to calculate next value of ban time, default value bellow,
# the same ban time growing will be reached by multipliers 1, 2, 4, 8, 16, 32...
#bantime.formula = ban.Time * (1<<(ban.Count if ban.Count<20 else 20)) * banFactor
#
# more aggressive example of formula has the same values only for factor "2.0 / 2.885385" :
#bantime.formula = ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)

# "bantime.multipliers" used to calculate next value of ban time instead of formula, coresponding 
# previously ban count and given "bantime.factor" (for multipliers default is 1);
# following example grows ban time by 1, 2, 4, 8, 16 ... and if last ban count greater as multipliers count, 
# always used last multiplier (64 in example), for factor '1' and original ban time 600 - 10.6 hours
#bantime.multipliers = 1 2 4 8 16 32 64
# following example can be used for small initial ban time (bantime=60) - it grows more aggressive at begin,
# for bantime=60 the multipliers are minutes and equal: 1 min, 5 min, 30 min, 1 hour, 5 hour, 12 hour, 1 day, 2 day
#bantime.multipliers = 1 5 30 60 300 720 1440 2880

# "bantime.overalljails" (if true) specifies the search of IP in the database will be executed 
# cross over all jails, if false (dafault), only current jail of the ban IP will be searched
#bantime.overalljails = false

# --------------------

# "ignoreself" specifies whether the local resp. own IP addresses should be ignored
# (default is true). Fail2ban will not ban a host which matches such addresses.
#ignoreself = true

# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
#ignoreip = 127.0.0.1/8 ::1

# External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise.
#
# ignorecommand = /path/to/command <ip>
ignorecommand =

# "bantime" is the number of seconds that a host is banned.
bantime  = 10m

# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime  = 10m

# "maxretry" is the number of failures before a host get banned.
maxretry = 5

# "maxmatches" is the number of matches stored in ticket (resolvable via tag <matches> in actions).
maxmatches = %(maxretry)s

# "backend" specifies the backend used to get files modification.
# Available options are "pyinotify", "gamin", "polling", "systemd" and "auto".
# This option can be overridden in each jail as well.
#
# pyinotify: requires pyinotify (a file alteration monitor) to be installed.
#              If pyinotify is not installed, Fail2ban will use auto.
# gamin:     requires Gamin (a file alteration monitor) to be installed.
#              If Gamin is not installed, Fail2ban will use auto.
# polling:   uses a polling algorithm which does not require external libraries.
# systemd:   uses systemd python library to access the systemd journal.
#              Specifying "logpath" is not valid for this backend.
#              See "journalmatch" in the jails associated filter config
# auto:      will try to use the following backends, in order:
#              pyinotify, gamin, polling.
#
# Note: if systemd backend is chosen as the default but you enable a jail
#       for which logs are present only in its own log files, specify some other
#       backend for that jail (e.g. polling) and provide empty value for
#       journalmatch. See https://github.com/fail2ban/fail2ban/issues/959#issuecomment-74901200
backend = auto

# "usedns" specifies if jails should trust hostnames in logs,
#   warn when DNS lookups are performed, or ignore all hostnames in logs
#
# yes:   if a hostname is encountered, a DNS lookup will be performed.
# warn:  if a hostname is encountered, a DNS lookup will be performed,
#        but it will be logged as a warning.
# no:    if a hostname is encountered, will not be used for banning,
#        but it will be logged as info.
# raw:   use raw value (no hostname), allow use it for no-host filters/actions (example user)
usedns = warn

# "logencoding" specifies the encoding of the log files handled by the jail
#   This is used to decode the lines from the log file.
#   Typical examples:  "ascii", "utf-8"
#
#   auto:   will use the system locale setting
logencoding = auto

# "enabled" enables the jails.
#  By default all jails are disabled, and it should stay this way.
#  Enable only relevant to your setup jails in your .local or jail.d/*.conf
#
# true:  jail will be enabled and log files will get monitored for changes
# false: jail is not enabled
enabled = false


# "mode" defines the mode of the filter (see corresponding filter implementation for more info).
mode = normal

# "filter" defines the filter to use by the jail.
#  By default jails have names matching their filter name
#
filter = %(__name__)s[mode=%(mode)s]


#
# ACTIONS
#

# Some options used for actions

# Destination email address used solely for the interpolations in
# jail.{conf,local,d/*} configuration files.
destemail = root@localhost

# Sender email address used solely for some actions
sender = root@<fq-hostname>

# E-mail action. Since 0.8.1 Fail2Ban uses sendmail MTA for the
# mailing. Change mta configuration parameter to mail if you want to
# revert to conventional 'mail'.
mta = sendmail

# Default protocol
protocol = tcp

# Specify chain where jumps would need to be added in ban-actions expecting parameter chain
chain = <known/chain>

# Ports to be banned
# Usually should be overridden in a particular jail
port = 0:65535

# Format of user-agent https://tools.ietf.org/html/rfc7231#section-5.5.3
fail2ban_agent = Fail2Ban/%(fail2ban_version)s

#
# Action shortcuts. To be used to define action parameter

# Default banning action (e.g. iptables, iptables-new,
# iptables-multiport, shorewall, etc) It is used to define
# action_* variables. Can be overridden globally or per
# section within jail.local file
banaction = iptables-multiport
banaction_allports = iptables-allports

# The simplest action to take: ban only
action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report to the destemail.
action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
            %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

# ban & send an e-mail with whois report and relevant log lines
# to the destemail.
action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# See the IMPORTANT note in action.d/xarf-login-attack for when to use this action
#
# ban & send a xarf e-mail to abuse contact of IP address and include relevant log lines
# to the destemail.
action_xarf = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]

# ban IP on CloudFlare & send an e-mail with whois report and relevant log lines
# to the destemail.
action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

# Report block via blocklist.de fail2ban reporting service API
# 
# See the IMPORTANT note in action.d/blocklist_de.conf for when to use this action.
# Specify expected parameters in file action.d/blocklist_de.local or if the interpolation
# `action_blocklist_de` used for the action, set value of `blocklist_de_apikey`
# in your `jail.local` globally (section [DEFAULT]) or per specific jail section (resp. in 
# corresponding jail.d/my-jail.local file).
#
action_blocklist_de  = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]

# Report ban via badips.com, and use as blacklist
#
# See BadIPsAction docstring in config/action.d/badips.py for
# documentation for this action.
#
# NOTE: This action relies on banaction being present on start and therefore
# should be last action defined for a jail.
#
action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
#
# Report ban via badips.com (uses action.d/badips.conf for reporting only)
#
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]

# Report ban via abuseipdb.com.
#
# See action.d/abuseipdb.conf for usage example and details.
#
action_abuseipdb = abuseipdb

# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s


#
# JAILS
#

#
# SSH servers
#

[sshd]

# To use more aggressive sshd modes set filter parameter "mode" in jail.local:
# normal (default), ddos, extra or aggressive (combines all).
# See "tests/files/logs/sshd" or "filter.d/sshd.conf" for usage example and details.
#mode   = normal
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s


[dropbear]

port     = ssh
logpath  = %(dropbear_log)s
backend  = %(dropbear_backend)s


[selinux-ssh]

port     = ssh
logpath  = %(auditd_log)s


#
# HTTP servers
#

[apache-auth]

port     = http,https
logpath  = %(apache_error_log)s


[apache-badbots]
# Ban hosts which agent identifies spammer robots crawling the web
# for email addresses. The mail outputs are buffered.
port     = http,https
logpath  = %(apache_access_log)s
bantime  = 48h
maxretry = 1


[apache-noscript]

port     = http,https
logpath  = %(apache_error_log)s


[apache-overflows]

port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2


[apache-nohome]

port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2


[apache-botsearch]

port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2


[apache-fakegooglebot]

port     = http,https
logpath  = %(apache_access_log)s
maxretry = 1
ignorecommand = %(ignorecommands_dir)s/apache-fakegooglebot <ip>


[apache-modsecurity]

port     = http,https
logpath  = %(apache_error_log)s
maxretry = 2


[apache-shellshock]

port    = http,https
logpath = %(apache_error_log)s
maxretry = 1


[openhab-auth]

filter = openhab
action = iptables-allports[name=NoAuthFailures]
logpath = /opt/openhab/logs/request.log


[nginx-http-auth]

port    = http,https
logpath = %(nginx_error_log)s

# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module` 
# and define `limit_req` and `limit_req_zone` as described in nginx documentation
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
# or for example see in 'config/filter.d/nginx-limit-req.conf'
[nginx-limit-req]
port    = http,https
logpath = %(nginx_error_log)s

[nginx-botsearch]

port     = http,https
logpath  = %(nginx_error_log)s
maxretry = 2


# Ban attackers that try to use PHP's URL-fopen() functionality
# through GET/POST variables. - Experimental, with more than a year
# of usage in production environments.

[php-url-fopen]

port    = http,https
logpath = %(nginx_access_log)s
          %(apache_access_log)s


[suhosin]

port    = http,https
logpath = %(suhosin_log)s


[lighttpd-auth]
# Same as above for Apache's mod_auth
# It catches wrong authentifications
port    = http,https
logpath = %(lighttpd_error_log)s


#
# Webmail and groupware servers
#

[roundcube-auth]

port     = http,https
logpath  = %(roundcube_errors_log)s
# Use following line in your jail.local if roundcube logs to journal.
#backend = %(syslog_backend)s


[openwebmail]

port     = http,https
logpath  = /var/log/openwebmail.log


[horde]

port     = http,https
logpath  = /var/log/horde/horde.log


[groupoffice]

port     = http,https
logpath  = /home/groupoffice/log/info.log


[sogo-auth]
# Monitor SOGo groupware server
# without proxy this would be:
# port    = 20000
port     = http,https
logpath  = /var/log/sogo/sogo.log


[tine20]

logpath  = /var/log/tine20/tine20.log
port     = http,https


#
# Web Applications
#
#

[drupal-auth]

port     = http,https
logpath  = %(syslog_daemon)s
backend  = %(syslog_backend)s

[guacamole]

port     = http,https
logpath  = /var/log/tomcat*/catalina.out

[monit]
#Ban clients brute-forcing the monit gui login
port = 2812
logpath  = /var/log/monit
           /var/log/monit.log


[webmin-auth]

port    = 10000
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s


[froxlor-auth]

port    = http,https
logpath  = %(syslog_authpriv)s
backend  = %(syslog_backend)s


#
# HTTP Proxy servers
#
#

[squid]

port     =  80,443,3128,8080
logpath = /var/log/squid/access.log


[3proxy]

port    = 3128
logpath = /var/log/3proxy.log


#
# FTP servers
#


[proftpd]

port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(proftpd_log)s
backend  = %(proftpd_backend)s


[pure-ftpd]

port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(pureftpd_log)s
backend  = %(pureftpd_backend)s


[gssftpd]

port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(syslog_daemon)s
backend  = %(syslog_backend)s


[wuftpd]

port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(wuftpd_log)s
backend  = %(wuftpd_backend)s


[vsftpd]
# or overwrite it in jails.local to be
# logpath = %(syslog_authpriv)s
# if you want to rely on PAM failed login attempts
# vsftpd's failregex should match both of those formats
port     = ftp,ftp-data,ftps,ftps-data
logpath  = %(vsftpd_log)s


#
# Mail servers
#

# ASSP SMTP Proxy Jail
[assp]

port     = smtp,465,submission
logpath  = /root/path/to/assp/logs/maillog.txt


[courier-smtp]

port     = smtp,465,submission
logpath  = %(syslog_mail)s
backend  = %(syslog_backend)s


[postfix]
# To use another modes set filter parameter "mode" in jail.local:
mode    = more
port    = smtp,465,submission
logpath = %(postfix_log)s
backend = %(postfix_backend)s


[postfix-rbl]

filter   = postfix[mode=rbl]
port     = smtp,465,submission
logpath  = %(postfix_log)s
backend  = %(postfix_backend)s
maxretry = 1


[sendmail-auth]

port    = submission,465,smtp
logpath = %(syslog_mail)s
backend = %(syslog_backend)s


[sendmail-reject]
# To use more aggressive modes set filter parameter "mode" in jail.local:
# normal (default), extra or aggressive
# See "tests/files/logs/sendmail-reject" or "filter.d/sendmail-reject.conf" for usage example and details.
#mode    = normal
port     = smtp,465,submission
logpath  = %(syslog_mail)s
backend  = %(syslog_backend)s


[qmail-rbl]

filter  = qmail
port    = smtp,465,submission
logpath = /service/qmail/log/main/current


# dovecot defaults to logging to the mail syslog facility
# but can be set by syslog_facility in the dovecot configuration.
[dovecot]

port    = pop3,pop3s,imap,imaps,submission,465,sieve
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s


[sieve]

port   = smtp,465,submission
logpath = %(dovecot_log)s
backend = %(dovecot_backend)s


[solid-pop3d]

port    = pop3,pop3s
logpath = %(solidpop3d_log)s


[exim]
# see filter.d/exim.conf for further modes supported from filter:
#mode = normal
port   = smtp,465,submission
logpath = %(exim_main_log)s


[exim-spam]

port   = smtp,465,submission
logpath = %(exim_main_log)s


[kerio]

port    = imap,smtp,imaps,465
logpath = /opt/kerio/mailserver/store/logs/security.log


#
# Mail servers authenticators: might be used for smtp,ftp,imap servers, so
# all relevant ports get banned
#

[courier-auth]

port     = smtp,465,submission,imap,imaps,pop3,pop3s
logpath  = %(syslog_mail)s
backend  = %(syslog_backend)s


[postfix-sasl]

filter   = postfix[mode=auth]
port     = smtp,465,submission,imap,imaps,pop3,pop3s
# You might consider monitoring /var/log/mail.warn instead if you are
# running postfix since it would provide the same log lines at the
# "warn" level but overall at the smaller filesize.
logpath  = %(postfix_log)s
backend  = %(postfix_backend)s


[perdition]

port   = imap,imaps,pop3,pop3s
logpath = %(syslog_mail)s
backend = %(syslog_backend)s


[squirrelmail]

port = smtp,465,submission,imap,imap2,imaps,pop3,pop3s,http,https,socks
logpath = /var/lib/squirrelmail/prefs/squirrelmail_access_log


[cyrus-imap]

port   = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s


[uwimap-auth]

port   = imap,imaps
logpath = %(syslog_mail)s
backend = %(syslog_backend)s


#
#
# DNS servers
#


# !!! WARNING !!!
#   Since UDP is connection-less protocol, spoofing of IP and imitation
#   of illegal actions is way too simple.  Thus enabling of this filter
#   might provide an easy way for implementing a DoS against a chosen
#   victim. See
#    http://nion.modprobe.de/blog/archives/690-fail2ban-+-dns-fail.html
#   Please DO NOT USE this jail unless you know what you are doing.
#
# IMPORTANT: see filter.d/named-refused for instructions to enable logging
# This jail blocks UDP traffic for DNS requests.
# [named-refused-udp]
#
# filter   = named-refused
# port     = domain,953
# protocol = udp
# logpath  = /var/log/named/security.log

# IMPORTANT: see filter.d/named-refused for instructions to enable logging
# This jail blocks TCP traffic for DNS requests.

[named-refused]

port     = domain,953
logpath  = /var/log/named/security.log


[nsd]

port     = 53
action   = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
           %(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
logpath = /var/log/nsd.log


#
# Miscellaneous
#

[asterisk]

port     = 5060,5061
action   = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
           %(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
           %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
logpath  = /var/log/asterisk/messages
maxretry = 10


[freeswitch]

port     = 5060,5061
action   = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
           %(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]
           %(mta)s-whois[name=%(__name__)s, dest="%(destemail)s"]
logpath  = /var/log/freeswitch.log
maxretry = 10


# enable adminlog; it will log to a file inside znc's directory by default.
[znc-adminlog]

port     = 6667
logpath  = /var/lib/znc/moddata/adminlog/znc.log


# To log wrong MySQL access attempts add to /etc/my.cnf in [mysqld] or
# equivalent section:
# log-warnings = 2
#
# for syslog (daemon facility)
# [mysqld_safe]
# syslog
#
# for own logfile
# [mysqld]
# log-error=/var/log/mysqld.log
[mysqld-auth]

port     = 3306
logpath  = %(mysql_log)s
backend  = %(mysql_backend)s


# Log wrong MongoDB auth (for details see filter 'filter.d/mongodb-auth.conf')
[mongodb-auth]
# change port when running with "--shardsvr" or "--configsvr" runtime operation
port     = 27017
logpath  = /var/log/mongodb/mongodb.log


# Jail for more extended banning of persistent abusers
# !!! WARNINGS !!!
# 1. Make sure that your loglevel specified in fail2ban.conf/.local
#    is not at DEBUG level -- which might then cause fail2ban to fall into
#    an infinite loop constantly feeding itself with non-informative lines
# 2. Increase dbpurgeage defined in fail2ban.conf to e.g. 648000 (7.5 days)
#    to maintain entries for failed logins for sufficient amount of time
[recidive]

logpath  = /var/log/fail2ban.log
banaction = %(banaction_allports)s
bantime  = 1w
findtime = 1d


# Generic filter for PAM. Has to be used with action which bans all
# ports such as iptables-allports, shorewall

[pam-generic]
# pam-generic filter can be customized to monitor specific subset of 'tty's
banaction = %(banaction_allports)s
logpath  = %(syslog_authpriv)s
backend  = %(syslog_backend)s


[xinetd-fail]

banaction = iptables-multiport-log
logpath   = %(syslog_daemon)s
backend   = %(syslog_backend)s
maxretry  = 2


# stunnel - need to set port for this
[stunnel]

logpath = /var/log/stunnel4/stunnel.log


[ejabberd-auth]

port    = 5222
logpath = /var/log/ejabberd/ejabberd.log


[counter-strike]

logpath = /opt/cstrike/logs/L[0-9]*.log
# Firewall: http://www.cstrike-planet.com/faq/6
tcpport = 27030,27031,27032,27033,27034,27035,27036,27037,27038,27039
udpport = 1200,27000,27001,27002,27003,27004,27005,27006,27007,27008,27009,27010,27011,27012,27013,27014,27015
action  = %(banaction)s[name=%(__name__)s-tcp, port="%(tcpport)s", protocol="tcp", chain="%(chain)s", actname=%(banaction)s-tcp]
           %(banaction)s[name=%(__name__)s-udp, port="%(udpport)s", protocol="udp", chain="%(chain)s", actname=%(banaction)s-udp]

[bitwarden]
port    = http,https
logpath = /home/*/bwdata/logs/identity/Identity/log.txt

[centreon]
port    = http,https
logpath = /var/log/centreon/login.log

# consider low maxretry and a long bantime
# nobody except your own Nagios server should ever probe nrpe
[nagios]

logpath  = %(syslog_daemon)s     ; nrpe.cfg may define a different log_facility
backend  = %(syslog_backend)s
maxretry = 1


[oracleims]
# see "oracleims" filter file for configuration requirement for Oracle IMS v6 and above
logpath = /opt/sun/comms/messaging64/log/mail.log_current
banaction = %(banaction_allports)s

[directadmin]
logpath = /var/log/directadmin/login.log
port = 2222

[portsentry]
logpath  = /var/lib/portsentry/portsentry.history
maxretry = 1

[pass2allow-ftp]
# this pass2allow example allows FTP traffic after successful HTTP authentication
port         = ftp,ftp-data,ftps,ftps-data
# knocking_url variable must be overridden to some secret value in jail.local
knocking_url = /knocking/
filter       = apache-pass[knocking_url="%(knocking_url)s"]
# access log of the website with HTTP auth
logpath      = %(apache_access_log)s
blocktype    = RETURN
returntype   = DROP
action       = %(action_)s[blocktype=%(blocktype)s, returntype=%(returntype)s,
                        actionstart_on_demand=false, actionrepair_on_unban=true]
bantime      = 1h
maxretry     = 1
findtime     = 1


[murmur]
# AKA mumble-server
port     = 64738
action   = %(banaction)s[name=%(__name__)s-tcp, port="%(port)s", protocol=tcp, chain="%(chain)s", actname=%(banaction)s-tcp]
           %(banaction)s[name=%(__name__)s-udp, port="%(port)s", protocol=udp, chain="%(chain)s", actname=%(banaction)s-udp]
logpath  = /var/log/mumble-server/mumble-server.log


[screensharingd]
# For Mac OS Screen Sharing Service (VNC)
logpath  = /var/log/system.log
logencoding = utf-8

[haproxy-http-auth]
# HAProxy by default doesn't log to file you'll need to set it up to forward
# logs to a syslog server which would then write them to disk.
# See "haproxy-http-auth" filter for a brief cautionary note when setting
# maxretry and findtime.
logpath  = /var/log/haproxy.log

[slapd]
port    = ldap,ldaps
logpath = /var/log/slapd.log

[domino-smtp]
port    = smtp,ssmtp
logpath = /home/domino01/data/IBM_TECHNICAL_SUPPORT/console.log

[phpmyadmin-syslog]
port    = http,https
logpath = %(syslog_authpriv)s
backend = %(syslog_backend)s


[zoneminder]
# Zoneminder HTTP/HTTPS web interface auth
# Logs auth failures to apache2 error log
port    = http,https
logpath = %(apache_error_log)s

[traefik-auth]
# to use 'traefik-auth' filter you have to configure your Traefik instance,
# see `filter.d/traefik-auth.conf` for details and service example.
port    = http,https
logpath = /var/log/traefik/access.log

Default /etc/fail2ban/jail.local file with (almost all) comments removed:

Default /etc/fail2ban/jail.local with (almost) comments removed:
[INCLUDES]

before = paths-debian.conf


[DEFAULT]

ignorecommand =

bantime  = 10m

findtime  = 10m

maxretry = 5

maxmatches = %(maxretry)s

backend = auto

usedns = warn

logencoding = auto

enabled = false


mode = normal

filter = %(__name__)s[mode=%(mode)s]

#
# ACTIONS
#


destemail = root@localhost

sender = root@<fq-hostname>

mta = sendmail

protocol = tcp

chain = <known/chain>

port = 0:65535

fail2ban_agent = Fail2Ban/%(fail2ban_version)s

banaction = iptables-multiport
banaction_allports = iptables-allports

action_ = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]

action_mw = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
            %(mta)s-whois[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", protocol="%(protocol)s", chain="%(chain)s"]

action_mwl = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

action_xarf = %(banaction)s[name=%(__name__)s, port="%(port)s", protocol="%(protocol)s", chain="%(chain)s"]
             xarf-login-attack[service=%(__name__)s, sender="%(sender)s", logpath="%(logpath)s", port="%(port)s"]

action_cf_mwl = cloudflare[cfuser="%(cfemail)s", cftoken="%(cfapikey)s"]
                %(mta)s-whois-lines[name=%(__name__)s, sender="%(sender)s", dest="%(destemail)s", logpath="%(logpath)s", chain="%(chain)s"]

action_blocklist_de  = blocklist_de[email="%(sender)s", service=%(filter)s, apikey="%(blocklist_de_apikey)s", agent="%(fail2ban_agent)s"]

action_badips = badips.py[category="%(__name__)s", banaction="%(banaction)s", agent="%(fail2ban_agent)s"]
action_badips_report = badips[category="%(__name__)s", agent="%(fail2ban_agent)s"]

action_abuseipdb = abuseipdb

action = %(action_)s

#
# JAILS
#

#
# SSH servers
#

[sshd]

port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Disconnect/kick and ban an ip from list


Just below we are going to append these lines to /etc/fail2ban/jail.local

# Reject/Disconnect Connections that failed username password
_action_tcp_udp = %(banaction)s[name=%(__name__)s-tcp, protocol="tcp", port="%(port)s", blocktype="REJECT --reject-with tcp-reset", chain="%(chain)s", actname=%(banaction)s-tcp]
    %(banaction)s[name=%(__name__)s-udp, protocol="udp", port="%(port)s", blocktype="REJECT --reject-with icmp-port-unreachable", chain="%(chain)s", actname=%(banaction)s-udp]


actionx = %(_action_tcp_udp)s

Before Changes:

# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s


#
# JAILS
#

#
# SSH servers
#

After Changes:

# Choose default action.  To change, just override value of 'action' with the
# interpolation to the chosen action shortcut (e.g.  action_mw, action_mwl, etc) in jail.local
# globally (section [DEFAULT]) or per specific section
action = %(action_)s

# Reject/Disconnect Connections that failed username password
_action_tcp_udp = %(banaction)s[name=%(__name__)s-tcp, protocol="tcp", port="%(port)s", blocktype="REJECT --reject-with tcp-reset", chain="%(chain)s", actname=%(banaction)s-tcp]
    %(banaction)s[name=%(__name__)s-udp, protocol="udp", port="%(port)s", blocktype="REJECT --reject-with icmp-port-unreachable", chain="%(chain)s", actname=%(banaction)s-udp]


actionx = %(_action_tcp_udp)s

#
# JAILS
#

#
# SSH servers
#

Jail for MediaWiki - /etc/fail2ban/jail.local

[mediawiki]

enabled = true
filter = mediawiki
action = iptables-allports
bantime = 1m
maxretry = 2
logpath = /var/log/Fail2Log.log


Before:

#
# JAILS
#

#
# SSH servers
#

After:

#
# JAILS
#
[mediawiki]

enabled = true
filter = mediawiki
action = iptables-allports
bantime = 1h
maxretry = 20
logpath = /var/log/Fail2Log.log
#
# SSH servers
#


Filter for mediawiki

Regex quick up and running tutorial: External Link:(youtube)

This Is a link to a video made by "Corey Schafer".
The best no nonsense up and running regex tut there is.
https://www.youtube.com/watch?v=sa-TUpSx1JA

$EDITOR /etc/fail2ban/filter.d/mediawiki.conf

[Definition]

failregex = ^Failed:<HOST>

ignoreregex =
Try out regex on log file

fail2ban-regex --print-all-matched /var/log/Fail2Log.log /etc/fail2ban/filter.d/mediawiki.conf


Restart Fail2Ban

systemctl restart fail2ban

fail2ban-client status

fail2ban-client status mediawiki

Now test by trying to login to your wiki with wrong password three times.

fail2ban regex and error checking

Check regex:

  • Syntax: fail2ban-regex <logfile> <failregex> <ignoreregex>
    • Example: fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/nginx-correct-up.conf
  • If you want to test ignoreregex enter filter file twice:
    • Example: fail2ban-regex /var/log/nginx/error.log /etc/fail2ban/filter.d/nginx-correct-up.conf /etc/fail2ban/filter.d/nginx-correct-up.conf
  • Read man fail2ban-regex for some more opitions:
  • Examples:
    • -v, --verbose
      • Be verbose in output
    • --print-all-missed
      • Print all missed lines
    • --print-all-ignored
      • Print all ignored lines
    • --print-all-matched
      • Print all matched lines

Debug Fail2Ban:

  • -d dump configuration. For debugging.

fail2ban-client -d

  • --dp, --dump-pretty dump the configuration using more human readable representation.

fail2ban-client --dp

  • will print the systemd log for Fail2Ban.

journalctl -u fail2ban


Change ban time After testing

$EDITOR /etc/fail2ban/jail.local

[mediawiki]

enabled = true
filter = mediawiki
action = iptables-allports
bantime = 1h
maxretry = 20
logpath = /var/log/Fail2Log.log

Unban IP's

Get list of Jails:
fail2ban-client status

See banned ips by that jail:
fail2ban-client status <jailname>

Unban IP from jail:
fail2ban-client set <jailname> unbanip <ip_address>

Log File:
/var/log/Fail2Log.log


Moving To VPS

Create ssh key pair on local host

ssh-keygen -t rsa -b 4096 -C "MYSERVER" -f ~/.ssh/serverkey
You will be prompted to Enter a passphase, you can just press Enter for no passphase.
You will now have a file called serverkey and serverkey.pub in your /home/$USER/.ssh directory.
Now lets setup are server and move public key to server.

BACKUP YOUR PRIVATE KEY TO USB STICK OR SOMETHING!
serverkey.pubPUBLIC KEY
serverkeyPRIVATE KEY

Login to Server - ssh

Using Vultr i am going to deploy a Ubuntu 20.04 Server.
$10, 1 cpu, 2048MB ram, 55GB ssd, 2000GB Bandwidth.
I have been given the IP:192.248.145.129 and the Password:1R?o.gPasdaLz1w and with Vultr the default login/user is root
Lets move over the public key so we don't need a password to login:
ssh-copy-id -i ~/.ssh/serverkey root@192.248.145.129
Will be promted for server password, enter password: 1R?o.gPasdaLz1w
Now lets login with are private key.
ssh -i .ssh/serverkey root@192.248.145.129

Update Server

apt update && apt upgrade -y
The Server may need a restart, you will see this after updates if it does
*** System restart required ***
restart server and log back in after a minute.
reboot

Change default ssh port and disable plain text passwords

Log back into server
ssh -i .ssh/serverkey root@192.248.145.129
$EDITOR /etc/ssh/sshd_config

#Port 22
Port 7788

disable clear text passwords

#PasswordAuthentication yes
PasswordAuthentication no


restart sshd systemctl restart sshd
Exit server and re-login
exit

Log back in with new port
ssh -p 7788 -i .ssh/serverkey root@192.248.145.129

Create ssh login shortcut:

To be done on host:
touch ~/.ssh/config
chmod 600 ~/.ssh/config
$EDITOR ~/.ssh/config

Host mediawikiserver
    HostName 192.248.145.129
    User root
    Port 7788
    IdentityFile /home/$USER/.ssh/severkey

You can now login to server from host with:
ssh mediawikiserver

Syntax of config file:

#Syntax
#
#Host <ALIAS_NAME>
#    HostName <ADDRESS_IP_OR_DOMAIN>
#    User <USERNAME_LOGIN>
#    Port <PORT_NUMBER_IF_NOT_DEFAULT>
#    IdentityFile </PATH/TO/PRIVATE_KEY>
## Can now login with <code>ssh <ALIAS_NAME>

Enable Basic FireWall

Block IPv6
$EDITOR /etc/default/ufw
Change the line
IPV6=yes
To
IPV6=no
Save and Exit
ufw allow 7788/tcp
ufw enable

Create Swap space on server

First check if you already have a swap space

First check if you already have a swap space
free -m
Returns:

              total        used        free      shared  buff/cache   available
Mem:           1987         103        1655           2         228        1732
Swap:             0           0           0


Other methods to check swap space

cat /proc/swaps
swapon -s -v

Create SwapSpace

preallocate a 2 gigabyte space to be used for swap.
Note: you can name swapfile to anything you want.

fallocate -l 2G /swapfile

Initialize the /swapfile file with zeros - see "Working out the count size" to see how to work out the count size.

Working out the count size:

Working out count size to scale the swapsize.

1 kilobyte = 1024 bytes

1 megabyte = 1024 kilobyte

1 gigabyte = 1024 megabytes

bs=1024 = 1 megabyte

1 gigabyte = 1024 megabyte

to get count of 1 gigabyte 1024 * 1024

2 gigabyte (1024 * 2048 ) or 1048576 * 2 = 2,097,152

dd if=/dev/zero of=/swapfile bs=1024 count=2097152

chmod 600 /swapfile

mkswap /swapfile

swapon /swapfile Or swapon -a Or mount -a

append to /etc/fstab so its mounted after reboot.
$EDITOR /etc/fstab
And enter this in a new line at the bottom:
/swapfile swap swap defaults 0 0

and thats it, you can check swap with(or same other methods as above):

free -m
Returns:

              total        used        free      shared  buff/cache   available
Mem:           1987         103          75           2        1808        1712
Swap:          2047           0        2047

ssmtp for email alerts

apt install ssmtp -y
$EDITOR /etc/ssmtp/ssmtp.conf

mailhub=mail.smtp2go.com:587
AuthUser=noobwiki
AuthPass=N0tTelinu
UseSTARTTLS=YES
FromLineOverride=YES
hostname=completenoobs.com

$EDITOR /etc/ssmtp/revaliases

root:admin@completenoobs.com:mail.smtp2go.com:587

usermod -c "CNWikiVPS" root

Send Test eMail
Create a file and add subject header and some content.
$EDITOR test-mail.txt

Subject:test email

Hello You.


Save and Exit
Now send the email:
sendmail email@address2receive.mail < test-mail.txt
Don't forget to check your spam folder if you don't see email
Once tested and email sent, you can delete test-mail.txt.
rm test-mail.txt

auto update server

$EDITOR /etc/apt/apt.conf.d/50unattended-upgrades
Uncomment (by removing // at start of line)and amend the lines we want:
// "${distro_id}:${distro_codename}-updates";
to
"${distro_id}:${distro_codename}-updates";
Add email address to send email to:

//Unattended-Upgrade::Mail "";
Unattended-Upgrade::Mail "email@tosendto.com";

We are going to test are send mail, so for now change MailReport to "always"

//Unattended-Upgrade::MailReport "on-change";
Unattended-Upgrade::MailReport "always";
// Remove unused automatically installed kernel-related packages
// (kernel images, kernel headers and kernel version locked tools).
//Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// Do automatic removal of newly unused dependencies after the upgrade
//Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

// Do automatic removal of unused packages after the upgrade
// (equivalent to apt-get autoremove)
//Unattended-Upgrade::Remove-Unused-Dependencies "false";

// Automatically reboot *WITHOUT CONFIRMATION* if
//  the file /var/run/reboot-required is found after the upgrade
//Unattended-Upgrade::Automatic-Reboot "false";

// Automatically reboot even if there are users currently logged in
// when Unattended-Upgrade::Automatic-Reboot is set to true
//Unattended-Upgrade::Automatic-Reboot-WithUsers "true";

// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
//  Default: "now"
//Unattended-Upgrade::Automatic-Reboot-Time "02:00";

// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";

Changed to

// Remove unused automatically installed kernel-related packages
// (kernel images, kernel headers and kernel version locked tools).
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";

// Do automatic removal of newly unused dependencies after the upgrade
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

// Do automatic removal of unused packages after the upgrade
// (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// Automatically reboot *WITHOUT CONFIRMATION* if
//  the file /var/run/reboot-required is found after the upgrade
Unattended-Upgrade::Automatic-Reboot "true";

// Automatically reboot even if there are users currently logged in
// when Unattended-Upgrade::Automatic-Reboot is set to true
Unattended-Upgrade::Automatic-Reboot-WithUsers "true";

// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
//  Default: "now"
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
Acquire::http::Dl-Limit "500";

Test with debug flag -d
unattended-upgrade -d

Once email alerts from auto updates has been tested and working, change MailReport back from 'always' to 'on-change', unless you want to be emailed at every update.

Send Container to server

From host
scp -i ~/.ssh/serverkey -P 7788 mediawiki.lxc root@192.248.145.129:/root/
If you created a ssh shortcut in .ssh/config you can use:
scp mediawiki.lxc mediawikiserver:/root/
Once container transferred to server checksum to confirm
Do on Local and Server
sha256sum mediawiki.lxc
The checksum should be the same on both!

LXD setup on server

Check if lxd already installed.
lxd --version
snap install lxd
Initialize LXD
lxd init
all defaults

Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (lvm, zfs, ceph, btrfs, dir) [default=zfs]: 
Create a new ZFS pool? (yes/no) [default=yes]: 
Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=10GB]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like the LXD server to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: 


Import Container

Note: If version of LXD on server is older than the one you are exporting from, you may see error Error: Failed importing backup: Failed creating instance record: Unknown configuration key: volatile.last_state.ready
To Fix this update your LXD
snap remove lxd
snap install lxd
lxd --version
lxd init

Import mediawiki container
lxc import mediawiki.lxc mediawiki
lxc list
lxc start mediawiki
lxc list
Returns:

+-----------+---------+-----------------------+------+-----------+-----------+
|   NAME    |  STATE  |         IPV4          | IPV6 |   TYPE    | SNAPSHOTS |
+-----------+---------+-----------------------+------+-----------+-----------+
| mediawiki | RUNNING | 10.207.119.233 (eth0) |      | CONTAINER | 0         |
+-----------+---------+-----------------------+------+-----------+-----------+

Note the Change of IP
Are Containers IP is now:10.207.119.233

Now for some reason changing the IP on /var/www/html/mediawiki/LocalSettings.php and the /etc/apache2/sites-available/completenoobs.com.conf does not really work on a VPS (Forgot how i fixed this last time, pretty sure i got it workin a few years back).

You need a DNS name:

DNS

Domain Name System: An index that connects an ip address with a more human readable name(website name):
Like a phone book would index a persons name with a phone number.
If you have a domain name for your wiki, point it to your server's ip address.
This will be required for a letsencrypt cert also.

I am using namecheap.com and on the Advanced DNS Page
Add two Type A Records:

Dns
Type Host Ip address TTL
A record @ 192.248.145.129 auto
A record www 192.248.145.129 auto


Change IP on config files

Login to conatiner and change IP's to Domain Name
lxc exec mediawiki bash

$EDITOR /etc/apache2/sites-available/completenoobs.com.conf

    Redirect permanent "/" "https://10.3.45.233"
    Redirect permanent "/" "https://www.completenoobs.com"

$EDITOR /var/www/html/mediawiki/LocalSettings.php

$wgServer = "https://10.3.45.233";
$wgServer = "https://www.completenoobs.com";

systemctl restart apache2


Use IPTables to forward traffic to container

iptable syntax

  • CONTAINER_IP = place holder for your containers ip
  • GLOBAL_IP = place holder for your servers public ip address
  • ETH = network interface: enp1s0
    • to be done/found on host VPS and NOT Container
    • Find network interface:ip route show default or use ip route show default | awk '{print $5}'
iptables -t nat -I PREROUTING -i ETH -p TCP -d GLOBAL_IP --dport 80 -j DNAT --to-destination CONTAINER_IP:80 -m comment --comment "forward real ip to container"
iptables -t nat -I PREROUTING -i ETH -p TCP -d GLOBAL_IP --dport 443 -j DNAT --to-destination CONTAINER_IP:443 -m comment --comment "forward real ip to container"

These commands to be done on host VPS and NOT in container!
Get out of container exit
Network interface=enp1s0

Find you network interface name:

To be run on VPS host and Not in Container:
ip route show default | awk '{print $5}'

VPS Global IP=192.248.145.129
Container IP=10.207.119.233
iptables -t nat -I PREROUTING -i enp1s0 -p TCP -d 192.248.145.129 --dport 443 -j DNAT --to-destination 10.207.119.233:443 -m comment --comment "forward real ip to container"
iptables -t nat -I PREROUTING -i enp1s0 -p TCP -d 192.248.145.129 --dport 80 -j DNAT --to-destination 10.207.119.233:80 -m comment --comment "forward real ip to container"

The new rules for your iptable will not persistent after a reboot.

Create systemd service to load firewall rules at startup:

$EDITOR /usr/local/bin/lxc-mediawiki-rules

#!/bin/bash
iptables -t nat -I PREROUTING -i enp1s0 -p TCP -d 192.248.145.129 --dport 443 -j DNAT --to-destination 10.207.119.233:443 -m comment --comment "forward real ip to container"
iptables -t nat -I PREROUTING -i enp1s0 -p TCP -d 192.248.145.129 --dport 80 -j DNAT --to-destination 10.207.119.233:80 -m comment --comment "forward real ip to container"

chmod +x /usr/local/bin/lxc-mediawiki-rules

$EDITOR /etc/systemd/system/lxcip.service

[Unit]
Description = apply ip rules at startup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/lxc-mediawiki-rules

[Install]
WantedBy=multi-user.target

systemctl enable lxcip

LXC proxy method:

DO NOT USE This method! placed here as a note:
LXC also has a way to forward proxy traffic, but it will show all visits to website, as coming from 127.0.0.1
When we install fail2ban, this would be very bad!

lxc config device add CONTAINER_NAME myport80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
lxc config device add CONTAINER_NAME myport443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443
To remove proxy:
lxc config device remove CONTAINER_NAME myport80
lxc config device remove CONTAINER_NAME myport443



Visit webpage and check all working

Visit the domain you selected
www.completenoobs.com
Should be up and running.
NOTE: We did not need to allow port 443 or 80 on VPS host.
Check Iptables persist for restart, by rebooting server!
reboot
Give it a minute or 2 and check website again.


LetsEncrypt

Log back into server
ssh mediawikiserver
Log into container
lxc exec mediawiki bash
Install certbot
snap install certbot --classic
Backup Apache2 config file
cp /etc/apache2/sites-available/completenoobs.com.conf /etc/apache2/sites-available/completenoobs.com.conf.bk
Create Cert
certbot --apache -d www.completenoobs.com -d completenoobs.com
And Certbot broke are apache2 configs, and thats why we back up!
ls /etc/letsencrypt/live/www.completenoobs.com/
cp /etc/letsencrypt/live/www.completenoobs.com/fullchain.pem /etc/ssl/certs/cn-selfsigned.crt
cp /etc/letsencrypt/live/www.completenoobs.com/privkey.pem /etc/ssl/private/cn-selfsigned.key
rm /etc/apache2/sites-available/completenoobs.com-le-ssl.conf /etc/apache2/sites-available/completenoobs.com.conf
cp /etc/apache2/sites-available/completenoobs.com.conf.bk /etc/apache2/sites-available/completenoobs.com.conf

Turn SSLUseStapling on
$EDITOR /etc/apache2/conf-available/ssl-params.conf

SSLUseStapling off


Change to:

SSLUseStapling on


Restart apache
systemctl restart apache2
Now check your site on browser.

Useful Notes - tips

Forgot your Admin Password

Can use for any user:
php /var/www/html/mediawiki/maintenance/changePassword.php --user=admin --password=newpassword

Make Wiki Read Only

Add to LocalSettings.php:
$wgReadOnly = 'Read Only';

Restrict account creation on wiki

Add to LocalSettings.php:
$wgGroupPermissions['*']['createaccount'] = false;


Only Admin accounts can edit

Add to LocalSettings.php:

$wgGroupPermissions['*']['edit'] = false;
$wgGroupPermissions['user']['edit'] = false;
$wgGroupPermissions['sysop']['edit'] = true;

Protect a page so only admin can edit

At the top of the page when logged in with admin account, click More.
A drop down of three opitions: Delete, Move, Protect.
Clicking Protect will not allow any non admin from editing the page.

When logged in as admin
Read Edit View history (STAR) More

Make User an Admin

go to special pages

With Admin Account go to:
index.php/Special:SpecialPages

List of users can be found here:
index.php/Special:ListUsers

Go to:
index.php/Special:UserRights
And enter username:
Groups you can change
And rest is self explanatory.

Remove admin rights

Same thing, just untick admin rights!

Upgrading MediaWiki

BACK SURE YOU BACKUP FIRST!!! just in case.

This example update 1.35 to 1.36 from 1.36 onwards php-intl is required.

Download the wiki you are going to upgrade to.
https://releases.wikimedia.org/mediawiki/1.36/
cd /root
wget https://releases.wikimedia.org/mediawiki/1.36/mediawiki-1.36.1.tar.gz

In LocalSettings.php put in readonly mode
$EDITOR /var/www/html/mediawiki/LocalSettings.php
$wgReadOnly = "Upgrading";

tar xvzf mediawiki-1.36.1.tar.gz -C /var/www/html/mediawiki --strip-components=1
php /var/www/html/mediawiki/maintenance/update.php

Returns:

Error: Missing one or more required components of PHP.
You are missing a required extension to PHP that MediaWiki needs.
Please install:
 * intl <https://www.php.net/intl>

apt install php-intl
php /var/www/html/mediawiki/maintenance/update.php
And thats it. If you do get an error:

MediaWiki 1.36 internal error Installing some PHP extensions is required.

Required components You are missing a required extension to PHP that MediaWiki requires to run. Please install:

intl (more information)

Then reboot the container and its all fine after.

Backup your Wiki

LXC Snapshots

Easy way, backup the container using snapshot
lxc snapshot mediawiki beforeupgrade_11_12_2020
To see snapshots
lxc info mediawiki
To restore container to snapshot
lxc restore mediawiki beforeupgrade_11_12_2020
To delete a snapshot
lxc delete mediawiki/beforeupgrade_11_12_2020

Export a Snapshot

lxc snapshot mediawiki testsnap

lxc publish mediawiki/testsnap --alias mediawiki-backup-20-07-2021

lxc image export mediawiki-backup-20-07-2021

you end up with a file named after the sha256sum a23ee82572e5f14aabd4b59d6c7bc7923fe88f30f83b776401871e237b554ceb.tar.gz

NOTE:You can change name from a23ee82572e5f14aabd4b59d6c7bc7923fe88f30f83b776401871e237b554ceb.tar.gz
to something like mediawiki-backup-20-07-2021.tar.gz and restore will still work fine.

can now delete image lxc image delete mediawiki-backup-20-07-2021

Import Snapshot

Move to another computer and install init lxd

lxc image import a23ee82572e5f14aabd4b59d6c7bc7923fe88f30f83b776401871e237b554ceb.tar.gz --alias testrestore

lxc launch testrestore mediarestore

lxc list

lxc exec mediarestore bash

Change IP in LocalSettings and apache config and restart apache.
And your up and running.

you can also delete image on new restore computer:
lxc image delete testrestore


Dump mediawiki database - xml

Log into container root dir
lxc exec NAME bash
In container of wiki:
php /var/www/html/mediawiki/maintenance/dumpBackup.php --full > /root/dump_mediawiki.xml
Exit container
exit Pull file to host
lxc file pull NAME/root/dump_mediawiki.xml wiki-dump.xml

automate xml dumps to server

TIP: Create an scp only account on server first
$EDITOR /usr/local/bin/auto-export.sh

#!/bin/bash
set -x

time_stamp=$(date '+%d_%m_%y')
dumps_dir="/var/www/dumps"
noobs_dir="/var/www/html/noobs"
local_settings="$noobs_dir/LocalSettings.php"
wiki_dump_dir="$dumps_dir/$time_stamp.Noobs"
xmlkey="/root/.ssh/xmlkey"
remote_host="rscp@xml.completenoobs.com"
remote_path="/home/rscp/media/"

function ensure_read_only_line_exists {
    if ! grep -q "wgReadOnly" "$local_settings"; then
        cat <<EOF >> "$local_settings"
\$wgReadOnly = 'Dumping Database, Access will be restored shortly';
EOF
    fi
}

function set_wiki_read_only {
    sed -i 's/^#*\(\$wgReadOnly\)/\1/' "$local_settings"
}

function unset_wiki_read_only {
    sed -i 's/^\(\$wgReadOnly\)/#\1/' "$local_settings"
}

function create_directories {
    mkdir -p "$dumps_dir"
    mkdir -p "$wiki_dump_dir"
}

function dump_wiki {
    php "$noobs_dir/maintenance/dumpBackup.php" --full > "$wiki_dump_dir/$time_stamp.Noobs.xml"
}

function generate_checksums {
    md5sum "$wiki_dump_dir/$time_stamp.Noobs.xml" > "$wiki_dump_dir/$time_stamp.md5sum.txt"
    sha256sum "$wiki_dump_dir/$time_stamp.Noobs.xml" > "$wiki_dump_dir/$time_stamp.sha256sum.txt"
}

function push_to_remote {
    scp -i /root/.ssh/xmlkey -r /var/www/dumps/$time_stamp.Noobs rscp@xml.completenoobs.com:/home/rscp/media/
    #rsync -avz -e "ssh -i $xmlkey" "$wiki_dump_dir" "$remote_host:$remote_path"
}

# Main script
ensure_read_only_line_exists
create_directories
set_wiki_read_only
dump_wiki
generate_checksums
unset_wiki_read_only
push_to_remote


chmod +x /usr/local/bin/auto-export.sh

add to cron to export every 5 days

crontab -e

30 3 */5 * * /usr/local/bin/auto-export.sh

Will export at 3:30 am every 5 days, check Ubuntu Cron Quick start for more info

Import Dump

Create Quick local wiki

localwiki

Import dump

lxc file push wiki-dump.xml localwiki/root/
lxc exec localwiki bash

Restore dump

php /var/www/html/mediawiki/maintenance/importDump.php --conf /var/www/html/mediawiki/LocalSettings.php /root/wiki-dump.xml
php /var/www/html/mediawiki/maintenance/rebuildrecentchanges.php
php /var/www/html/mediawiki/maintenance/initSiteStats.php
php /var/www/html/mediawiki/maintenance/rebuildall.php

Everything apart from index.php/Main_Page restored.

Full Wiki Dump and Restore

Backing up

Making your wiki READ ONLY - will lock database

$EDITOR LocalSettings.php
$wgReadOnly = 'Dumping Database, Access will be restored shortly';

Dump and gzip database for transport

will be prompted for password:

mysqldump -h localhost --default-character-set=binary --no-tablespaces -u green -p mywiki_database | gzip > /root/greenwiki.sql.gz

ALt method for dump(password in cmd):

mysqldump -h localhost --default-character-set=binary --no-tablespaces -u green --password=THISpasswordSHOULDbeCHANGED -p mywiki_database | gzip > /root/greenwiki.sql.gz

php /var/www/html/mediawiki/maintenance/dumpBackup.php --full > /root/dump_mediawiki.xml

Back mediawiki Root Directory.
tar cvzhf /root/mediawiki-rootDir.tgz /var/www/html/mediawiki

All into one file for easy transport.
cd /root/
tar cvzhf mediawiki-transfer.tgz mediawiki-rootDir.tgz greenwiki.sql.gz dump_mediawiki.xml

All file in mediawiki-transfer.tgz for transfer to new server

exit Container
exit
lxc file pull mediawiki/root/mediawiki-transfer.tgz mediawiki.bk.tgz

Restore wiki

create container (backupwiki) and push file
lxc file push mediawiki.bk.tgz backupwiki/root/

login to container
apt update && apt upgrade -y
apt install apache2 mysql-server php php-mysql libapache2-mod-php php-xml php-mbstring php-intl -y

tar xvf mediawiki.bk.tgz
tar xvf mediawiki-rootDir.tgz -C /

Create basebase:
NOTE: If you use diff username, passwd, database_name, append/correct details on LocalSettings.
mysql -u root

CREATE USER 'green'@'localhost' IDENTIFIED BY 'THISpasswordSHOULDbeCHANGED';

CREATE DATABASE mywiki_database;

use mywiki_database;

GRANT ALL ON mywiki_database.* TO 'green'@'localhost';

quit;

gunzip -d greenwiki.sql.gz
mysql -u green -p mywiki_database < greenwiki.sql


php /var/www/html/mediawiki/maintenance/importDump.php --conf /var/www/html/mediawiki/LocalSettings.php /root/dump_mediawiki.xml
php /var/www/html/mediawiki/maintenance/rebuildrecentchanges.php
php /var/www/html/mediawiki/maintenance/initSiteStats.php
php /var/www/html/mediawiki/maintenance/rebuildall.php

Config Apache2


$EDITOR /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
        DocumentRoot /var/www/html/mediawiki
</VirtualHost>


Reload Apache2

systemctl restart apache2

Youtube extension

  • needed to view embedded videos

https://www.mediawiki.org/wiki/Extension:YouTube

wget https://extdist.wmflabs.org/dist/extensions/YouTube-REL1_39-f272bb3.tar.gz

tar -xzf YouTube-REL1_39-f272bb3.tar.gz -C /var/www/html/mediawiki/extensions/

  • Append to LocalSettings.php

wfLoadExtension( 'YouTube' );

  • On wiki page can now embed youtube videos
  • Defaults width=640 pixels height=385 pixels
  • Change defaults <youtube width="800" height="400">wB4gvSgYmfY</youtube>

Remove Index.php From URL

How to remove the Index.php from URL


SpamBot Wars

Bit busy now, notes to look into later:

https://www.mediawiki.org/wiki/Extension:Nuke
https://www.mediawiki.org/wiki/Manual:Preventing_access
https://www.mediawiki.org/wiki/Extension:ConfirmAccount
https://www.mediawiki.org/wiki/Extension:InviteSignup


Well the bots won for now - Disable eMail function for all related options in LocalSettings.php
$wgEnableEmail = false;
Or just stop users sending email with:
$wgEnableUserEmail = false;

Notes

Syntax highlighting not working

Install pygments
apt install python3-pygments

Add to LocalSettings:
wfLoadExtension( 'SyntaxHighlight_GeSHi' );