<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://feministwiki.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Technician</id>
	<title>FeministWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://feministwiki.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Technician"/>
	<link rel="alternate" type="text/html" href="https://feministwiki.org/wiki/Special:Contributions/Technician"/>
	<updated>2026-04-29T14:07:45Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Isabel_Rohner&amp;diff=1448</id>
		<title>Isabel Rohner</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Isabel_Rohner&amp;diff=1448"/>
		<updated>2026-04-26T08:13:42Z</updated>

		<summary type="html">&lt;p&gt;Technician: Redirect to German wiki.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[de:Isabel Rohner]]&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Geschlechtsidentit%C3%A4t&amp;diff=1447</id>
		<title>Geschlechtsidentität</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Geschlechtsidentit%C3%A4t&amp;diff=1447"/>
		<updated>2026-04-26T08:11:57Z</updated>

		<summary type="html">&lt;p&gt;Technician: Redirect to German wiki.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[de:Geschlechtsidentität]]&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Magdalen_Berns&amp;diff=1446</id>
		<title>Magdalen Berns</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Magdalen_Berns&amp;diff=1446"/>
		<updated>2026-04-26T08:11:05Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageSeo&lt;br /&gt;
|description = Magdalen Berns was a British lesbian radical feminist, software developer and YouTuber.&lt;br /&gt;
}}&lt;br /&gt;
[[File:Magdalen_Berns.jpg|thumb|right|Magdalen Berns]]&lt;br /&gt;
&#039;&#039;&#039;Magdalen Berns&#039;&#039;&#039; (6 May 1983 – 13 September 2019)&amp;lt;ref&amp;gt;{{cite web|url=https://www.feministcurrent.com/2019/09/13/whats-current-lesbian-feminist-shero-magdalen-berns-passes-away-at-36/ |title=What&#039;s Current: Lesbian feminist shero Magdalen Berns passes away at 36 |publisher=Feministcurrent.com |date=September 13, 2019 }}&amp;lt;/ref&amp;gt; was a British software developer and YouTuber.  Berns, a [[lesbian]] and [[Radical feminism|radical feminist]], came to prominence as a result of a series of YouTube vlogs focusing on lesbian politics, free speech, women&#039;s sex-based rights and the [[gender identity]] debate.&amp;lt;ref&amp;gt;{{cite web |url=https://www.youtube.com/channel/UCvTTakI97sQ4SkMnsH8r0qQ |title=Magdalen Berns |publisher=YouTube |access-date=2019-09-14}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Biography ==&lt;br /&gt;
&lt;br /&gt;
=== Education ===&lt;br /&gt;
&lt;br /&gt;
Berns attended the University of Edinburgh, where she was a recipient of a Doris Gray Scholarship Award.&amp;lt;ref&amp;gt;{{cite web|url=https://www.wes.org.uk/content/current-recipients-doris-gray-scholarships |title=Current recipients of the Doris Gray Scholarships |publisher=[[Women&#039;s Engineering Society]] |access-date=2019-09-15}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Work and career ===&lt;br /&gt;
&lt;br /&gt;
In 2013–2014, she participated in the &#039;&#039;Google Summer of Code&#039;&#039; programme,&amp;lt;ref&amp;gt;{{cite web|url=https://github.com/SciRuby/sciruby/wiki/Google-Summer-of-Code-2018-Application |title=Google Summer of Code 2018 Application |publisher=Github |date=January 2018 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt; working on implementing the &#039;&#039;FFTW3&#039;&#039; software library for the Ruby programming language.&amp;lt;ref&amp;gt;{{cite web|url=http://sciruby.com/blog/2014/06/04/introducing-the-fftw-sciruby-gsoc-project/ |title=Introducing the FFTW SciRuby GSoC Project |publisher=SciRuby.com |date=June 4, 2014 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt; She went on to join the [[Wikipedia:GNOME Foundation|GNOME Foundation]] as a software developer.&amp;lt;ref&amp;gt;{{cite web|url=https://www.dgsiegel.net/talks/gnome-outreach-yearbook-2013.pdf |title=GNOME Outreach Program Yearbook 2013 |publisher=GNOME Foundation |date=August 2013 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt; She developed the Java ATK Wrapper, a module to translate Swing (Java) events for the Accessibility Toolkit.&amp;lt;ref&amp;gt;{{cite web|url=https://www.gnome.org/news/2015/08/pictures-from-guadec-2015/attachment/magdalen-berns-present-her-work-with-improving-the-java-atk-wrapper/ |title=Magdalen Berns present her work with improving the Java-ATK-Wrapper |publisher=GNOME Foundation |date=August 2015 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Radical feminism ===&lt;br /&gt;
&lt;br /&gt;
Berns&#039; statement that &amp;quot;there&#039;s no such thing as a lesbian with a penis&amp;quot; made her well-known, as well as her opposition to the &amp;quot;cotton ceiling”, a term coined by Canadian [[transwoman]] and activist Drew DeVeaux, which refers to the perceived injustice of lesbians not wanting to have sex with transwomen.&amp;lt;ref&amp;gt;{{cite web|url=https://www.afterellen.com/general-news/571815-celebrating-magdalen-berns-a-lesbian-feminist-warrior |title=Celebrating Magdalen Berns, a Lesbian Feminist Warrior |publisher=Afterellen.com |date=May 29, 2018 |access-date=2019-09-14}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite web|url=https://medium.com/@mirandayardley/girl-dick-the-cotton-ceiling-and-the-cultural-war-on-lesbians-and-women-c323b4789368 |title=The Cotton Ceiling and the Cultural War on Lesbians and Women |publisher=medium.com |access-date=2019-09-15}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Berns was slurred by [[Transgender ideology|trans activists]] as a [[TERF|trans-exclusionary radical feminist]], and has stated that it was this accusation that first led her to research radical feminism.  She was also known for her arguments against the concepts of gender self-identification and [[gender]] itself.  Speaking on the subject of gender and sexuality, Berns stated: &amp;quot;You don’t get ‘assigned’ reproductive organs.....males are defined by their biological sex organs. Likewise, [[Homosexuality|homosexuals]] are people who are attracted to the same [[Sex|biological sex]].”&amp;lt;ref&amp;gt;{{cite web|url=https://feministlegal.org/scotlands-magdalen-berns-feminism-a-shero-among-women/#.XX5zTShKjIU |title=Scotland’s Magdalen Berns &amp;amp; Feminism — A ‘Shero’ Among Women |publisher=feministlegal.org |date=September 7, 2019 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt; In June 2019, British author J.K. Rowling (of Harry Potter fame) followed Magdalen Berns on Twitter, bringing her more visibility and prompting criticism towards Rowling from trans activists.&amp;lt;ref&amp;gt;{{cite web|url=https://www.indy100.com/article/jk-rowling-twitter-transphobe-magdalen-berns-terf-lgbt-8974041 |title=JK Rowling criticised for following &#039;transphobe&#039; Magdalen Berns on Twitter |publisher=indy100 |date=June 25, 2019 |access-date=2019-09-14}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite web|url=https://www.altpress.com/news/j-k-rowling-transphobic-behavior/ |title=J.K. Rowling Faces Backlash For Allegedly Displaying Transphobic Behaviour |publisher=altpress.com |date=June 28, 2019 |access-date=2019-09-15}}&amp;lt;/ref&amp;gt; Berns was labelled a [[transphobia|transphobe]] and a self-professed transphobe.&amp;lt;ref&amp;gt;{{cite web |author=Narjas Zatat |date=June 25, 2019 |title= JK Rowling criticised for following a &#039;famous transphobe&#039; on Twitter |url= https://www.indy100.com/article/jk-rowling-twitter-transphobe-magdalen-berns-terf-lgbt-8974041 |website= Indy100 (from The Independent) |access-date= 15 September 2019}}&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;{{cite web |author=Emma Maurice |date=June 25, 2019 |title= JK Rowling under fire for following a ‘proud transphobe’ on Twitter |url= https://www.pinknews.co.uk/2019/06/25/jk-rowling-under-fire-following-transphobe-twitter/ |website= Pink News |access-date= 15 September 2019}}&amp;lt;/ref&amp;gt; In August 2019, Dr. [[Rachel McKinnon]] of the College of Charleston attracted criticism after describing the celebration of Berns&#039; impending death as &amp;quot;ethically justified&amp;quot; in light of Berns&#039; positions on gender.&amp;lt;ref&amp;gt;{{cite web|url=https://www.postandcourier.com/news/the-tweet-heard-round-the-world-charleston-professor-sparks-global/article_4a462cda-c9c7-11e9-8134-d32dc721835d.html |title=The tweet heard &#039;round the world: Charleston professor sparks global Twitter debate |publisher=Evening Post Industries |website=The Post and Courier |date=August 29, 2019 |access-date=2019-09-15 |author=Jenna Schiferl}}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Health and death ===&lt;br /&gt;
&lt;br /&gt;
Berns was diagnosed with a glioblastoma (aggressive brain cancer) in 2018.&amp;lt;ref&amp;gt;{{cite web|url=https://www.youtube.com/watch?v=-brCJkXxzaM|title=My ladybrain update #2}}&amp;lt;/ref&amp;gt; Notably, Irish comedy writer [[Graham Linehan]] voiced vocal support for Berns on Twitter and other platforms,&amp;lt;ref&amp;gt;{{cite web|last1=Linehan|first1=Graham|title=Magdalen Berns 1983–2019|url=https://glinner.co.uk/stunning-and-brave-magdalen-berns-1983-2019/|website=Glinner|date=September 13, 2019}}&amp;lt;/ref&amp;gt; and visited her in palliative care. She was also visited by fellow radical feminist activists [[Julie_Bindel|Julie Bindel]]&amp;lt;ref&amp;gt;{{cite web |url=https://twitter.com/bindelj/status/1171341052109873152 |author=@bindelj ([[Julie Bindel]]) |date=September 10, 2019|title=I am visiting our Queen, Magdalen Berns tomorrow. I would be delighted to pass on any messages of love and appreciation to her if you would like to send me in a (short) DM? Thank you x |website=Twitter }}&amp;lt;/ref&amp;gt; and [[Rachel Moran]].&amp;lt;ref&amp;gt;{{Cite web|url=https://twitter.com/RachelRMoran/status/1172459990570938368 |author=@RachelRMoran ([[Rachel Moran]]) |date=September 13, 2019|title=I just feel so lucky to have been able to spend time with Magdalen the two weekends before she died. If people could see the carry-on in that hospice room there would be peals of laughter. She was absolutely her feisty determined self to the very end. Rest well little Sister, xxx |website=Twitter }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
She died on 13 September 2019, aged 36 in Edinburgh.&amp;lt;ref&amp;gt;{{cite web|url=https://www.feministcurrent.com/2019/09/13/whats-current-lesbian-feminist-shero-magdalen-berns-passes-away-at-36/ |title=What&#039;s Current: Lesbian feminist shero Magdalen Berns passes away at 36 |publisher=Feministcurrent.com |date=September 13, 2019 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.youtube.com/channel/UCvTTakI97sQ4SkMnsH8r0qQ Official YouTube Page]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Language links: --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[pt:Magdalen Berns]][[de:Magdalen Berns]]&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1443</id>
		<title>FeministWiki:Technical documentation</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1443"/>
		<updated>2026-03-04T13:33:40Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* SMTP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the FeministWiki&#039;s technical infrastructure, the target audience being technicians.  Note that while this page will help you understand the inner workings of the FeministWiki, it&#039;s not optimal for guiding you through the setup of a new server.  For that, see the page [[FW:Server setup]] instead.&lt;br /&gt;
&lt;br /&gt;
== Hosts ==&lt;br /&gt;
&lt;br /&gt;
The following table documents the basic DNS configuration, and can be used as part of the {{C|/etc/hosts}} file on each server to obviate the need for DNS lookups when connecting to one another.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!IP            !! FQDN                        !! Host          !! Purpose                 !! Ports&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||            feministwiki.org ||               || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||        www.feministwiki.org || www           || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       ldap.feministwiki.org || ldap          || LDAP                    || -&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      blogs.feministwiki.org || blogs         || Blogging                || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       chat.feministwiki.org || chat          || Web-client for XMPP     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      forum.feministwiki.org || forum         || BBS Forum               || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       mail.feministwiki.org || mail          || Web-client for Mail     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      files.feministwiki.org || files         || File storage            || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       imap.feministwiki.org || imap          || IMAP                    || 993&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       pop3.feministwiki.org || pop3          || POP3                    || 995&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       smtp.feministwiki.org || smtp          || SMTP                    || 25, 465, 587&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       xmpp.feministwiki.org || xmpp          || XMPP                    || 5222, 5223, 5269, 5270, 5443, 7777&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||        irc.feministwiki.org || irc           || IRC                     || 6697&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||    account.feministwiki.org || account       || Account operations      || 80, 443&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As you can see, all services are on the same server for now.  However, it should be kept as an open possibility that the hosts are split across different IPs.  When done so, the {{C|ldap}} host should listen on 636 for LDAPS connections.&lt;br /&gt;
&lt;br /&gt;
There are no AAAA entries in the DNS because we only allow IPv4 for incoming connections.  This simplifies security auditing.&lt;br /&gt;
&lt;br /&gt;
== Special DNS entries ==&lt;br /&gt;
&lt;br /&gt;
For CAA:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Name !! Flag !! Tag   !! Value          &lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || issue || letsencrypt.org&lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || iodef || admin@feministwiki.org&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For email:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data                                                                   !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|MX   || @               || smtp.feministwiki.org                                                  || Mail server&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || v=spf1 mx -all                                                         || SPF&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || mail._domainkey || v=DKIM1; k=rsa; p=&amp;lt;pubkey&amp;gt;                                             || DKIM&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || _dmarc          || v=DMARC1; p=reject; rua=&amp;lt;nowiki&amp;gt;mailto:admin&amp;lt;/nowiki&amp;gt;@feministwiki.org || DMARC&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; There must be a direct A or AAAA record (not a CNAME record) for the domain name specified in the MX record.&lt;br /&gt;
&lt;br /&gt;
For XMPP:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Service      !! Protocol !! Name !! Destination           !! Port&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-client || _tcp     || @    || xmpp.feministwiki.org || 5222&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-server || _tcp     || @    || xmpp.feministwiki.org || 5269&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-client || _tcp     || @    || xmpp.feministwiki.org || 5223&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-server || _tcp     || @    || xmpp.feministwiki.org || 5270&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Google Site Verification:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || google-site-verification=&amp;lt;key&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall ==&lt;br /&gt;
&lt;br /&gt;
The simple {{C|ufw}} firewall-frontend is used to trivially limit all network I/O to the ports you can see in the host table above, plus port 22 for ssh and scp.&lt;br /&gt;
&lt;br /&gt;
UFW adds IPv6 rules by default, which can be prevented by using more explicit rules.  Consider the following rule:&lt;br /&gt;
&lt;br /&gt;
  ufw allow 12345/tcp  # will allow TCP connections to port 12345 via IPv4 and IPv6&lt;br /&gt;
&lt;br /&gt;
To limit this to IPv4 you can instead use this:&lt;br /&gt;
&lt;br /&gt;
  ufw allow proto tcp to 0.0.0.0/0 port 12345  # will allow TCP connections to port 12345 via IPv4 only&lt;br /&gt;
&lt;br /&gt;
== Fail2ban ==&lt;br /&gt;
&lt;br /&gt;
We use {{C|fail2ban}} to detect brute force attempts on some services.  The git repository for scripts and config contains the relevant Fail2ban configuration under {{C|etc/fail2ban}}.&lt;br /&gt;
&lt;br /&gt;
== SSH access ==&lt;br /&gt;
&lt;br /&gt;
FeministWiki hosts have ssh enabled for {{C|root}} access, but password login is disabled.  You must own a valid private key to log in.&lt;br /&gt;
&lt;br /&gt;
== Git repo of scripts and configuration ==&lt;br /&gt;
&lt;br /&gt;
The following GitHub account hosts repositories with scripts and configuration used by the FeministWiki:&lt;br /&gt;
&lt;br /&gt;
https://github.com/FeministWiki&lt;br /&gt;
&lt;br /&gt;
== Certs ==&lt;br /&gt;
&lt;br /&gt;
The FeministWiki uses LetsEncrypt to acquire digital certificates for encrypted communication.&lt;br /&gt;
&lt;br /&gt;
After certificates are generated with {{C|certbot}}, copies of them are put into {{C|/etc/feministwiki/certs}}, and the group ownership and permissions of the {{C|privkey.pem}} and {{C|bundle.pem}} files are set such that any user who&#039;s in the {{C|ssl-cert}} group can read the private key and bundle.  (The others can be read by anyone anyway.)  A script in {{C|/etc/letsencrypt/renewal-hooks/post}} is responsible for taking care of this after automatic executions of certbot scheduled by the operating system.&lt;br /&gt;
&lt;br /&gt;
The file {{C|/etc/feministwiki/certs/bundle.pem}} is useful for programs that don&#039;t have the capability of reading a separate cert and key file; it combines the full certificate chain ({{C|fullchain.pem}}) with the private key in a single file.&lt;br /&gt;
&lt;br /&gt;
If you ever add a new domain under which the FeministWiki server will be reachable, add it as a line to the file {{C|/etc/feministwiki/domains}} and run the script {{C|/root/bin/letsencrypt-refresh}}.  This script takes care of running {{C|certbot}} to refresh the cert files, and populating the {{C|/etc/feministwiki/certs}} directory with updated files.&lt;br /&gt;
&lt;br /&gt;
Note that whenever you run the {{C|letsencrypt-refresh}} script, it will momentarily stop the web server.  This means you&#039;re causing a short outage of the web-based services of the FeministWiki whenever you run the script.&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
&lt;br /&gt;
This section documents the individual services of the FeministWiki.  They should work regardless of what server they&#039;re on.  I.e. every service could in theory be hosted on its own server.&lt;br /&gt;
&lt;br /&gt;
=== LDAP ===&lt;br /&gt;
&lt;br /&gt;
Host: ldap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: OpenLDAP&lt;br /&gt;
&lt;br /&gt;
The LDAP service contains the central database of FeministWiki members.  For details on the LDAP schema, see [[FeministWiki:LDAP Schema]].&lt;br /&gt;
&lt;br /&gt;
=== Wiki ===&lt;br /&gt;
&lt;br /&gt;
Host: feministwiki.org, www.feministwiki.org, fem.wiki, feminist.wiki, feminism.wiki, feministwiki.de, www.feministwiki.de &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: MediaWiki&lt;br /&gt;
&lt;br /&gt;
The wiki uses a [https://www.mediawiki.org/wiki/MediaWiki MediaWiki] installation located at {{C|/var/www/fw/wiki/w}}.  It uses the [https://www.mediawiki.org/wiki/LDAP_Stack LDAP Stack] extension for login management, and the &amp;quot;Short URL&amp;quot; feature is enabled.  The wiki uses the SQL database called &amp;quot;feministwiki&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
The default wiki is in English.  Parallel wiki installations for different languages are supported via a combination of Apache&#039;s URL rewriting, and conditional branches in the {{C|LocalSettings.php}} file of the MediaWiki installation:&lt;br /&gt;
&lt;br /&gt;
* The rewrite rules ensure that, for any supported language {{C|xy}}, URLs beginning with {{C|/xy/wiki/...}} internally resolve to {{C|/w/index.php}} and URLs beginning with {{C|/xy/w/...}} resolve to {{C|/w/...}}.&lt;br /&gt;
* The LocalSettings file checks {{C|$_SERVER[&#039;REQUEST_URI&#039;]}} to determine the language code prefix in the requested URL, and configures things accordingly:&lt;br /&gt;
** It sets {{C|$wgArticlePath}} to {{C|/xy/wiki/$1}} so that {{C|/w/index.php}} knows that when it&#039;s invoked via such a URL, it should serve an article.&lt;br /&gt;
** It sets {{C|$wgScriptPath}} to {{C|/xy/w}} so that links to scripts served by MediaWiki are correct for the language.&lt;br /&gt;
** It sets the SQL database name to {{C|feministwiki_xy}}.&lt;br /&gt;
** It configures a &amp;quot;foreign&amp;quot; image database via the [https://www.mediawiki.org/wiki/Manual:$wgForeignFileRepos#Using_files_from_a_database_that_you_can_access_:_ForeignDBRepo,_ForeignDBViaLBRepo ForeignDBRepo] method so that the media upload database of the default wiki is used by all, instead of every parallel wiki having its own media database.&lt;br /&gt;
&lt;br /&gt;
To add a new language, follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Clone the English wiki&#039;s database into a new one via: {{C|mysqldump feministwiki &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; mysql feministwiki_xy}}&lt;br /&gt;
* Grant permissions on the new database via: {{C|GRANT ALL ON feministwiki_xy.* TO feministwiki@localhost;}}&lt;br /&gt;
* Edit {{C|/etc/apache2/sites-available/000-wiki.conf}} to add the line: {{C|Use Wiki xy}}&lt;br /&gt;
* Add the language to {{C|~/bin/fw-update-languages.sh}} and run it&lt;br /&gt;
&lt;br /&gt;
The last step will produce a lot of errors complaining about keys already existing; these can be safely ignored.&lt;br /&gt;
&lt;br /&gt;
The domain names feministwiki.de and www.feministwiki.de redirect to {{C|https://feministwiki.org/de}}.  For instance, requesting {{C|https://feministwiki.de/wiki/Hauptseite}} will result in an HTTP redirect to {{C|https://feministwiki.org/de/wiki/Hauptseite}}.&lt;br /&gt;
&lt;br /&gt;
=== Blogs ===&lt;br /&gt;
&lt;br /&gt;
Host: blogs.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: WordPress (multisite)&lt;br /&gt;
&lt;br /&gt;
This is an installation of WordPress in {{C|/var/www/fw/blogs}}, with the &amp;quot;multisite network&amp;quot; feature enabled on a path-basis, so users can have their own blogs on URLs like {{C|blogs.feministwiki.org/janedoe}}.  LDAP authentication is enabled via the AD/LDAP plugin from miniOrange.&lt;br /&gt;
&lt;br /&gt;
Users from LDAP who log in for the first time are automatically registered as &amp;quot;Subscriber&amp;quot; accounts, and the admin can change their WordPress role &amp;quot;Author&amp;quot; to allow publishing.&lt;br /&gt;
&lt;br /&gt;
This WordPress installation uses the SQL database called &amp;quot;blogs&amp;quot; and an SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Chat (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: chat.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Converse.js&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministChat uses the full-screen &amp;quot;Impress&amp;quot; variant of the [https://conversejs.org/ Converse.js] XMPP client.  The hosted HTML and JS files are located at {{C|/var/www/fw/chat}}, although they load Converse.js as an external script from upstream, which is why the self-hosted HTML and JS are very minimal.&lt;br /&gt;
&lt;br /&gt;
=== Forum ===&lt;br /&gt;
&lt;br /&gt;
Host: forum.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: phpBB&lt;br /&gt;
&lt;br /&gt;
The forum uses a [https://www.phpbb.com/ phpBB] installation located at {{C|/var/www/fw/forum}}.  Most configuration of phpBB, including LDAP authentication, is done through its administration panel.  The style used by the forum is a minimally changed &amp;quot;ProSilver Dark&amp;quot;.  The forum uses the SQL database called &amp;quot;feministforum&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Mail (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: mail.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Roundcube&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministMail uses the [https://roundcube.net/ Roundcube] mail client, installed at {{C|/var/www/fw/mail}}.  It uses a FeministWiki-branded modification of the new &amp;quot;elastic&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
&lt;br /&gt;
Host: files.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Nextcloud&lt;br /&gt;
&lt;br /&gt;
FeministFiles is a [https://nextcloud.com/ Nextcloud] installation with some branding, and LDAP authentication, installed at {{C|/var/www/fw/files}}.&lt;br /&gt;
&lt;br /&gt;
=== IMAP ===&lt;br /&gt;
&lt;br /&gt;
Host: imap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [https://www.dovecot.org/ Dovecot] IMAP server, configured for LDAP authentication and using virtual mail boxes under {{C|/home/vmail}}.&lt;br /&gt;
&lt;br /&gt;
=== POP3 ===&lt;br /&gt;
&lt;br /&gt;
Host: pop3.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
While Dovecot is primarily an IMAP server, it also offers POP3 support, which the FeministWiki installation has enabled.&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
&lt;br /&gt;
Host: smtp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Postfix, Rspamd&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [http://www.postfix.org/ Postfix] SMTP server, using SASL authentication through Dovecot, LDAP-based virtual mail boxes under {{C|/home/vmail}}, and DKIM signing as well as DMARC/SPF validation and spam filtering via Rspamd.  Send a mail to a Gmail account and use the &amp;quot;Show original&amp;quot; feature of Gmail to see if the mail passes SPF, DKIM, and DMARC tests.&lt;br /&gt;
&lt;br /&gt;
There are also various tools on the web to automatically test the DNS settings for correctness, to check if the domain/IP is on blacklists, etc., which you can find via Google.  All in all, FeministMail is probably the most complicated service of the FeministWiki, as far as technical background goes.&lt;br /&gt;
&lt;br /&gt;
=== Mailing lists ===&lt;br /&gt;
&lt;br /&gt;
Email domain: lists.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: GNU Mailman, Postfix&lt;br /&gt;
&lt;br /&gt;
Postfix is configured to recognize {{C|lists.feministwiki.org}} as a &amp;quot;local&amp;quot; domain.  This means it uses the file specified in the {{C|alias_maps}} configuration directive (typically {{C|/etc/aliases}}) to decide the final recipient of an e-mail sent to this domain.  Correspondingly, we populate {{C|/etc/aliases}} with the aliases needed by Mailman to operate each mailing list it controls.&lt;br /&gt;
&lt;br /&gt;
Note that there is no DNS entry for {{C|lists.feministwiki.org}} because e-mail software just checks the MX record for {{C|feministwiki.org}} when the recipient is from the domain {{C|&amp;lt;em&amp;gt;anything&amp;lt;/em&amp;gt;.feministwiki.org}}.&lt;br /&gt;
&lt;br /&gt;
=== XMPP ===&lt;br /&gt;
&lt;br /&gt;
Host: xmpp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: ejabberd&lt;br /&gt;
&lt;br /&gt;
FeministChat uses the [https://www.ejabberd.im/ ejabberd] XMPP server, configured to use LDAP authentication and an LDAP-based shared roster group for all members.&lt;br /&gt;
&lt;br /&gt;
=== IRC ===&lt;br /&gt;
&lt;br /&gt;
Host: irc.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: InspIRCd&lt;br /&gt;
&lt;br /&gt;
FeministIRC uses the [http://www.inspircd.org/ InspIRCd] IRC server with the {{C|ldapauth}} module for LDAP authentication.  The client is authenticated via the combination of the NICK and PASS provided upon connection, which must correspond to the FeministWiki credentials.&lt;br /&gt;
&lt;br /&gt;
=== Account operations ===&lt;br /&gt;
&lt;br /&gt;
Host: account.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: custom&lt;br /&gt;
&lt;br /&gt;
This custom web interface hosted at {{C|/var/www/fw/account}} lets you complete several tasks related to FeministWiki membership, such as changing your account settings, resetting your password, or adding a new member.  It also contains a form to request membership.  The interface is written in HTML, CSS, PHP, and C.&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1442</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1442"/>
		<updated>2026-03-04T13:25:31Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     rspamd \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.4 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine {{=}} &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates and DKIM key ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/feministwiki/certs feministwiki.dev:/etc/feministwiki&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/feministwiki/certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
Finally, copy over the DKIM signing key:&lt;br /&gt;
&lt;br /&gt;
 rsync -avz /etc/feministwiki/dkim.key feministwiki.dev:/etc/feministwiki&lt;br /&gt;
&lt;br /&gt;
This file must be owned by the {{C|_rspamd}} user and not readable by anyone else.&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop rspamd&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop rspamd&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1427</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1427"/>
		<updated>2026-03-02T09:17:22Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     opendmarc \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM &amp;amp; OpenDMARC ===&lt;br /&gt;
&lt;br /&gt;
Postfix&#039;s SMTPD daemon runs in a chroot in {{C|/var/spool/postfix}}, so the configuration of OpenDKIM and OpenDMARC arrange for their respective Unix sockets to be created in subdirectories therein; we must ensure that these exist and have the correct permissions:&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendmarc&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendmarc:opendmarc /var/spool/postfix/opendmarc&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
 adduser postfix opendmarc&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.4 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine {{=}} &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/feministwiki/certs feministwiki.dev:/etc/feministwiki/certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/feministwiki/certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1426</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1426"/>
		<updated>2026-03-02T06:44:46Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Install server components */ Add rspamd.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     rspamd \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine {{=}} &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/feministwiki/certs feministwiki.dev:/etc/feministwiki/certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/feministwiki/certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1424</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1424"/>
		<updated>2025-09-18T18:24:40Z</updated>

		<summary type="html">&lt;p&gt;Technician: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1423</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1423"/>
		<updated>2025-09-18T18:24:29Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test.&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1422</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1422"/>
		<updated>2025-09-18T18:23:58Z</updated>

		<summary type="html">&lt;p&gt;Technician: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1421</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1421"/>
		<updated>2025-09-18T18:23:48Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test.&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:LDAP_Schema&amp;diff=1420</id>
		<title>FeministWiki:LDAP Schema</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:LDAP_Schema&amp;diff=1420"/>
		<updated>2025-02-06T11:50:23Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Tips on the usage of ldap commands */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The member database of the FeministWiki is stored via LDAP.  This page explains some details about the setup.&lt;br /&gt;
&lt;br /&gt;
=== Structure ===&lt;br /&gt;
&lt;br /&gt;
The basic structure looks like this:&lt;br /&gt;
&lt;br /&gt;
 dc=feministwiki,dc=org&lt;br /&gt;
   ou=members&lt;br /&gt;
     - cn=&#039;&#039;username&#039;&#039;&lt;br /&gt;
       objectClass: fwMember&lt;br /&gt;
       cn: &#039;&#039;username&#039;&#039;&lt;br /&gt;
       uid: &#039;&#039;username&#039;&#039;&lt;br /&gt;
       sn: &#039;&#039;Display name&#039;&#039;&lt;br /&gt;
       userPassword: {SSHA}&#039;&#039;saltedhash&#039;&#039;&lt;br /&gt;
       mail: &#039;&#039;username&#039;&#039;@feministwiki.org&lt;br /&gt;
       fwRecoveryMail: &#039;&#039;user@example.org&#039;&#039;&lt;br /&gt;
     - cn=&#039;&#039;username2&#039;&#039;&lt;br /&gt;
       objectClass: fwMembe&lt;br /&gt;
       cn: &#039;&#039;username2&#039;&#039;&lt;br /&gt;
       uid: &#039;&#039;username2&#039;&#039;&lt;br /&gt;
       sn: &#039;&#039;Display name&#039;&#039;&lt;br /&gt;
       userPassword: {SSHA}&#039;&#039;saltedhash2&#039;&#039;&lt;br /&gt;
       mail: &#039;&#039;username2&#039;&#039;@feministwiki.org&lt;br /&gt;
       manager: cn=&#039;&#039;username&#039;&#039;,ou=members,dc=feministwiki,dc=org&lt;br /&gt;
     - ...&lt;br /&gt;
   ou=groups&lt;br /&gt;
     cn=members&lt;br /&gt;
     objectClass: groupOfNames&lt;br /&gt;
     cn: members&lt;br /&gt;
     member: &#039;&#039;username&#039;&#039;&lt;br /&gt;
     member: &#039;&#039;username2&#039;&#039;&lt;br /&gt;
     member: ...&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The &amp;lt;code&amp;gt;cn&amp;lt;/code&amp;gt; (common name) and &amp;lt;code&amp;gt;uid&amp;lt;/code&amp;gt; (user ID) fields both contain the username.  This is because some software is preconfigured to look at &amp;lt;code&amp;gt;uid&amp;lt;/code&amp;gt;, while most look at &amp;lt;code&amp;gt;cn&amp;lt;/code&amp;gt;.&lt;br /&gt;
* The &amp;lt;code&amp;gt;sn&amp;lt;/code&amp;gt; (surname) field is used to hold a display name that may be different from the username.  The field is filled with the username by default.&lt;br /&gt;
* The &amp;lt;code&amp;gt;mail&amp;lt;/code&amp;gt; field holds the primary mail address for communication with the member.  It&#039;s filled with the FeministWiki mail address of the member by default, but can be changed freely.&lt;br /&gt;
* The &amp;lt;code&amp;gt;fwRecoveryMail&amp;lt;/code&amp;gt; field may hold a mail address that will be used for password reset requests.  It&#039;s different from the primary mail address because that one may be the member&#039;s FeministWiki address, which they can&#039;t access if they&#039;ve lost their password.&lt;br /&gt;
* The &amp;lt;code&amp;gt;manager&amp;lt;/code&amp;gt; contains the DN (distinguished name) of the member who added the member.  It may be empty for special member accounts like &amp;quot;Administrator&amp;quot; or the &amp;quot;Deleted&amp;quot; pseudo-account.&lt;br /&gt;
&lt;br /&gt;
=== Tips on the usage of ldap commands ===&lt;br /&gt;
&lt;br /&gt;
Commands such as ldapsearch, ldapmodify, etc. require authentication.  The correct method depends on whether you want to interact with the configuration database found in {{C|/etc/ldap/slapd.d}}, or the actual data database found in {{C|/var/lib/ldap}}.&lt;br /&gt;
&lt;br /&gt;
For configuration, use {{C|-Y external -H ldapi://}} to connect directly with root permissions, so no actual LDAP domain login is needed.&lt;br /&gt;
&lt;br /&gt;
For data, use {{C|-xy ~/pwd/ldap}} to use the LDAP domain admin password.  The file {{C|~/.ldaprc}} should contain the following, so you don&#039;t have to specify the domain admin explicitly every time:&lt;br /&gt;
&lt;br /&gt;
 BINDDN cn=admin,dc=feministwiki,dc=org&lt;br /&gt;
&lt;br /&gt;
=== Read-only user ===&lt;br /&gt;
&lt;br /&gt;
For security purposes, it&#039;s a good idea to have a &amp;quot;read-only&amp;quot; user for LDAP read operations, instead of using the admin for everything.&lt;br /&gt;
&lt;br /&gt;
 # Add read-only user&lt;br /&gt;
 ldapadd -xy ~/pwd/ldap &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=readonly,dc=feministwiki,dc=org&lt;br /&gt;
 objectClass: simpleSecurityObject&lt;br /&gt;
 objectClass: organizationalRole&lt;br /&gt;
 cn: readonly&lt;br /&gt;
 description: Read-only user&lt;br /&gt;
 userPassword: $(cat ~/pwd/ldap-readonly)&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
No fiddling with access control is needed, since read-only access is the default.&lt;br /&gt;
&lt;br /&gt;
=== Custom objectClass ===&lt;br /&gt;
&lt;br /&gt;
The following command creates the &amp;lt;code&amp;gt;fwMember&amp;lt;/code&amp;gt; object class.&lt;br /&gt;
&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
=== Attribute permissions ===&lt;br /&gt;
&lt;br /&gt;
We want to make the following changes to the default LDAP permissions:&lt;br /&gt;
&lt;br /&gt;
* Members should be able to change their own display name (&amp;lt;code&amp;gt;sn&amp;lt;/code&amp;gt;) and e-mail address (&amp;lt;code&amp;gt;mail&amp;lt;/code&amp;gt;).&lt;br /&gt;
* The read-only user should be able to find users via the combination of their username and recovery mail address (&amp;lt;code&amp;gt;fwRecoveryMail&amp;lt;/code&amp;gt;), but not actually see their recovery mail addresses.  (The password reset mechanism uses this.)&lt;br /&gt;
* Members should not be able to see who a member was added by (the &amp;lt;code&amp;gt;manager&amp;lt;/code&amp;gt; field).&lt;br /&gt;
&lt;br /&gt;
The following command makes the necessary access control changes:&lt;br /&gt;
&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;olcAccess&amp;lt;/code&amp;gt; entries are evaluated in order, and the first match takes effect.  This can affect performance.  In the statement above, we start inserting entries from index 2, because indexes 0 and 1 already have some meaningful default entries.&lt;br /&gt;
&lt;br /&gt;
=== Password policy ===&lt;br /&gt;
&lt;br /&gt;
To make sure passwords are stored with the &amp;lt;code&amp;gt;{SSHA}&amp;lt;/code&amp;gt; scheme rather than plain text, the &amp;lt;code&amp;gt;ppolicy&amp;lt;/code&amp;gt; &amp;quot;password policy overlay&amp;quot; is used.  ZYTRAX has a very nice book about LDAP which documents how to enable this: http://www.zytrax.com/books/ldap/ch6/ppolicy.html&lt;br /&gt;
&lt;br /&gt;
In short, the steps go as follows (these commands &#039;&#039;should&#039;&#039; work verbatim):&lt;br /&gt;
&lt;br /&gt;
 # Only needed on old versions of slapd, to add the ppolicy schema&lt;br /&gt;
 #ldapadd -Y external -H ldapi:// &amp;lt; /etc/ldap/schema/ppolicy.ldif&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Further, &amp;lt;code&amp;gt;ppolicy&amp;lt;/code&amp;gt; is used to enable brute-force protection.  For this, we need to add an entry of the object class &amp;lt;code&amp;gt;pwdPolicy&amp;lt;/code&amp;gt; to the directory, add attributes related to brute-force protection, and then set it as the default password policy:&lt;br /&gt;
&lt;br /&gt;
 # Add an OU for password policies&lt;br /&gt;
 ldapadd -xy ~/pwd/ldap &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 objectClass: organizationalUnit&lt;br /&gt;
 ou: pwdPolicies&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the pwdPolicy object&lt;br /&gt;
 ldapadd -xy ~/pwd/ldap &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 objectClass: applicationProcess&lt;br /&gt;
 objectClass: pwdPolicy&lt;br /&gt;
 cn: default&lt;br /&gt;
 pwdAttribute: userPassword&lt;br /&gt;
 pwdLockout: TRUE&lt;br /&gt;
 pwdLockoutDuration: 3600&lt;br /&gt;
 pwdMaxFailure: 10&lt;br /&gt;
 pwdFailureCountInterval: 3600&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set it as the default password policy&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
With these settings, ten consecutive authentication failures with a username will lock the account for an hour.  Login failures are also cleared after an hour.  This means it&#039;s possible to try ten passwords per hour during a brute-force attack, which won&#039;t get the attacker very far.&lt;br /&gt;
&lt;br /&gt;
=== Time of last login ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;lastbind&amp;lt;/code&amp;gt; module of OpenLDAP keeps track of when a user last logged in.&lt;br /&gt;
&lt;br /&gt;
 # Load the module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
 # Enable the overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:About&amp;diff=1395</id>
		<title>FeministWiki:About</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:About&amp;diff=1395"/>
		<updated>2024-12-05T16:13:29Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;FeministWiki.org is a project by the German LLC:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
WikiWiz UG (haftungsbeschränkt)&lt;br /&gt;
&lt;br /&gt;
Richard-Wagner-Str. 25&lt;br /&gt;
&lt;br /&gt;
DE-35321 Laubach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
USt-IdNr. DE414203449&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
District court Gießen, HRB 10100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Legal correspondent: Taylan Ulrich Kammer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
E-Mail: info@feministwiki.org&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Main_Page&amp;diff=1394</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Main_Page&amp;diff=1394"/>
		<updated>2024-11-13T11:50:32Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Who&amp;#039;s behind the project? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageSeo&lt;br /&gt;
|description = Welcome to the FeministWiki, a digital platform for feminism consisting of a wiki, forum, chat, blog hosting, and more.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;[[:de:Hauptseite|Deutsch]] - [[:es:Página_principal|Español]] - [[:fr:Accueil|Français]] - [[:it:Pagina_principale|Italiano]] - [[:pt:Página_principal|Português]]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Welcome to &#039;&#039;&#039;FeministWiki&#039;&#039;&#039;, a wiki and integrated digital platform for feminism.&lt;br /&gt;
&lt;br /&gt;
A wiki is a knowledge-base like an encyclopedia, but managed by the public.  The FeministWiki specializes on feminism, and is managed by feminists and their supporters.  It aims to archive and present information relevant to feminism, and explain feminist perspectives to the reader.&lt;br /&gt;
&lt;br /&gt;
Further, the FeministWiki aims to offer a complete integrated digital platform for feminists, with components such as a blogging platform, a discussion forum, a messaging/chat system, private and shared online storage for large files, and more.  You don&#039;t need to provide any personally identifying information to become a member, nor do you need to pay; the modest number of users makes the platform cheap to run.&lt;br /&gt;
&lt;br /&gt;
There are a few ways to become a member:&lt;br /&gt;
* Use the [https://account.feministwiki.org/register.html Registration Request] form to ask for an account.&lt;br /&gt;
* Contact an existing member and have them create an account for you by using the [https://account.feministwiki.org/add-member.html Add Member] form.&lt;br /&gt;
* Ask for an account by manually contacting technician@feministwiki.org or by messaging an official social media account of the FeministWiki.&lt;br /&gt;
&lt;br /&gt;
Spinster: [https://spinster.xyz/@FeministWiki @FeministWiki] (preferred) &amp;lt;br/&amp;gt;&lt;br /&gt;
Twitter: [https://twitter.com/@FeministWiki @FeministWiki] &amp;lt;br/&amp;gt;&lt;br /&gt;
Facebook: [https://www.facebook.com/FeministWiki/ FeministWiki]&lt;br /&gt;
&lt;br /&gt;
Once you are a member, you will be given a username and password with which you can log in to all FeministWiki services.  For example, to log in to the wiki itself (which you are reading right now), use the small &amp;quot;Log in&amp;quot; link at the top right of the page.&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;&#039;[[FW:Welcome|Welcome page]]&#039;&#039;&#039; for further information on the FeministWiki, written with new members in mind.&lt;br /&gt;
&lt;br /&gt;
Heads up: &#039;&#039;&#039;the FeministWiki needs you&#039;&#039;&#039;.  All of the technical infrastructure of the FeministWiki is only useful if there&#039;s a community making use of it, and content on the wiki doesn&#039;t write itself!  Be bold, don&#039;t shy off of asking for membership, and let the community and the world benefit from your added knowledge.  You can become a member even if you have no intention to contribute to the actual wiki; feel free to chat away with other members, discuss matters important to you on the forum, or use the file storage to have a central place to store your favorite information-material on feminism.&lt;br /&gt;
&lt;br /&gt;
== Check out some articles ==&lt;br /&gt;
&lt;br /&gt;
=== Notable feminists ===&lt;br /&gt;
&lt;br /&gt;
* [[Magdalen Berns]]&lt;br /&gt;
&lt;br /&gt;
=== Sex, gender, and trans activism ===&lt;br /&gt;
&lt;br /&gt;
* [[Gender]]&lt;br /&gt;
* [[Transgender ideology]]&lt;br /&gt;
* [[Cisgender]]&lt;br /&gt;
* [[Autogynephilia]]&lt;br /&gt;
* [[TERF]]&lt;br /&gt;
* [[Transwomen in women&#039;s sports]]&lt;br /&gt;
&lt;br /&gt;
=== Sex industry ===&lt;br /&gt;
&lt;br /&gt;
* [[Nordic Model]]&lt;br /&gt;
&lt;br /&gt;
=== Black feminism ===&lt;br /&gt;
&lt;br /&gt;
* [[Black feminism]]&lt;br /&gt;
&lt;br /&gt;
== What is feminism? ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of ideological groupings which call themselves feminism, and some of them are in contradiction with each other.  As such, one cannot support all types of feminism at the same time.  The FeministWiki is for people who adhere to a relatively straightforward and classical interpretation of feminism: the liberation of female people from male supremacism.  This is sometimes called &#039;&#039;radical feminism&#039;&#039; because male supremacism is a radical notion for many people, and its elimination requires radical changes to society.&lt;br /&gt;
&lt;br /&gt;
Male supremacism refers to social and political systems that use stereotypes, myths, discrimination, belittlement, violence, and other means to keep men in power and women oppressed.  Women are then exploited for reproductive and domestic labor, men&#039;s sexual gratification, and more.  Male supremacism also causes collateral damage to some men and boys.  For instance, effeminate boys and gay men are often targeted with punishment for failing to uphold the myth that men are inherently masculine.&lt;br /&gt;
&lt;br /&gt;
The FeministWiki promotes second-wave feminist literature:&lt;br /&gt;
&lt;br /&gt;
* [https://radfem.org/ Radical Feminist Archives]&lt;br /&gt;
&lt;br /&gt;
The FeministWiki is in full support of the Women&#039;s Human Rights Campaign:&lt;br /&gt;
&lt;br /&gt;
* [https://www.womensdeclaration.com/ Declaration on Women&#039;s Sex-Based Rights]&lt;br /&gt;
&lt;br /&gt;
The FeministWiki recommends Spinster as a feminism-friendly social media platform:&lt;br /&gt;
&lt;br /&gt;
* [https://spinster.xyz Spinster.xyz]&lt;br /&gt;
&lt;br /&gt;
Further, the FeministWiki promotes and stands in solidarity with the following groups and organizations:&lt;br /&gt;
&lt;br /&gt;
* [http://lgballiance.org.uk LGB Alliance]: The LGB Alliance&lt;br /&gt;
* [http://womensliberationfront.org/ WoLF]: The Women&#039;s Liberation Front&lt;br /&gt;
* [https://feministcurrent.com/ Feminist Current]: Canadian feminist news, commentary, and podcasts&lt;br /&gt;
* [https://www.rapereliefshelter.bc.ca/ Vancouver Rape Relief]: Female-only rape-relief and women&#039;s shelter&lt;br /&gt;
* [https://nordicmodelnow.org/ Nordic Model Now]: Educational movement for the abolition of prostitution&lt;br /&gt;
* [http://www.spaceintl.org/ SPACE International]: Survivors of Prostitution Abuse Calling for Enlightenment&lt;br /&gt;
* [https://womansplaceuk.org/ Woman&#039;s Place UK]: Women&#039;s campaigning group scrutinizing gender self-identification&lt;br /&gt;
* [https://speakupforwomen.nz/ Speak Up for Women]: New Zealand group opposing gender self-identification&lt;br /&gt;
* [https://feministstruggle.org/ Feminists in Struggle - FIST]: US-based female-only radical feminist network&lt;br /&gt;
&lt;br /&gt;
== Who&#039;s behind the project? ==&lt;br /&gt;
&lt;br /&gt;
The FeministWiki platform is offered to the public for free by the German LLC &#039;&#039;&#039;WikiWiz UG (haftungsbeschränkt)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The technical infrastructure is managed by [[FW:Technician|the technician]], who also offers user support.  For support, please contact technician@feministwiki.org.&lt;br /&gt;
&lt;br /&gt;
For legal inquiries please contact info@feministwiki.org or feministwiki@gmail.com.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Language links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[de:Hauptseite]] [[es:Página_principal]] [[fr:Accueil]] [[it:Pagina_principale]] [[pt:Página_principal]]&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:About&amp;diff=1393</id>
		<title>FeministWiki:About</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:About&amp;diff=1393"/>
		<updated>2024-10-11T08:30:01Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;FeministWiki.org is a project by the German LLC:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
WikiWiz UG (haftungsbeschränkt)&lt;br /&gt;
&lt;br /&gt;
Richard-Wagner-Str. 25&lt;br /&gt;
&lt;br /&gt;
DE-35321 Laubach&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
District court Gießen, HRB 10100&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Legal correspondent: Taylan Ulrich Kammer&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
E-Mail: info@feministwiki.org&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1392</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1392"/>
		<updated>2024-06-02T20:15:35Z</updated>

		<summary type="html">&lt;p&gt;Technician: Blanked the page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1391</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1391"/>
		<updated>2024-06-02T20:09:00Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 15&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1390</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1390"/>
		<updated>2024-06-02T20:00:12Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 14&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1389</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1389"/>
		<updated>2024-06-02T19:45:32Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 13&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1388</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1388"/>
		<updated>2024-06-02T19:26:46Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 12&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1387</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1387"/>
		<updated>2024-06-02T19:26:39Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 11&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1386</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1386"/>
		<updated>2024-06-02T19:23:38Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 10&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1385</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1385"/>
		<updated>2024-06-02T19:20:12Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 9&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1384</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1384"/>
		<updated>2024-06-02T19:19:59Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 8&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1383</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1383"/>
		<updated>2024-06-02T19:18:51Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 7&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1382</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1382"/>
		<updated>2024-06-02T18:22:53Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 6&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1381</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1381"/>
		<updated>2024-06-02T18:22:35Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 5&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1380</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1380"/>
		<updated>2024-06-02T18:16:07Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 4&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1379</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1379"/>
		<updated>2024-06-02T18:15:37Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 3&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1378</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1378"/>
		<updated>2024-06-02T18:15:17Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test 2&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1377</id>
		<title>User:Technician</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=User:Technician&amp;diff=1377"/>
		<updated>2024-06-02T18:14:48Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Test&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1376</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1376"/>
		<updated>2024-06-01T17:37:00Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine {{=}} &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/feministwiki/certs feministwiki.dev:/etc/feministwiki/certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/feministwiki/certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1375</id>
		<title>FeministWiki:Technical documentation</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1375"/>
		<updated>2024-06-01T17:31:34Z</updated>

		<summary type="html">&lt;p&gt;Technician: Update IP address.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the FeministWiki&#039;s technical infrastructure, the target audience being technicians.  Note that while this page will help you understand the inner workings of the FeministWiki, it&#039;s not optimal for guiding you through the setup of a new server.  For that, see the page [[FW:Server setup]] instead.&lt;br /&gt;
&lt;br /&gt;
== Hosts ==&lt;br /&gt;
&lt;br /&gt;
The following table documents the basic DNS configuration, and can be used as part of the {{C|/etc/hosts}} file on each server to obviate the need for DNS lookups when connecting to one another.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!IP            !! FQDN                        !! Host          !! Purpose                 !! Ports&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||            feministwiki.org ||               || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||        www.feministwiki.org || www           || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       ldap.feministwiki.org || ldap          || LDAP                    || -&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      blogs.feministwiki.org || blogs         || Blogging                || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       chat.feministwiki.org || chat          || Web-client for XMPP     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      forum.feministwiki.org || forum         || BBS Forum               || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       mail.feministwiki.org || mail          || Web-client for Mail     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||      files.feministwiki.org || files         || File storage            || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       imap.feministwiki.org || imap          || IMAP                    || 993&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       pop3.feministwiki.org || pop3          || POP3                    || 995&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       smtp.feministwiki.org || smtp          || SMTP                    || 25, 465, 587&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||       xmpp.feministwiki.org || xmpp          || XMPP                    || 5222, 5223, 5269, 5270, 5443, 7777&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||        irc.feministwiki.org || irc           || IRC                     || 6697&lt;br /&gt;
|-&lt;br /&gt;
|116.202.218.124 ||    account.feministwiki.org || account       || Account operations      || 80, 443&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As you can see, all services are on the same server for now.  However, it should be kept as an open possibility that the hosts are split across different IPs.  When done so, the {{C|ldap}} host should listen on 636 for LDAPS connections.&lt;br /&gt;
&lt;br /&gt;
There are no AAAA entries in the DNS because we only allow IPv4 for incoming connections.  This simplifies security auditing.&lt;br /&gt;
&lt;br /&gt;
== Special DNS entries ==&lt;br /&gt;
&lt;br /&gt;
For CAA:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Name !! Flag !! Tag   !! Value          &lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || issue || letsencrypt.org&lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || iodef || admin@feministwiki.org&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For email:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data                                                                   !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|MX   || @               || smtp.feministwiki.org                                                  || Mail server&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || v=spf1 mx -all                                                         || SPF&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || mail._domainkey || v=DKIM1; k=rsa; p=&amp;lt;pubkey&amp;gt;                                             || DKIM&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || _dmarc          || v=DMARC1; p=reject; rua=&amp;lt;nowiki&amp;gt;mailto:admin&amp;lt;/nowiki&amp;gt;@feministwiki.org || DMARC&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; There must be a direct A or AAAA record (not a CNAME record) for the domain name specified in the MX record.&lt;br /&gt;
&lt;br /&gt;
For XMPP:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Service      !! Protocol !! Name !! Destination           !! Port&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-client || _tcp     || @    || xmpp.feministwiki.org || 5222&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-server || _tcp     || @    || xmpp.feministwiki.org || 5269&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-client || _tcp     || @    || xmpp.feministwiki.org || 5223&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-server || _tcp     || @    || xmpp.feministwiki.org || 5270&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Google Site Verification:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || google-site-verification=&amp;lt;key&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall ==&lt;br /&gt;
&lt;br /&gt;
The simple {{C|ufw}} firewall-frontend is used to trivially limit all network I/O to the ports you can see in the host table above, plus port 22 for ssh and scp.&lt;br /&gt;
&lt;br /&gt;
UFW adds IPv6 rules by default, which can be prevented by using more explicit rules.  Consider the following rule:&lt;br /&gt;
&lt;br /&gt;
  ufw allow 12345/tcp  # will allow TCP connections to port 12345 via IPv4 and IPv6&lt;br /&gt;
&lt;br /&gt;
To limit this to IPv4 you can instead use this:&lt;br /&gt;
&lt;br /&gt;
  ufw allow proto tcp to 0.0.0.0/0 port 12345  # will allow TCP connections to port 12345 via IPv4 only&lt;br /&gt;
&lt;br /&gt;
== Fail2ban ==&lt;br /&gt;
&lt;br /&gt;
We use {{C|fail2ban}} to detect brute force attempts on some services.  The git repository for scripts and config contains the relevant Fail2ban configuration under {{C|etc/fail2ban}}.&lt;br /&gt;
&lt;br /&gt;
== SSH access ==&lt;br /&gt;
&lt;br /&gt;
FeministWiki hosts have ssh enabled for {{C|root}} access, but password login is disabled.  You must own a valid private key to log in.&lt;br /&gt;
&lt;br /&gt;
== Git repo of scripts and configuration ==&lt;br /&gt;
&lt;br /&gt;
The following GitHub account hosts repositories with scripts and configuration used by the FeministWiki:&lt;br /&gt;
&lt;br /&gt;
https://github.com/FeministWiki&lt;br /&gt;
&lt;br /&gt;
== Certs ==&lt;br /&gt;
&lt;br /&gt;
The FeministWiki uses LetsEncrypt to acquire digital certificates for encrypted communication.&lt;br /&gt;
&lt;br /&gt;
After certificates are generated with {{C|certbot}}, copies of them are put into {{C|/etc/feministwiki/certs}}, and the group ownership and permissions of the {{C|privkey.pem}} and {{C|bundle.pem}} files are set such that any user who&#039;s in the {{C|ssl-cert}} group can read the private key and bundle.  (The others can be read by anyone anyway.)  A script in {{C|/etc/letsencrypt/renewal-hooks/post}} is responsible for taking care of this after automatic executions of certbot scheduled by the operating system.&lt;br /&gt;
&lt;br /&gt;
The file {{C|/etc/feministwiki/certs/bundle.pem}} is useful for programs that don&#039;t have the capability of reading a separate cert and key file; it combines the full certificate chain ({{C|fullchain.pem}}) with the private key in a single file.&lt;br /&gt;
&lt;br /&gt;
If you ever add a new domain under which the FeministWiki server will be reachable, add it as a line to the file {{C|/etc/feministwiki/domains}} and run the script {{C|/root/bin/letsencrypt-refresh}}.  This script takes care of running {{C|certbot}} to refresh the cert files, and populating the {{C|/etc/feministwiki/certs}} directory with updated files.&lt;br /&gt;
&lt;br /&gt;
Note that whenever you run the {{C|letsencrypt-refresh}} script, it will momentarily stop the web server.  This means you&#039;re causing a short outage of the web-based services of the FeministWiki whenever you run the script.&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
&lt;br /&gt;
This section documents the individual services of the FeministWiki.  They should work regardless of what server they&#039;re on.  I.e. every service could in theory be hosted on its own server.&lt;br /&gt;
&lt;br /&gt;
=== LDAP ===&lt;br /&gt;
&lt;br /&gt;
Host: ldap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: OpenLDAP&lt;br /&gt;
&lt;br /&gt;
The LDAP service contains the central database of FeministWiki members.  For details on the LDAP schema, see [[FeministWiki:LDAP Schema]].&lt;br /&gt;
&lt;br /&gt;
=== Wiki ===&lt;br /&gt;
&lt;br /&gt;
Host: feministwiki.org, www.feministwiki.org, fem.wiki, feminist.wiki, feminism.wiki, feministwiki.de, www.feministwiki.de &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: MediaWiki&lt;br /&gt;
&lt;br /&gt;
The wiki uses a [https://www.mediawiki.org/wiki/MediaWiki MediaWiki] installation located at {{C|/var/www/fw/wiki/w}}.  It uses the [https://www.mediawiki.org/wiki/LDAP_Stack LDAP Stack] extension for login management, and the &amp;quot;Short URL&amp;quot; feature is enabled.  The wiki uses the SQL database called &amp;quot;feministwiki&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
The default wiki is in English.  Parallel wiki installations for different languages are supported via a combination of Apache&#039;s URL rewriting, and conditional branches in the {{C|LocalSettings.php}} file of the MediaWiki installation:&lt;br /&gt;
&lt;br /&gt;
* The rewrite rules ensure that, for any supported language {{C|xy}}, URLs beginning with {{C|/xy/wiki/...}} internally resolve to {{C|/w/index.php}} and URLs beginning with {{C|/xy/w/...}} resolve to {{C|/w/...}}.&lt;br /&gt;
* The LocalSettings file checks {{C|$_SERVER[&#039;REQUEST_URI&#039;]}} to determine the language code prefix in the requested URL, and configures things accordingly:&lt;br /&gt;
** It sets {{C|$wgArticlePath}} to {{C|/xy/wiki/$1}} so that {{C|/w/index.php}} knows that when it&#039;s invoked via such a URL, it should serve an article.&lt;br /&gt;
** It sets {{C|$wgScriptPath}} to {{C|/xy/w}} so that links to scripts served by MediaWiki are correct for the language.&lt;br /&gt;
** It sets the SQL database name to {{C|feministwiki_xy}}.&lt;br /&gt;
** It configures a &amp;quot;foreign&amp;quot; image database via the [https://www.mediawiki.org/wiki/Manual:$wgForeignFileRepos#Using_files_from_a_database_that_you_can_access_:_ForeignDBRepo,_ForeignDBViaLBRepo ForeignDBRepo] method so that the media upload database of the default wiki is used by all, instead of every parallel wiki having its own media database.&lt;br /&gt;
&lt;br /&gt;
To add a new language, follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Clone the English wiki&#039;s database into a new one via: {{C|mysqldump feministwiki &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; mysql feministwiki_xy}}&lt;br /&gt;
* Grant permissions on the new database via: {{C|GRANT ALL ON feministwiki_xy.* TO feministwiki@localhost;}}&lt;br /&gt;
* Edit {{C|/etc/apache2/sites-available/000-wiki.conf}} to add the line: {{C|Use Wiki xy}}&lt;br /&gt;
* Add the language to {{C|~/bin/fw-update-languages.sh}} and run it&lt;br /&gt;
&lt;br /&gt;
The last step will produce a lot of errors complaining about keys already existing; these can be safely ignored.&lt;br /&gt;
&lt;br /&gt;
The domain names feministwiki.de and www.feministwiki.de redirect to {{C|https://feministwiki.org/de}}.  For instance, requesting {{C|https://feministwiki.de/wiki/Hauptseite}} will result in an HTTP redirect to {{C|https://feministwiki.org/de/wiki/Hauptseite}}.&lt;br /&gt;
&lt;br /&gt;
=== Blogs ===&lt;br /&gt;
&lt;br /&gt;
Host: blogs.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: WordPress (multisite)&lt;br /&gt;
&lt;br /&gt;
This is an installation of WordPress in {{C|/var/www/fw/blogs}}, with the &amp;quot;multisite network&amp;quot; feature enabled on a path-basis, so users can have their own blogs on URLs like {{C|blogs.feministwiki.org/janedoe}}.  LDAP authentication is enabled via the AD/LDAP plugin from miniOrange.&lt;br /&gt;
&lt;br /&gt;
Users from LDAP who log in for the first time are automatically registered as &amp;quot;Subscriber&amp;quot; accounts, and the admin can change their WordPress role &amp;quot;Author&amp;quot; to allow publishing.&lt;br /&gt;
&lt;br /&gt;
This WordPress installation uses the SQL database called &amp;quot;blogs&amp;quot; and an SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Chat (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: chat.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Converse.js&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministChat uses the full-screen &amp;quot;Impress&amp;quot; variant of the [https://conversejs.org/ Converse.js] XMPP client.  The hosted HTML and JS files are located at {{C|/var/www/fw/chat}}, although they load Converse.js as an external script from upstream, which is why the self-hosted HTML and JS are very minimal.&lt;br /&gt;
&lt;br /&gt;
=== Forum ===&lt;br /&gt;
&lt;br /&gt;
Host: forum.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: phpBB&lt;br /&gt;
&lt;br /&gt;
The forum uses a [https://www.phpbb.com/ phpBB] installation located at {{C|/var/www/fw/forum}}.  Most configuration of phpBB, including LDAP authentication, is done through its administration panel.  The style used by the forum is a minimally changed &amp;quot;ProSilver Dark&amp;quot;.  The forum uses the SQL database called &amp;quot;feministforum&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Mail (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: mail.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Roundcube&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministMail uses the [https://roundcube.net/ Roundcube] mail client, installed at {{C|/var/www/fw/mail}}.  It uses a FeministWiki-branded modification of the new &amp;quot;elastic&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
&lt;br /&gt;
Host: files.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Nextcloud&lt;br /&gt;
&lt;br /&gt;
FeministFiles is a [https://nextcloud.com/ Nextcloud] installation with some branding, and LDAP authentication, installed at {{C|/var/www/fw/files}}.&lt;br /&gt;
&lt;br /&gt;
=== IMAP ===&lt;br /&gt;
&lt;br /&gt;
Host: imap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [https://www.dovecot.org/ Dovecot] IMAP server, configured for LDAP authentication and using virtual mail boxes under {{C|/home/vmail}}.&lt;br /&gt;
&lt;br /&gt;
=== POP3 ===&lt;br /&gt;
&lt;br /&gt;
Host: pop3.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
While Dovecot is primarily an IMAP server, it also offers POP3 support, which the FeministWiki installation has enabled.&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
&lt;br /&gt;
Host: smtp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Postfix, OpenDKIM&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [http://www.postfix.org/ Postfix] SMTP server, using SASL authentication through Dovecot, LDAP-based virtual mail boxes under {{C|/home/vmail}}, and DKIM signing via OpenDKIM.  Send a mail to a Gmail account and use the &amp;quot;Show original&amp;quot; feature of Gmail to see if the mail passes SPF, DKIM, and DMARC tests.&lt;br /&gt;
&lt;br /&gt;
There are also various tools on the web to automatically test the DNS settings for correctness, to check if the domain/IP is on blacklists, etc., which you can find via Google.  All in all, FeministMail is probably the most complicated service of the FeministWiki, as far as technical background goes.&lt;br /&gt;
&lt;br /&gt;
=== Mailing lists ===&lt;br /&gt;
&lt;br /&gt;
Email domain: lists.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: GNU Mailman, Postfix&lt;br /&gt;
&lt;br /&gt;
Postfix is configured to recognize {{C|lists.feministwiki.org}} as a &amp;quot;local&amp;quot; domain.  This means it uses the file specified in the {{C|alias_maps}} configuration directive (typically {{C|/etc/aliases}}) to decide the final recipient of an e-mail sent to this domain.  Correspondingly, we populate {{C|/etc/aliases}} with the aliases needed by Mailman to operate each mailing list it controls.&lt;br /&gt;
&lt;br /&gt;
Note that there is no DNS entry for {{C|lists.feministwiki.org}} because e-mail software just checks the MX record for {{C|feministwiki.org}} when the recipient is from the domain {{C|&amp;lt;em&amp;gt;anything&amp;lt;/em&amp;gt;.feministwiki.org}}.&lt;br /&gt;
&lt;br /&gt;
=== XMPP ===&lt;br /&gt;
&lt;br /&gt;
Host: xmpp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: ejabberd&lt;br /&gt;
&lt;br /&gt;
FeministChat uses the [https://www.ejabberd.im/ ejabberd] XMPP server, configured to use LDAP authentication and an LDAP-based shared roster group for all members.&lt;br /&gt;
&lt;br /&gt;
=== IRC ===&lt;br /&gt;
&lt;br /&gt;
Host: irc.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: InspIRCd&lt;br /&gt;
&lt;br /&gt;
FeministIRC uses the [http://www.inspircd.org/ InspIRCd] IRC server with the {{C|ldapauth}} module for LDAP authentication.  The client is authenticated via the combination of the NICK and PASS provided upon connection, which must correspond to the FeministWiki credentials.&lt;br /&gt;
&lt;br /&gt;
=== Account operations ===&lt;br /&gt;
&lt;br /&gt;
Host: account.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: custom&lt;br /&gt;
&lt;br /&gt;
This custom web interface hosted at {{C|/var/www/fw/account}} lets you complete several tasks related to FeministWiki membership, such as changing your account settings, resetting your password, or adding a new member.  It also contains a form to request membership.  The interface is written in HTML, CSS, PHP, and C.&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1374</id>
		<title>FeministWiki:Technical documentation</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Technical_documentation&amp;diff=1374"/>
		<updated>2024-05-10T11:55:39Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Certs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the FeministWiki&#039;s technical infrastructure, the target audience being technicians.  Note that while this page will help you understand the inner workings of the FeministWiki, it&#039;s not optimal for guiding you through the setup of a new server.  For that, see the page [[FW:Server setup]] instead.&lt;br /&gt;
&lt;br /&gt;
== Hosts ==&lt;br /&gt;
&lt;br /&gt;
The following table documents the basic DNS configuration, and can be used as part of the {{C|/etc/hosts}} file on each server to obviate the need for DNS lookups when connecting to one another.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!IP            !! FQDN                        !! Host          !! Purpose                 !! Ports&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||            feministwiki.org ||               || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||        www.feministwiki.org || www           || Wiki                    || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       ldap.feministwiki.org || ldap          || LDAP                    || -&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||      blogs.feministwiki.org || blogs         || Blogging                || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       chat.feministwiki.org || chat          || Web-client for XMPP     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||      forum.feministwiki.org || forum         || BBS Forum               || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       mail.feministwiki.org || mail          || Web-client for Mail     || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||      files.feministwiki.org || files         || File storage            || 80, 443&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       imap.feministwiki.org || imap          || IMAP                    || 993&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       pop3.feministwiki.org || pop3          || POP3                    || 995&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       smtp.feministwiki.org || smtp          || SMTP                    || 25, 465, 587&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||       xmpp.feministwiki.org || xmpp          || XMPP                    || 5222, 5223, 5269, 5270, 5443, 7777&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||        irc.feministwiki.org || irc           || IRC                     || 6697&lt;br /&gt;
|-&lt;br /&gt;
|85.214.206.20 ||    account.feministwiki.org || account       || Account operations      || 80, 443&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As you can see, all services are on the same server for now.  However, it should be kept as an open possibility that the hosts are split across different IPs.  When done so, the {{C|ldap}} host should listen on 636 for LDAPS connections.&lt;br /&gt;
&lt;br /&gt;
There are no AAAA entries in the DNS because we only allow IPv4 for incoming connections.  This simplifies security auditing.&lt;br /&gt;
&lt;br /&gt;
== Special DNS entries ==&lt;br /&gt;
&lt;br /&gt;
For CAA:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Name !! Flag !! Tag   !! Value          &lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || issue || letsencrypt.org&lt;br /&gt;
|-&lt;br /&gt;
|CAA  || @    || 0    || iodef || admin@feministwiki.org&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For email:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data                                                                   !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
|MX   || @               || smtp.feministwiki.org                                                  || Mail server&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || v=spf1 mx -all                                                         || SPF&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || mail._domainkey || v=DKIM1; k=rsa; p=&amp;lt;pubkey&amp;gt;                                             || DKIM&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || _dmarc          || v=DMARC1; p=reject; rua=&amp;lt;nowiki&amp;gt;mailto:admin&amp;lt;/nowiki&amp;gt;@feministwiki.org || DMARC&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; There must be a direct A or AAAA record (not a CNAME record) for the domain name specified in the MX record.&lt;br /&gt;
&lt;br /&gt;
For XMPP:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Service      !! Protocol !! Name !! Destination           !! Port&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-client || _tcp     || @    || xmpp.feministwiki.org || 5222&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpp-server || _tcp     || @    || xmpp.feministwiki.org || 5269&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-client || _tcp     || @    || xmpp.feministwiki.org || 5223&lt;br /&gt;
|-&lt;br /&gt;
|SRV  || _xmpps-server || _tcp     || @    || xmpp.feministwiki.org || 5270&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Google Site Verification:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type !! Host            !! Data&lt;br /&gt;
|-&lt;br /&gt;
|TXT  || @               || google-site-verification=&amp;lt;key&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Firewall ==&lt;br /&gt;
&lt;br /&gt;
The simple {{C|ufw}} firewall-frontend is used to trivially limit all network I/O to the ports you can see in the host table above, plus port 22 for ssh and scp.&lt;br /&gt;
&lt;br /&gt;
UFW adds IPv6 rules by default, which can be prevented by using more explicit rules.  Consider the following rule:&lt;br /&gt;
&lt;br /&gt;
  ufw allow 12345/tcp  # will allow TCP connections to port 12345 via IPv4 and IPv6&lt;br /&gt;
&lt;br /&gt;
To limit this to IPv4 you can instead use this:&lt;br /&gt;
&lt;br /&gt;
  ufw allow proto tcp to 0.0.0.0/0 port 12345  # will allow TCP connections to port 12345 via IPv4 only&lt;br /&gt;
&lt;br /&gt;
== Fail2ban ==&lt;br /&gt;
&lt;br /&gt;
We use {{C|fail2ban}} to detect brute force attempts on some services.  The git repository for scripts and config contains the relevant Fail2ban configuration under {{C|etc/fail2ban}}.&lt;br /&gt;
&lt;br /&gt;
== SSH access ==&lt;br /&gt;
&lt;br /&gt;
FeministWiki hosts have ssh enabled for {{C|root}} access, but password login is disabled.  You must own a valid private key to log in.&lt;br /&gt;
&lt;br /&gt;
== Git repo of scripts and configuration ==&lt;br /&gt;
&lt;br /&gt;
The following GitHub account hosts repositories with scripts and configuration used by the FeministWiki:&lt;br /&gt;
&lt;br /&gt;
https://github.com/FeministWiki&lt;br /&gt;
&lt;br /&gt;
== Certs ==&lt;br /&gt;
&lt;br /&gt;
The FeministWiki uses LetsEncrypt to acquire digital certificates for encrypted communication.&lt;br /&gt;
&lt;br /&gt;
After certificates are generated with {{C|certbot}}, copies of them are put into {{C|/etc/feministwiki/certs}}, and the group ownership and permissions of the {{C|privkey.pem}} and {{C|bundle.pem}} files are set such that any user who&#039;s in the {{C|ssl-cert}} group can read the private key and bundle.  (The others can be read by anyone anyway.)  A script in {{C|/etc/letsencrypt/renewal-hooks/post}} is responsible for taking care of this after automatic executions of certbot scheduled by the operating system.&lt;br /&gt;
&lt;br /&gt;
The file {{C|/etc/feministwiki/certs/bundle.pem}} is useful for programs that don&#039;t have the capability of reading a separate cert and key file; it combines the full certificate chain ({{C|fullchain.pem}}) with the private key in a single file.&lt;br /&gt;
&lt;br /&gt;
If you ever add a new domain under which the FeministWiki server will be reachable, add it as a line to the file {{C|/etc/feministwiki/domains}} and run the script {{C|/root/bin/letsencrypt-refresh}}.  This script takes care of running {{C|certbot}} to refresh the cert files, and populating the {{C|/etc/feministwiki/certs}} directory with updated files.&lt;br /&gt;
&lt;br /&gt;
Note that whenever you run the {{C|letsencrypt-refresh}} script, it will momentarily stop the web server.  This means you&#039;re causing a short outage of the web-based services of the FeministWiki whenever you run the script.&lt;br /&gt;
&lt;br /&gt;
== Services ==&lt;br /&gt;
&lt;br /&gt;
This section documents the individual services of the FeministWiki.  They should work regardless of what server they&#039;re on.  I.e. every service could in theory be hosted on its own server.&lt;br /&gt;
&lt;br /&gt;
=== LDAP ===&lt;br /&gt;
&lt;br /&gt;
Host: ldap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: OpenLDAP&lt;br /&gt;
&lt;br /&gt;
The LDAP service contains the central database of FeministWiki members.  For details on the LDAP schema, see [[FeministWiki:LDAP Schema]].&lt;br /&gt;
&lt;br /&gt;
=== Wiki ===&lt;br /&gt;
&lt;br /&gt;
Host: feministwiki.org, www.feministwiki.org, fem.wiki, feminist.wiki, feminism.wiki, feministwiki.de, www.feministwiki.de &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: MediaWiki&lt;br /&gt;
&lt;br /&gt;
The wiki uses a [https://www.mediawiki.org/wiki/MediaWiki MediaWiki] installation located at {{C|/var/www/fw/wiki/w}}.  It uses the [https://www.mediawiki.org/wiki/LDAP_Stack LDAP Stack] extension for login management, and the &amp;quot;Short URL&amp;quot; feature is enabled.  The wiki uses the SQL database called &amp;quot;feministwiki&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
The default wiki is in English.  Parallel wiki installations for different languages are supported via a combination of Apache&#039;s URL rewriting, and conditional branches in the {{C|LocalSettings.php}} file of the MediaWiki installation:&lt;br /&gt;
&lt;br /&gt;
* The rewrite rules ensure that, for any supported language {{C|xy}}, URLs beginning with {{C|/xy/wiki/...}} internally resolve to {{C|/w/index.php}} and URLs beginning with {{C|/xy/w/...}} resolve to {{C|/w/...}}.&lt;br /&gt;
* The LocalSettings file checks {{C|$_SERVER[&#039;REQUEST_URI&#039;]}} to determine the language code prefix in the requested URL, and configures things accordingly:&lt;br /&gt;
** It sets {{C|$wgArticlePath}} to {{C|/xy/wiki/$1}} so that {{C|/w/index.php}} knows that when it&#039;s invoked via such a URL, it should serve an article.&lt;br /&gt;
** It sets {{C|$wgScriptPath}} to {{C|/xy/w}} so that links to scripts served by MediaWiki are correct for the language.&lt;br /&gt;
** It sets the SQL database name to {{C|feministwiki_xy}}.&lt;br /&gt;
** It configures a &amp;quot;foreign&amp;quot; image database via the [https://www.mediawiki.org/wiki/Manual:$wgForeignFileRepos#Using_files_from_a_database_that_you_can_access_:_ForeignDBRepo,_ForeignDBViaLBRepo ForeignDBRepo] method so that the media upload database of the default wiki is used by all, instead of every parallel wiki having its own media database.&lt;br /&gt;
&lt;br /&gt;
To add a new language, follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Clone the English wiki&#039;s database into a new one via: {{C|mysqldump feministwiki &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; mysql feministwiki_xy}}&lt;br /&gt;
* Grant permissions on the new database via: {{C|GRANT ALL ON feministwiki_xy.* TO feministwiki@localhost;}}&lt;br /&gt;
* Edit {{C|/etc/apache2/sites-available/000-wiki.conf}} to add the line: {{C|Use Wiki xy}}&lt;br /&gt;
* Add the language to {{C|~/bin/fw-update-languages.sh}} and run it&lt;br /&gt;
&lt;br /&gt;
The last step will produce a lot of errors complaining about keys already existing; these can be safely ignored.&lt;br /&gt;
&lt;br /&gt;
The domain names feministwiki.de and www.feministwiki.de redirect to {{C|https://feministwiki.org/de}}.  For instance, requesting {{C|https://feministwiki.de/wiki/Hauptseite}} will result in an HTTP redirect to {{C|https://feministwiki.org/de/wiki/Hauptseite}}.&lt;br /&gt;
&lt;br /&gt;
=== Blogs ===&lt;br /&gt;
&lt;br /&gt;
Host: blogs.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: WordPress (multisite)&lt;br /&gt;
&lt;br /&gt;
This is an installation of WordPress in {{C|/var/www/fw/blogs}}, with the &amp;quot;multisite network&amp;quot; feature enabled on a path-basis, so users can have their own blogs on URLs like {{C|blogs.feministwiki.org/janedoe}}.  LDAP authentication is enabled via the AD/LDAP plugin from miniOrange.&lt;br /&gt;
&lt;br /&gt;
Users from LDAP who log in for the first time are automatically registered as &amp;quot;Subscriber&amp;quot; accounts, and the admin can change their WordPress role &amp;quot;Author&amp;quot; to allow publishing.&lt;br /&gt;
&lt;br /&gt;
This WordPress installation uses the SQL database called &amp;quot;blogs&amp;quot; and an SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Chat (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: chat.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Converse.js&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministChat uses the full-screen &amp;quot;Impress&amp;quot; variant of the [https://conversejs.org/ Converse.js] XMPP client.  The hosted HTML and JS files are located at {{C|/var/www/fw/chat}}, although they load Converse.js as an external script from upstream, which is why the self-hosted HTML and JS are very minimal.&lt;br /&gt;
&lt;br /&gt;
=== Forum ===&lt;br /&gt;
&lt;br /&gt;
Host: forum.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: phpBB&lt;br /&gt;
&lt;br /&gt;
The forum uses a [https://www.phpbb.com/ phpBB] installation located at {{C|/var/www/fw/forum}}.  Most configuration of phpBB, including LDAP authentication, is done through its administration panel.  The style used by the forum is a minimally changed &amp;quot;ProSilver Dark&amp;quot;.  The forum uses the SQL database called &amp;quot;feministforum&amp;quot; and the SQL user of the same name.&lt;br /&gt;
&lt;br /&gt;
=== Mail (web interface) ===&lt;br /&gt;
&lt;br /&gt;
Host: mail.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Roundcube&lt;br /&gt;
&lt;br /&gt;
The web-interface for the FeministMail uses the [https://roundcube.net/ Roundcube] mail client, installed at {{C|/var/www/fw/mail}}.  It uses a FeministWiki-branded modification of the new &amp;quot;elastic&amp;quot; style.&lt;br /&gt;
&lt;br /&gt;
=== Files ===&lt;br /&gt;
&lt;br /&gt;
Host: files.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Nextcloud&lt;br /&gt;
&lt;br /&gt;
FeministFiles is a [https://nextcloud.com/ Nextcloud] installation with some branding, and LDAP authentication, installed at {{C|/var/www/fw/files}}.&lt;br /&gt;
&lt;br /&gt;
=== IMAP ===&lt;br /&gt;
&lt;br /&gt;
Host: imap.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [https://www.dovecot.org/ Dovecot] IMAP server, configured for LDAP authentication and using virtual mail boxes under {{C|/home/vmail}}.&lt;br /&gt;
&lt;br /&gt;
=== POP3 ===&lt;br /&gt;
&lt;br /&gt;
Host: pop3.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Dovecot&lt;br /&gt;
&lt;br /&gt;
While Dovecot is primarily an IMAP server, it also offers POP3 support, which the FeministWiki installation has enabled.&lt;br /&gt;
&lt;br /&gt;
=== SMTP ===&lt;br /&gt;
&lt;br /&gt;
Host: smtp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: Postfix, OpenDKIM&lt;br /&gt;
&lt;br /&gt;
FeministMail uses the [http://www.postfix.org/ Postfix] SMTP server, using SASL authentication through Dovecot, LDAP-based virtual mail boxes under {{C|/home/vmail}}, and DKIM signing via OpenDKIM.  Send a mail to a Gmail account and use the &amp;quot;Show original&amp;quot; feature of Gmail to see if the mail passes SPF, DKIM, and DMARC tests.&lt;br /&gt;
&lt;br /&gt;
There are also various tools on the web to automatically test the DNS settings for correctness, to check if the domain/IP is on blacklists, etc., which you can find via Google.  All in all, FeministMail is probably the most complicated service of the FeministWiki, as far as technical background goes.&lt;br /&gt;
&lt;br /&gt;
=== Mailing lists ===&lt;br /&gt;
&lt;br /&gt;
Email domain: lists.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: GNU Mailman, Postfix&lt;br /&gt;
&lt;br /&gt;
Postfix is configured to recognize {{C|lists.feministwiki.org}} as a &amp;quot;local&amp;quot; domain.  This means it uses the file specified in the {{C|alias_maps}} configuration directive (typically {{C|/etc/aliases}}) to decide the final recipient of an e-mail sent to this domain.  Correspondingly, we populate {{C|/etc/aliases}} with the aliases needed by Mailman to operate each mailing list it controls.&lt;br /&gt;
&lt;br /&gt;
Note that there is no DNS entry for {{C|lists.feministwiki.org}} because e-mail software just checks the MX record for {{C|feministwiki.org}} when the recipient is from the domain {{C|&amp;lt;em&amp;gt;anything&amp;lt;/em&amp;gt;.feministwiki.org}}.&lt;br /&gt;
&lt;br /&gt;
=== XMPP ===&lt;br /&gt;
&lt;br /&gt;
Host: xmpp.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: ejabberd&lt;br /&gt;
&lt;br /&gt;
FeministChat uses the [https://www.ejabberd.im/ ejabberd] XMPP server, configured to use LDAP authentication and an LDAP-based shared roster group for all members.&lt;br /&gt;
&lt;br /&gt;
=== IRC ===&lt;br /&gt;
&lt;br /&gt;
Host: irc.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: InspIRCd&lt;br /&gt;
&lt;br /&gt;
FeministIRC uses the [http://www.inspircd.org/ InspIRCd] IRC server with the {{C|ldapauth}} module for LDAP authentication.  The client is authenticated via the combination of the NICK and PASS provided upon connection, which must correspond to the FeministWiki credentials.&lt;br /&gt;
&lt;br /&gt;
=== Account operations ===&lt;br /&gt;
&lt;br /&gt;
Host: account.feministwiki.org &amp;lt;br/&amp;gt;&lt;br /&gt;
Software: custom&lt;br /&gt;
&lt;br /&gt;
This custom web interface hosted at {{C|/var/www/fw/account}} lets you complete several tasks related to FeministWiki membership, such as changing your account settings, resetting your password, or adding a new member.  It also contains a form to request membership.  The interface is written in HTML, CSS, PHP, and C.&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1373</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1373"/>
		<updated>2024-05-10T11:54:54Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Copy over certificates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/feministwiki/certs feministwiki.dev:/etc/feministwiki/certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/feministwiki/certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1372</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1372"/>
		<updated>2024-01-18T18:28:54Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Install miscellaneous tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 iotop \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Main_Page&amp;diff=1371</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Main_Page&amp;diff=1371"/>
		<updated>2024-01-18T14:07:32Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageSeo&lt;br /&gt;
|description = Welcome to the FeministWiki, a digital platform for feminism consisting of a wiki, forum, chat, blog hosting, and more.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;[[:de:Hauptseite|Deutsch]] - [[:es:Página_principal|Español]] - [[:fr:Accueil|Français]] - [[:it:Pagina_principale|Italiano]] - [[:pt:Página_principal|Português]]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Welcome to &#039;&#039;&#039;FeministWiki&#039;&#039;&#039;, a wiki and integrated digital platform for feminism.&lt;br /&gt;
&lt;br /&gt;
A wiki is a knowledge-base like an encyclopedia, but managed by the public.  The FeministWiki specializes on feminism, and is managed by feminists and their supporters.  It aims to archive and present information relevant to feminism, and explain feminist perspectives to the reader.&lt;br /&gt;
&lt;br /&gt;
Further, the FeministWiki aims to offer a complete integrated digital platform for feminists, with components such as a blogging platform, a discussion forum, a messaging/chat system, private and shared online storage for large files, and more.  You don&#039;t need to provide any personally identifying information to become a member, nor do you need to pay; the modest number of users makes the platform cheap to run.&lt;br /&gt;
&lt;br /&gt;
There are a few ways to become a member:&lt;br /&gt;
* Use the [https://account.feministwiki.org/register.html Registration Request] form to ask for an account.&lt;br /&gt;
* Contact an existing member and have them create an account for you by using the [https://account.feministwiki.org/add-member.html Add Member] form.&lt;br /&gt;
* Ask for an account by manually contacting technician@feministwiki.org or by messaging an official social media account of the FeministWiki.&lt;br /&gt;
&lt;br /&gt;
Spinster: [https://spinster.xyz/@FeministWiki @FeministWiki] (preferred) &amp;lt;br/&amp;gt;&lt;br /&gt;
Twitter: [https://twitter.com/@FeministWiki @FeministWiki] &amp;lt;br/&amp;gt;&lt;br /&gt;
Facebook: [https://www.facebook.com/FeministWiki/ FeministWiki]&lt;br /&gt;
&lt;br /&gt;
Once you are a member, you will be given a username and password with which you can log in to all FeministWiki services.  For example, to log in to the wiki itself (which you are reading right now), use the small &amp;quot;Log in&amp;quot; link at the top right of the page.&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;&#039;[[FW:Welcome|Welcome page]]&#039;&#039;&#039; for further information on the FeministWiki, written with new members in mind.&lt;br /&gt;
&lt;br /&gt;
Heads up: &#039;&#039;&#039;the FeministWiki needs you&#039;&#039;&#039;.  All of the technical infrastructure of the FeministWiki is only useful if there&#039;s a community making use of it, and content on the wiki doesn&#039;t write itself!  Be bold, don&#039;t shy off of asking for membership, and let the community and the world benefit from your added knowledge.  You can become a member even if you have no intention to contribute to the actual wiki; feel free to chat away with other members, discuss matters important to you on the forum, or use the file storage to have a central place to store your favorite information-material on feminism.&lt;br /&gt;
&lt;br /&gt;
== Check out some articles ==&lt;br /&gt;
&lt;br /&gt;
=== Notable feminists ===&lt;br /&gt;
&lt;br /&gt;
* [[Magdalen Berns]]&lt;br /&gt;
&lt;br /&gt;
=== Sex, gender, and trans activism ===&lt;br /&gt;
&lt;br /&gt;
* [[Gender]]&lt;br /&gt;
* [[Transgender ideology]]&lt;br /&gt;
* [[Cisgender]]&lt;br /&gt;
* [[Autogynephilia]]&lt;br /&gt;
* [[TERF]]&lt;br /&gt;
* [[Transwomen in women&#039;s sports]]&lt;br /&gt;
&lt;br /&gt;
=== Sex industry ===&lt;br /&gt;
&lt;br /&gt;
* [[Nordic Model]]&lt;br /&gt;
&lt;br /&gt;
=== Black feminism ===&lt;br /&gt;
&lt;br /&gt;
* [[Black feminism]]&lt;br /&gt;
&lt;br /&gt;
== What is feminism? ==&lt;br /&gt;
&lt;br /&gt;
There are a variety of ideological groupings which call themselves feminism, and some of them are in contradiction with each other.  As such, one cannot support all types of feminism at the same time.  The FeministWiki is for people who adhere to a relatively straightforward and classical interpretation of feminism: the liberation of female people from male supremacism.  This is sometimes called &#039;&#039;radical feminism&#039;&#039; because male supremacism is a radical notion for many people, and its elimination requires radical changes to society.&lt;br /&gt;
&lt;br /&gt;
Male supremacism refers to social and political systems that use stereotypes, myths, discrimination, belittlement, violence, and other means to keep men in power and women oppressed.  Women are then exploited for reproductive and domestic labor, men&#039;s sexual gratification, and more.  Male supremacism also causes collateral damage to some men and boys.  For instance, effeminate boys and gay men are often targeted with punishment for failing to uphold the myth that men are inherently masculine.&lt;br /&gt;
&lt;br /&gt;
The FeministWiki promotes second-wave feminist literature:&lt;br /&gt;
&lt;br /&gt;
* [https://radfem.org/ Radical Feminist Archives]&lt;br /&gt;
&lt;br /&gt;
The FeministWiki is in full support of the Women&#039;s Human Rights Campaign:&lt;br /&gt;
&lt;br /&gt;
* [https://www.womensdeclaration.com/ Declaration on Women&#039;s Sex-Based Rights]&lt;br /&gt;
&lt;br /&gt;
The FeministWiki recommends Spinster as a feminism-friendly social media platform:&lt;br /&gt;
&lt;br /&gt;
* [https://spinster.xyz Spinster.xyz]&lt;br /&gt;
&lt;br /&gt;
Further, the FeministWiki promotes and stands in solidarity with the following groups and organizations:&lt;br /&gt;
&lt;br /&gt;
* [http://lgballiance.org.uk LGB Alliance]: The LGB Alliance&lt;br /&gt;
* [http://womensliberationfront.org/ WoLF]: The Women&#039;s Liberation Front&lt;br /&gt;
* [https://feministcurrent.com/ Feminist Current]: Canadian feminist news, commentary, and podcasts&lt;br /&gt;
* [https://www.rapereliefshelter.bc.ca/ Vancouver Rape Relief]: Female-only rape-relief and women&#039;s shelter&lt;br /&gt;
* [https://nordicmodelnow.org/ Nordic Model Now]: Educational movement for the abolition of prostitution&lt;br /&gt;
* [http://www.spaceintl.org/ SPACE International]: Survivors of Prostitution Abuse Calling for Enlightenment&lt;br /&gt;
* [https://womansplaceuk.org/ Woman&#039;s Place UK]: Women&#039;s campaigning group scrutinizing gender self-identification&lt;br /&gt;
* [https://speakupforwomen.nz/ Speak Up for Women]: New Zealand group opposing gender self-identification&lt;br /&gt;
* [https://feministstruggle.org/ Feminists in Struggle - FIST]: US-based female-only radical feminist network&lt;br /&gt;
&lt;br /&gt;
== Who&#039;s behind the project? ==&lt;br /&gt;
&lt;br /&gt;
The FeministWiki platform is offered to the public by the German non-profit organization &#039;&#039;&#039;FeministWiki gemeinnützige UG (haftungsbeschränkt)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The FeministWiki g. UG is bound by German law to abide by the following mission statement (translated from German):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
1. The company exclusively and directly pursues charitable purposes within the meaning of the section &amp;quot;tax-privileged purposes&amp;quot; of the Tax Code. The purpose of the company is to promote equality between women and men.&lt;br /&gt;
&lt;br /&gt;
2. The purpose of the statutes is achieved by operating an online platform called feministwiki.org. The platform serves as an information center on the subject of feminism, as well as a communication platform for people who want to stand up for the rights of women. &lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The technical infrastructure is managed by [[FW:Technician|the technician]], who also offers user support.  For support, please contact technician@feministwiki.org.&lt;br /&gt;
&lt;br /&gt;
For legal inquiries please contact info@feministwiki.org or feministwiki@gmail.com.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Language links --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[de:Hauptseite]] [[es:Página_principal]] [[fr:Accueil]] [[it:Pagina_principale]] [[pt:Página_principal]]&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=Template:PageSeo&amp;diff=1370</id>
		<title>Template:PageSeo</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=Template:PageSeo&amp;diff=1370"/>
		<updated>2024-01-18T14:04:03Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;div style=&amp;quot;display: none;&amp;quot;&amp;gt;{{#seo:&lt;br /&gt;
|title = {{{fulltitle|{{{title|{{PAGENAME}}}}} - {{SITENAME}}}}}&lt;br /&gt;
|keywords = {{{fullkeywords|{{{keywords|{{PAGENAME}}}}}, {{SITENAME}}, feminism, wiki, feminist wiki, radical feminism, radfem, gender critical}}}&lt;br /&gt;
|description = {{{description}}}&lt;br /&gt;
|image = {{{image|FeministWiki_banner.png}}}&lt;br /&gt;
}}&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
Use this template to optimize a page for SEO.  It uses the &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{#seo:}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; tag underneath, which is added by the WikiSEO plugin.&lt;br /&gt;
&lt;br /&gt;
Example usage:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{{PageSeo&lt;br /&gt;
|title = An alternative title&lt;br /&gt;
|keywords = blah, blub, blip&lt;br /&gt;
|description = A summary of what this wiki page is about&lt;br /&gt;
|image = Some_image.jpg&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Default values:&lt;br /&gt;
&lt;br /&gt;
* {{c|title}}: &amp;lt;nowiki&amp;gt;{{PAGENAME}}&amp;lt;/nowiki&amp;gt; - {{SITENAME}}&lt;br /&gt;
* {{c|keywords}}: &amp;lt;nowiki&amp;gt;{{PAGENAME}}&amp;lt;/nowiki&amp;gt;, {{SITENAME}}, feminism, wiki, feminist wiki, radical feminism, radfem, gender critical&lt;br /&gt;
&lt;br /&gt;
If you provide the {{c|title}} parameter, it will automatically have {{c| - {{SITENAME}}}} appended to it.&lt;br /&gt;
&lt;br /&gt;
If you provide the {{c|keywords}} parameter, it will automatically have {{c|, {{SITENAME}}, feminism, wiki, feminist wiki, radical feminism, radfem, gender critical}} appended to it.&lt;br /&gt;
&lt;br /&gt;
If you would like to control the full title or keywords tag contents, you can use {{c|fulltitle}} and {{c|fullkeywords}} instead.&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1369</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1369"/>
		<updated>2024-01-18T12:52:32Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Install miscellaneous tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 composer \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1368</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1368"/>
		<updated>2024-01-16T17:25:41Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Install PHP and modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-bz2 \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1367</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1367"/>
		<updated>2024-01-16T13:48:17Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Apache modules and configuration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi rewrite&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1366</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1366"/>
		<updated>2024-01-14T19:13:42Z</updated>

		<summary type="html">&lt;p&gt;Technician: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1365</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1365"/>
		<updated>2024-01-14T19:12:45Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Create vmail user */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Make sure Postfix can connect to OpenDKIM ===&lt;br /&gt;
&lt;br /&gt;
 mkdir -p /var/spool/postfix/opendkim&lt;br /&gt;
 chown opendkim:opendkim /var/spool/postfix/opendkim&lt;br /&gt;
 adduser postfix opendkim&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1364</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1364"/>
		<updated>2024-01-14T13:38:05Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Finishing up */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
As with the old server, we leave MariaDB running since it will be needed for data transfer.&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1363</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1363"/>
		<updated>2024-01-14T13:34:22Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Stop services on the old server */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1362</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1362"/>
		<updated>2024-01-14T13:33:52Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Deactivate again */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop opendkim&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1361</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1361"/>
		<updated>2024-01-14T13:33:18Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Deactivate again */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop fw-wiki-job-runner&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Note that we leave MariaDB running, since it needs to be live for data transfer.&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1360</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1360"/>
		<updated>2024-01-14T13:31:07Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Contents of /var/www */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
There&#039;s actually a systemd service found in {{C|/var/www/fw/wiki}} that you&#039;ll want to enable on the new server:&lt;br /&gt;
&lt;br /&gt;
 systemctl enable /var/www/fw/wiki/fw-wiki-job-runner.service&lt;br /&gt;
&lt;br /&gt;
No need to actually start it yet.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1359</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1359"/>
		<updated>2024-01-12T20:22:11Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Install PHP and modules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
We also want {{C|php-luasandbox}}, which may not have a PHP version attached to the package name, in which case you&#039;ll have to make sure it supports the PHP version currently in use. If not, you can use the standalone Lua binary instead by setting {{C|$wgScribuntoDefaultEngine = &#039;luastandalone&#039;;}} in MediaWiki&#039;s {{C|LocalSettings.php}} configuration file.&lt;br /&gt;
&lt;br /&gt;
 # See if this works first:&lt;br /&gt;
 apt-get install php${php_version}-luasandbox&lt;br /&gt;
 &lt;br /&gt;
 # Otherwise...&lt;br /&gt;
 apt-get install php-luasandbox&lt;br /&gt;
 # Check the package contents to see which PHP versions are supported&lt;br /&gt;
 dpkg -L php-luasandbox&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
	<entry>
		<id>https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1358</id>
		<title>FeministWiki:Server setup</title>
		<link rel="alternate" type="text/html" href="https://feministwiki.org/w/index.php?title=FeministWiki:Server_setup&amp;diff=1358"/>
		<updated>2024-01-12T19:51:30Z</updated>

		<summary type="html">&lt;p&gt;Technician: /* Copy over the live data one more time */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are the steps required to set up a new FeministWiki Debian or Ubuntu server.  The guide assumes that you&#039;re comfortable connecting to a host with SSH and using the shell for various administration tasks, such as using {{C|systemctl}}, editing configuration files, installing packages, setting up SSH keys, and so on.&lt;br /&gt;
&lt;br /&gt;
== Initial setup of the new server ==&lt;br /&gt;
&lt;br /&gt;
This section describes various initialization tasks for the new server that are independent of the old server.&lt;br /&gt;
&lt;br /&gt;
=== Configure reverse DNS ===&lt;br /&gt;
&lt;br /&gt;
In the settings of the VPS host (e.g. Strato AG), you can configure reverse-DNS for the IP address of the server.  Set the FQDN for the IP address to {{C|feministwiki.org}}.  It&#039;s good to do this early since it can take some time to propagate.&lt;br /&gt;
&lt;br /&gt;
=== Make feministwiki.dev point to the new server ===&lt;br /&gt;
&lt;br /&gt;
During setup and testing of the new server, we want to make it accessible under the &#039;&#039;&#039;feministwiki.dev&#039;&#039;&#039; domain.  So change {{C|A}} entries of the {{C|feministwiki.dev}} DNS settings to point to the IP address of the new server.&lt;br /&gt;
&lt;br /&gt;
=== Update &amp;amp; upgrade ===&lt;br /&gt;
&lt;br /&gt;
First of all, let&#039;s make sure the system is up to date.&lt;br /&gt;
&lt;br /&gt;
 apt-get update&lt;br /&gt;
 apt-get upgrade&lt;br /&gt;
 apt-get dist-upgrade&lt;br /&gt;
&lt;br /&gt;
=== Install miscellaneous tools ===&lt;br /&gt;
&lt;br /&gt;
Some of these are needed further down, some are just good to have.&lt;br /&gt;
&lt;br /&gt;
 apt-get install automysqlbackup \&lt;br /&gt;
                 bsdutils \&lt;br /&gt;
                 certbot \&lt;br /&gt;
                 curl \&lt;br /&gt;
                 dnsutils \&lt;br /&gt;
                 emacs-nox \&lt;br /&gt;
                 git \&lt;br /&gt;
                 imagemagick \&lt;br /&gt;
                 ldap-utils \&lt;br /&gt;
                 mg \&lt;br /&gt;
                 moreutils \&lt;br /&gt;
                 net-tools \&lt;br /&gt;
                 netcat-openbsd \&lt;br /&gt;
                 nmap \&lt;br /&gt;
                 rsync \&lt;br /&gt;
                 tree&lt;br /&gt;
&lt;br /&gt;
=== Copy SSH key from old server ===&lt;br /&gt;
&lt;br /&gt;
Copy over {{C|~/.ssh/id_rsa}} and {{C|~/.ssh/id_rsa.pub}} from the old server onto the new one.  Make sure to set the permissions for the private key correctly: {{C|chmod 600 ~/.ssh/id_rsa}}&lt;br /&gt;
&lt;br /&gt;
=== Set up SSH access from the old server ===&lt;br /&gt;
&lt;br /&gt;
Some of the commands further below need SSH access from the old server to the new server, using the {{C|feministwiki.dev}} domain name.  Since we&#039;ve just copied over the public key of the old server, we can enable access from the old server with this simple command:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 cat .ssh/id_rsa.pub &amp;gt;&amp;gt; .ssh/authorized_keys&lt;br /&gt;
&lt;br /&gt;
Further, to make our life easier, we can edit the SSH configuration on the old server so we don&#039;t have to manually specify the custom SSH port number every time.  Add a block like the following into {{C|~/.ssh/config}} on the old server, replacing {{C|&amp;lt;SSH_PORT&amp;gt;}} with the actual port number:&lt;br /&gt;
&lt;br /&gt;
 Host feministwiki.dev&lt;br /&gt;
     Port &amp;lt;SSH_PORT&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tighten security of SSH access ===&lt;br /&gt;
&lt;br /&gt;
Port 22 will get lots of malicious login attempts.  It&#039;s a good idea to change the SSH port, and also to disable password authentication in favor of key-based authentication.  Both can be done by editing {{C|/etc/ssh/sshd_config}}.&lt;br /&gt;
&lt;br /&gt;
Before restarting the SSH service, make sure you&#039;ve actually added your public key (the contents of {{C|~/.ssh/id_rsa.pub}} on your computer) to {{C|/root/.ssh/authorized_keys}} on the server, or you&#039;ll lock yourself out.&lt;br /&gt;
&lt;br /&gt;
=== Set up firewall ===&lt;br /&gt;
&lt;br /&gt;
For now, block everything but SSH.&lt;br /&gt;
&lt;br /&gt;
 apt-get install ufw&lt;br /&gt;
 ufw allow proto tcp to 0.0.0.0/0 port ${SSH_PORT} # Replace with actual port number&lt;br /&gt;
 ufw enable&lt;br /&gt;
&lt;br /&gt;
=== Fetch scripts &amp;amp; config repo ===&lt;br /&gt;
  &lt;br /&gt;
Having copied the {{C|.ssh/id_rsa}} from the old server will give you access to the GitHub FeministWiki repo:&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 mkdir repo&lt;br /&gt;
 git clone git@github.com:FeministWiki/FeministWiki.git repo/fw&lt;br /&gt;
 cp -ai repo/fw/root/* repo/fw/root/.??* .&lt;br /&gt;
 sh repo/fw/decrypt-pwd.sh&lt;br /&gt;
&lt;br /&gt;
The decryption script will prompt you for a password the first time it&#039;s used.  Enter the password stored in {{C|/root/pwd/meta}} on the old server.&lt;br /&gt;
&lt;br /&gt;
=== Enable extra repositories ===&lt;br /&gt;
&lt;br /&gt;
We might want to add some additional package repositories so we can use the latest version of some of the used software.&lt;br /&gt;
&lt;br /&gt;
Backports is always OK to add since the packages don&#039;t get priority over the stable ones:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 # May not be necessary; see if there&#039;s a commented out line in /etc/apt/sources.list that you can activate.&lt;br /&gt;
 echo deb http://deb.debian.org/debian $(lsb_release -sc)-backports main contrib non-free &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 echo deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe &amp;gt; /etc/apt/sources.list.d/backports.list&lt;br /&gt;
&lt;br /&gt;
Usually you want up-to-date versions of Apache2, Nginx, and PHP.  Ondřej provides them:&lt;br /&gt;
&lt;br /&gt;
 # Debian&lt;br /&gt;
 for repo in apache2 nginx-mainline php&lt;br /&gt;
 do&lt;br /&gt;
   curl https://packages.sury.org/$repo/apt.gpg &amp;gt; /etc/apt/trusted.gpg.d/sury-$repo.gpg&lt;br /&gt;
   echo &amp;quot;deb https://packages.sury.org/$repo/ $(lsb_release -sc) main&amp;quot; &amp;gt; /etc/apt/sources.list.d/sury-$repo.list&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 # Ubuntu&lt;br /&gt;
 add-apt-repository ppa:ondrej/apache2&lt;br /&gt;
 add-apt-repository ppa:ondrej/nginx&lt;br /&gt;
 add-apt-repository ppa:ondrej/php&lt;br /&gt;
&lt;br /&gt;
It may be necessary to increase the priority of some repositories if you encounter errors about dependencies that can&#039;t be fulfilled, due to apt-get thinking it has to prioritize older versions of some packages.  This was last observed while trying to install {{C|nginx-extras}}, due to some library dependencies having the &amp;quot;epoch&amp;quot; part of the version number set in the regular Debian repository, but not set in the Sury repository.  The solution is to create a file in {{C|/etc/apt/preferences.d}} such as:&lt;br /&gt;
&lt;br /&gt;
 Package: *&lt;br /&gt;
 Pin: origin packages.sury.org&lt;br /&gt;
 Pin-Priority: 700&lt;br /&gt;
&lt;br /&gt;
Elasticsearch, if you want CirrusSearch for MediaWiki:&lt;br /&gt;
&lt;br /&gt;
 curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor -o /etc/apt/trusted.gpg.d/elasticsearch.gpg&lt;br /&gt;
 # As of January 2024, CirrusSearch only supports Elasticsearch 7.x&lt;br /&gt;
 echo &#039;deb https://artifacts.elastic.co/packages/7.x/apt stable main&#039; &amp;gt; /etc/apt/sources.list.d/elastic.list&lt;br /&gt;
&lt;br /&gt;
=== Create vmail user ===&lt;br /&gt;
&lt;br /&gt;
 groupadd -g 5000 vmail&lt;br /&gt;
 useradd -u 5000 -g vmail -s /usr/sbin/nologin -d /home/vmail -m vmail&lt;br /&gt;
&lt;br /&gt;
=== Install server components ===&lt;br /&gt;
&lt;br /&gt;
Now we can install all the software used for the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 apt-get install&lt;br /&gt;
     apache2 \&lt;br /&gt;
     dovecot-core \&lt;br /&gt;
     dovecot-imapd \&lt;br /&gt;
     dovecot-ldap \&lt;br /&gt;
     dovecot-pop3d \&lt;br /&gt;
     ejabberd \&lt;br /&gt;
     elasticsearch \&lt;br /&gt;
     fail2ban \&lt;br /&gt;
     inspircd \&lt;br /&gt;
     mariadb-server \&lt;br /&gt;
     nginx-extras \&lt;br /&gt;
     opendkim \&lt;br /&gt;
     postfix \&lt;br /&gt;
     postfix-ldap \&lt;br /&gt;
     slapd&lt;br /&gt;
&lt;br /&gt;
If any installation asks you for a password, remember that most passwords are found in {{C|/root/pwd}}.&lt;br /&gt;
&lt;br /&gt;
Example for installing ejabberd from backports instead:&lt;br /&gt;
&lt;br /&gt;
 apt-get install ejabberd/$(lsb_release -sc)-backports # e.g. ejabberd/bookworm-backports&lt;br /&gt;
&lt;br /&gt;
=== Install PHP and modules ===&lt;br /&gt;
&lt;br /&gt;
This should really be part of the last section, but due to the sheer number of PHP modules we want to install, it&#039;s in its own section:&lt;br /&gt;
&lt;br /&gt;
 php_version=8.1 # or whatever version we&#039;re on&lt;br /&gt;
 &lt;br /&gt;
 apt-get install php${php_version} \&lt;br /&gt;
                 php${php_version}-apcu \&lt;br /&gt;
                 php${php_version}-bcmath \&lt;br /&gt;
                 php${php_version}-cli \&lt;br /&gt;
                 php${php_version}-curl \&lt;br /&gt;
                 php${php_version}-fpm \&lt;br /&gt;
                 php${php_version}-gd \&lt;br /&gt;
                 php${php_version}-gmp \&lt;br /&gt;
                 php${php_version}-imagick \&lt;br /&gt;
                 php${php_version}-intl \&lt;br /&gt;
                 php${php_version}-ldap \&lt;br /&gt;
                 php${php_version}-mbstring \&lt;br /&gt;
                 php${php_version}-mysql \&lt;br /&gt;
                 php${php_version}-opcache \&lt;br /&gt;
                 php${php_version}-readline \&lt;br /&gt;
                 php${php_version}-xml \&lt;br /&gt;
                 php${php_version}-zip&lt;br /&gt;
&lt;br /&gt;
=== Copy over certificates ===&lt;br /&gt;
&lt;br /&gt;
Copy over the certs from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/fw-certs feministwiki.dev:/etc/fw-certs&lt;br /&gt;
&lt;br /&gt;
The {{C|/etc/fw-certs}} directory and its contents should be owned by the group {{C|ssl-cert}}.  Make sure this is the case on the new server after running the command above, since the group ID might be different on the new server.  If the group doesn&#039;t exist at all, just create it.&lt;br /&gt;
&lt;br /&gt;
Further, files in that directory which contain the private key ({{C|privkey.pem}} and {{C|bundle.pem}}) should only be readable by group members.  That is, their permission mode should be 640, displayed as {{C|-rw-r-----}} in the output of {{C|ls -l}}.  Make sure this really the case.&lt;br /&gt;
&lt;br /&gt;
Then, to allow certain services to read those files containing the private key, add them to the {{C|ssl-cert}} group:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 adduser ejabberd ssl-cert&lt;br /&gt;
 adduser irc ssl-cert&lt;br /&gt;
&lt;br /&gt;
Also copy over the certificates stored directly in {{C|/etc/letsencrypt}}:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -avz /etc/letsencrypt/{archive,live} feministwiki.dev:/etc/letsencrypt&lt;br /&gt;
&lt;br /&gt;
=== Put config files in place ===&lt;br /&gt;
&lt;br /&gt;
The principle is simple: take all the config files from {{C|/root/repo/etc}} and put them where they belong in {{C|/etc}}.  However, since a new server might mean much newer software, it&#039;s possible that some config files aren&#039;t compatible anymore, or that some new sensible defaults might be overwritten by the old config.  Sadly, figuring out these incompatibilities is a manual process: compare the new default config with the old default config, and/or with our own config saved in the repo, to figure out what our new config files should look like.&lt;br /&gt;
&lt;br /&gt;
There&#039;s a number of things important to remember:&lt;br /&gt;
&lt;br /&gt;
* Don&#039;t forget to revert the redactions of sensitive information.  Search files for {{C|[REDACTED]}}.&lt;br /&gt;
* After copying {{C|/etc/aliases}}, run {{C|newaliases}} to create the alias database file.&lt;br /&gt;
* After copying Postfix configuration, run {{C|postmap /etc/postfix/sender-access}} and {{C|postalias /etc/postfix/virtual-aliases}}.&lt;br /&gt;
* Make sure the executable bit is set on all {{C|cron}} scripts, {{C|/etc/rc.local}}, and scripts in {{C|/etc/letsencrypt/renewal-hooks}}.&lt;br /&gt;
&lt;br /&gt;
=== Apache modules and configuration ===&lt;br /&gt;
&lt;br /&gt;
Enable PHP FPM and other Apache modules:&lt;br /&gt;
&lt;br /&gt;
 a2enmod expires headers proxy_fcgi&lt;br /&gt;
 a2enconf php${php_version}-fpm&lt;br /&gt;
&lt;br /&gt;
=== OpenLDAP configuration database ===&lt;br /&gt;
&lt;br /&gt;
First of all, check if there are important changes in the base configuration of slapd.  For this, we can copy the old configuration into some directory on the new server and run a recursive diff:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 rsync -az /etc/ldap/slapd.d/ feministwiki.dev:/tmp/slapd.d&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 diff -ru --color=always /tmp/slapd.d /etc/ldap/slapd.d | less -R&lt;br /&gt;
&lt;br /&gt;
There are going to be a number of changes that are expected.  Namely:&lt;br /&gt;
&lt;br /&gt;
# CRCs, UIDs, timestamps, and other such auto-generated fields&lt;br /&gt;
# FeministWiki-specific things that only exists in the old configuration&lt;br /&gt;
&lt;br /&gt;
If these are the &#039;&#039;&#039;only&#039;&#039;&#039; differences you can see, then it should be safety to completely override the config on the new server with the old one, using the instructions in the following section.&lt;br /&gt;
&lt;br /&gt;
Otherwise, skip to the section after that and recreate the FeministWiki-specific configuration from scratch.&lt;br /&gt;
&lt;br /&gt;
==== Complete copying of old configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;next&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stop the LDAP server and delete the configuration database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Commands to run on the NEW (fresh) server:&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm -r /etc/ldap/slapd.d/*&lt;br /&gt;
&lt;br /&gt;
Then copy over the configuration database, by running the following commands from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 0 | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&lt;br /&gt;
&lt;br /&gt;
==== Recreation of FeministWiki configuration ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: This is an &#039;&#039;&#039;alternative&#039;&#039;&#039; method to that described in the &#039;&#039;&#039;previous&#039;&#039;&#039; section. See above for which one to choose.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
First run {{C|dpkg-reconfigure slapd}} to fill in some basic information such as the domain name and admin password.  You can reuse the old admin password found in {{C|/root/pwd/ldap}}.&lt;br /&gt;
&lt;br /&gt;
Then, running the following sequence of commands, taken from [[FeministWiki:LDAP Schema]], should do the rest:&lt;br /&gt;
&lt;br /&gt;
 # Create fwMember object class&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=feministwiki,cn=schema,cn=config&lt;br /&gt;
 objectClass: olcSchemaConfig&lt;br /&gt;
 cn: feministwiki&lt;br /&gt;
 olcAttributeTypes: {0}( 1.3.6.1.4.1.42.2.27.99.1.1&lt;br /&gt;
    NAME &#039;fwRecoveryMail&#039;&lt;br /&gt;
    DESC &#039;FeministWiki password recovery mail&#039;&lt;br /&gt;
    EQUALITY caseIgnoreMatch&lt;br /&gt;
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )&lt;br /&gt;
 olcObjectClasses: {1}( 1.3.6.1.4.1.42.2.27.99.2.1&lt;br /&gt;
    NAME &#039;fwMember&#039;&lt;br /&gt;
    DESC &#039;FeministWiki member&#039;&lt;br /&gt;
    SUP inetOrgPerson&lt;br /&gt;
    STRUCTURAL&lt;br /&gt;
    MAY ( fwRecoveryMail ) )&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set attribute permissions&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcAccess&lt;br /&gt;
 olcAccess: {2}to attrs=sn,mail by self write&lt;br /&gt;
 olcAccess: {3}to attrs=fwRecoveryMail by self write by dn.exact=&amp;quot;cn=readonly,dc=feministwiki,dc=org&amp;quot; search&lt;br /&gt;
 olcAccess: {4}to attrs=manager by self read&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the ppolicy dynamic module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: ppolicy&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Add the ppolicy overlay with olcPPolicyHashCleartext set to TRUE&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcPPolicyConfig&lt;br /&gt;
 olcOverlay: ppolicy&lt;br /&gt;
 olcPPolicyHashCleartext: TRUE&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Set the default password policy&lt;br /&gt;
 # The policy object referenced here doesn&#039;t exist yet,&lt;br /&gt;
 # but will exist once we copy over the main database.&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay={0}ppolicy,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcPPolicyDefault&lt;br /&gt;
 olcPPolicyDefault: cn=default,ou=pwdPolicies,dc=feministwiki,dc=org&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Load the lastbind module&lt;br /&gt;
 ldapmodify -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: cn=module{0},cn=config&lt;br /&gt;
 changetype: modify&lt;br /&gt;
 add: olcModuleLoad&lt;br /&gt;
 olcModuleLoad: lastbind&lt;br /&gt;
 EOF&lt;br /&gt;
 &lt;br /&gt;
 # Enable the lastbind overlay&lt;br /&gt;
 ldapadd -Y external -H ldapi:// &amp;lt;&amp;lt;EOF&lt;br /&gt;
 dn: olcOverlay=lastbind,olcDatabase={1}mdb,cn=config&lt;br /&gt;
 objectClass: olcLastBindConfig&lt;br /&gt;
 olcOverlay: lastbind&lt;br /&gt;
 olcLastBindPrecision: 60&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
==== Breaking changes in OpenLDAP ====&lt;br /&gt;
&lt;br /&gt;
There might be incompatible changes between OpenLDAP (aka {{C|slapd}}) versions which require manual editing of the {{C|slapcat}} output before it&#039;s read in on the new server with {{C|slapadd}}.  Following are two examples of this.&lt;br /&gt;
&lt;br /&gt;
These particular issues won&#039;t apply anymore when you&#039;re reading this guide, since they are one-time issues related to migrating to a newer OpenLDAP version, but they serve as good examples.  (Also, no such clear explanation of the first problem seems to be found anywhere on the web, so maybe someone who searches the related error message below will come upon this guide and be happy!)&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 1 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating from OpenLDAP 2.4.42 or earlier, to 2.4.43 or later.&lt;br /&gt;
&lt;br /&gt;
The ppolicy overlay gained a new attribute in OpenLDAP version 2.4.43, so if you simply run the command above which copies over the configuration database onto the new server, it will produce the following error message:&lt;br /&gt;
&lt;br /&gt;
 User Schema load failed for attribute &amp;quot;pwdMaxRecordedFailure&amp;quot;. Error code 17: attribute type undefined&lt;br /&gt;
&lt;br /&gt;
The solution is as follows:&lt;br /&gt;
&lt;br /&gt;
# On the new server, open {{C|/etc/ldap/schema/ppolicy.ldif}} and search for {{C|pwdMaxRecordedFailure}}.  You will see an {{C|olcAttributeTypes: ...}} entry that defines it.  Also, it&#039;s listed in the {{C|MAY}} attributes block of the {{C|olcObjectClasses: ...}} entry that defines the {{C|pwdPolicy}} object class.&lt;br /&gt;
# On the old server, save the output of {{C|slapcat -n 0}} to a file, open it in a text editor, and search for the block where the {{C|ppolicy}} schema is defined.  It should start with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}} (the {{C|&amp;lt;nowiki&amp;gt;{4}&amp;lt;/nowiki&amp;gt;}} part might contain a different integer, that&#039;s OK).  There, note that the {{C|olcAttributeTypes: ...}} entry for {{C|pwdMaxRecordedFailure}} is missing, and also it&#039;s not listed in the {{C|MAY}} list of the {{C|pwdPolicy}} object class definition.  Copy over the attribute type definition from the {{C|ppolicy.ldif}} file on the new server, and amend the {{C|MAY}} list to include it.&lt;br /&gt;
&lt;br /&gt;
===== OpenLDAP Migration: Example Problem 2 =====&lt;br /&gt;
&lt;br /&gt;
This problem occurs when migrating to OpenLDAP 2.5, and although the change is bigger, the fix is easier.  The issue is actually documented in the OpenLDAP 2.5 Administrator&#039;s Guide, Appendix B.2:&lt;br /&gt;
&lt;br /&gt;
https://www.openldap.org/doc/admin25/appendix-upgrading.html&lt;br /&gt;
&lt;br /&gt;
The second paragraph tells us what to do:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;In OpenLDAP 2.4 the slapo-ppolicy(5) overlay relied on a separate schema file to be included for it to function. This schema is now implemented internally in the slapo-ppolicy module. When upgrading slapd.conf(5) deployments the include statement for the schema must be removed. For slapd-config(5) deployments, the config database must be exported via slapcat and the old ppolicy schema removed from the export. The resulting config database can then be imported.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In simpler terms:&lt;br /&gt;
&lt;br /&gt;
# Save the output of {{C|slapcat -n 0}} from the old server in a file:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;slapcat -n 0 &amp;gt; slapcat.n0.out&amp;lt;/pre&amp;gt;&lt;br /&gt;
# Open the file in a text editor and delete the block starting with the line {{C|&amp;lt;nowiki&amp;gt;dn: cn={4}ppolicy,cn=schema,cn=config&amp;lt;/nowiki&amp;gt;}}, up to the next empty line (before the next block starting with a {{C|dn: ...}} line), and save the file.&lt;br /&gt;
# Feed the file to {{C|slapadd -n 1}} on the new server:&lt;br /&gt;
#: &amp;lt;pre&amp;gt;cat slapcat.n0.out | ssh feministwiki.dev &#039;sudo -u openldap slapadd -n 0 -F /etc/ldap/slapd.d&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copying over live data ==&lt;br /&gt;
&lt;br /&gt;
We want to make a first run of this copy process purely for testing purposes.  Note that although some of the steps described in this section take a long time to finish, they can be done in parallel.&lt;br /&gt;
&lt;br /&gt;
=== LDAP database ===&lt;br /&gt;
&lt;br /&gt;
Make sure slapd is not running and delete the existing database &#039;&#039;&#039;on the new server (careful!)&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server!&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
 rm /var/lib/ldap/data.mdb&lt;br /&gt;
&lt;br /&gt;
Then copy over the database by running the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 # Run on old server&lt;br /&gt;
 slapcat -n 1 | zstd | ssh feministwiki.dev &#039;zstd -d | sudo -u openldap slapadd -n 1&#039;&lt;br /&gt;
&lt;br /&gt;
Start slapd again in the new server afterwards:&lt;br /&gt;
&lt;br /&gt;
 # Run on new server&lt;br /&gt;
 systemctl start slapd&lt;br /&gt;
&lt;br /&gt;
=== Contents of /var/www ===&lt;br /&gt;
&lt;br /&gt;
This is very simple but takes a lot of time to finish.  &#039;&#039;&#039;Run it from the old server:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 rsync -azP --delete /var/www/ feministwiki.dev:/var/www&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/var/www/}} is important; if not provided, it will copy the directory to {{C|/var/www/www}} on the new server.&lt;br /&gt;
&lt;br /&gt;
=== SQL databases ===&lt;br /&gt;
&lt;br /&gt;
Run the following command from the old server:&lt;br /&gt;
&lt;br /&gt;
 mariadb-dump -u root -p&amp;quot;$(cat /root/pwd/mariadb)&amp;quot; \&lt;br /&gt;
   --add-drop-database \&lt;br /&gt;
   --databases feministblogs \&lt;br /&gt;
               feministfiles \&lt;br /&gt;
               feministforum \&lt;br /&gt;
               feministmail \&lt;br /&gt;
               feministwiki \&lt;br /&gt;
               feministwiki_de \&lt;br /&gt;
               feministwiki_es \&lt;br /&gt;
               feministwiki_fr \&lt;br /&gt;
               feministwiki_it \&lt;br /&gt;
               feministwiki_pt \&lt;br /&gt;
               fff \&lt;br /&gt;
   | zstd | ssh feministwiki.dev &#039;zstd -d | /root/bin/sql&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the {{C|show databases;}} command in the SQL console to make sure that the list of databases is complete.  Unfortunately they have to be listed manually, because using the {{C|--all-databases}} option includes system databases that we don&#039;t want to copy.&lt;br /&gt;
&lt;br /&gt;
=== Emails ===&lt;br /&gt;
&lt;br /&gt;
This is a simple one.  Run this command from the old server:&lt;br /&gt;
&lt;br /&gt;
 rsync -az --delete /home/vmail/ feministwiki.dev:/home/vmail&lt;br /&gt;
&lt;br /&gt;
Note that the trailing slash in {{C|/home/vmail/}} is important.&lt;br /&gt;
&lt;br /&gt;
=== Elasticsearch ===&lt;br /&gt;
&lt;br /&gt;
Temporarily stop Elasticsearch on the old server and copy over the data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 rsync -az --delete /var/lib/elasticsearch/ feministwiki.dev:/var/lib/elasticsearch&lt;br /&gt;
 systemctl start elasticsearch&lt;br /&gt;
&lt;br /&gt;
=== Mailman data ===&lt;br /&gt;
&lt;br /&gt;
GNU Mailman uses a filesystem-based &amp;quot;database&amp;quot; so we can transfer over its data as follows; run this from the old server:&lt;br /&gt;
&lt;br /&gt;
 cd /var/lib/mailman&lt;br /&gt;
 rsync -az --delete archives data lists feministwiki.dev:/var/lib/mailman&lt;br /&gt;
&lt;br /&gt;
And then this on the new server:&lt;br /&gt;
&lt;br /&gt;
 check_perms -f&lt;br /&gt;
&lt;br /&gt;
The {{C|check_perms}} command, which is part of GNU Mailman, will take care of fixing file ownership and permissions.&lt;br /&gt;
&lt;br /&gt;
== Recreate SQL users ==&lt;br /&gt;
&lt;br /&gt;
If the versions of MariaDB on the old and new server are compatible enough, you might be able to dump the {{C|mysql.user}} table and import it on the new server, but it&#039;s safer to recreate the users from scratch.  To do so, run this on the new server:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 create user &#039;feministblogs&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministblogs)&#039;;&lt;br /&gt;
 create user &#039;feministfiles&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministfiles)&#039;;&lt;br /&gt;
 create user &#039;feministforum&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministforum)&#039;;&lt;br /&gt;
 create user &#039;feministmail&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministmail)&#039;;&lt;br /&gt;
 create user &#039;feministwiki&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-feministwiki)&#039;;&lt;br /&gt;
 create user &#039;fff&#039;@localhost identified by &#039;$(cat ~/pwd/mariadb-fff)&#039;;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
Now grant them access to their corresponding databases.  Remember that this has to be done &#039;&#039;&#039;after&#039;&#039;&#039; the databases have been copied over:&lt;br /&gt;
&lt;br /&gt;
 /root/bin/sql &amp;lt;&amp;lt; EOF&lt;br /&gt;
 grant all on feministblogs.* to feministblogs@localhost;&lt;br /&gt;
 grant all on feministfiles.* to feministfiles@localhost;&lt;br /&gt;
 grant all on feministforum.* to feministforum@localhost;&lt;br /&gt;
 grant all on feministmail.* to feministmail@localhost;&lt;br /&gt;
 grant all on feministwiki.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_de.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_es.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_fr.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_it.* to feministwiki@localhost;&lt;br /&gt;
 grant all on feministwiki_pt.* to feministwiki@localhost;&lt;br /&gt;
 grant all on fff.* to fff@localhost;&lt;br /&gt;
 EOF&lt;br /&gt;
&lt;br /&gt;
== Test ==&lt;br /&gt;
&lt;br /&gt;
It&#039;s important to test the new server to make sure everything works well!&lt;br /&gt;
&lt;br /&gt;
=== Reboot ===&lt;br /&gt;
&lt;br /&gt;
We could restart a lot of services manually to ensure they&#039;ve read their new config, but it&#039;s easiest to just reboot.  (The new server, obviously.)&lt;br /&gt;
&lt;br /&gt;
=== Open ports ===&lt;br /&gt;
&lt;br /&gt;
We need to open all the ports used by the various FeministWiki services:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Test! ===&lt;br /&gt;
&lt;br /&gt;
At this point you should test everything using the feministwiki.dev domain name.&lt;br /&gt;
&lt;br /&gt;
Some things may not work correctly because they&#039;re hard-coded to work as &amp;quot;feministwiki.org&amp;quot; and not under the &amp;quot;feministwiki.dev&amp;quot; name.  Here&#039;s a list of known issues related to this:&lt;br /&gt;
&lt;br /&gt;
* WordPress normally redirects clients to the canonical address of a blog if it&#039;s visited through an alternative domain name.  This means we get redirected back to the old server if we try to visit {{C|blogs.feministwiki.dev}}.  To work around this, we use {{C|RequestHeader set Host}} in the Apache2 site configuration, which fools WordPress into believing it&#039;s being accessed through the canonical domain name.  Still, the HTML/CSS/JS sent back to the browser refers to some resources on the {{C|.org}} domain, which then fail to load due to CORS violation.&lt;br /&gt;
&lt;br /&gt;
If you want to be extra thorough, you can edit your {{C|/etc/hosts}} file to make {{C|feministwiki.org}}, various {{C|*.feministwiki.org}} subdomains, and maybe even other aliases (such as {{C|fem.wiki}}) point to the new server, and then test the few stubborn services that won&#039;t otherwise play nice.&lt;br /&gt;
&lt;br /&gt;
=== Deactivate again ===&lt;br /&gt;
&lt;br /&gt;
After we&#039;re done testing, we can &amp;quot;deactivate&amp;quot; the new server again to prepare it for the final switch-over:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
== Finishing up ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Now, all services on the old server should be stopped, because we will begin the final transfer of live data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Stop services on the old server ===&lt;br /&gt;
&lt;br /&gt;
Stop all the services that interface with users and/or are responsible for modifying live data:&lt;br /&gt;
&lt;br /&gt;
 systemctl stop apache2&lt;br /&gt;
 systemctl stop dovecot&lt;br /&gt;
 systemctl stop ejabberd&lt;br /&gt;
 systemctl stop elasticsearch&lt;br /&gt;
 systemctl stop inspircd&lt;br /&gt;
 systemctl stop nginx&lt;br /&gt;
 systemctl stop postfix&lt;br /&gt;
 systemctl stop slapd&lt;br /&gt;
&lt;br /&gt;
Close all the relevant ports just to be double-sure:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw delete allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Copy over the live data one more time ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Simply repeat the whole section &#039;&#039;Copying over live data&#039;&#039;.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The techniques and commands described above in the section &#039;&#039;Copying over live data&#039;&#039; are &#039;&#039;idempotent&#039;&#039;, meaning you can simply repeat them and they will make sure that the new copy of the live data is fresh and doesn&#039;t leave any outdated data on the new server.  For instance, the {{C|--delete}} argument to the {{C|rsync}} command and the {{C|--add-drop-database}} argument to the {{C|mariadb-dump}} command help to make sure of this.&lt;br /&gt;
&lt;br /&gt;
So just repeat the steps from that section exactly one more time.&lt;br /&gt;
&lt;br /&gt;
=== Reboot the new server ===&lt;br /&gt;
&lt;br /&gt;
At this point we can reboot the new server again, to make sure all services are properly restarted.&lt;br /&gt;
&lt;br /&gt;
=== Open ports on the new server ===&lt;br /&gt;
&lt;br /&gt;
Now we can open the ports again on the new server:&lt;br /&gt;
&lt;br /&gt;
 for port in 25 80 443 465 587 993 995 5222 5223 5269 5270 5443 6697 7777&lt;br /&gt;
 do ufw allow proto tcp to 0.0.0.0/0 port $port&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
=== Update DNS entries ===&lt;br /&gt;
&lt;br /&gt;
You have to change the configuration of the following domains:&lt;br /&gt;
&lt;br /&gt;
* feministwiki.org&lt;br /&gt;
* feministwiki.net&lt;br /&gt;
* feministwiki.de&lt;br /&gt;
* fem.wiki&lt;br /&gt;
* feminism.wiki&lt;br /&gt;
* feminist.wiki&lt;br /&gt;
* fffrauen.de&lt;br /&gt;
&lt;br /&gt;
==== feministwiki.org ====&lt;br /&gt;
&lt;br /&gt;
You only have to change three DNS entries, since most of the subdomains work via CNAME entries:&lt;br /&gt;
&lt;br /&gt;
* The main {{C|A}} entry for {{C|@}} (self-reference i.e. feministwiki.org)&lt;br /&gt;
* The {{C|A}} entry for {{C|smtp}} since this is not allowed to be a CNAME&lt;br /&gt;
* The {{C|A}} entry for {{C|xmpp}} since this is not allowed to be a CNAME&lt;br /&gt;
&lt;br /&gt;
==== Other domains ====&lt;br /&gt;
&lt;br /&gt;
For these, you only have to change the main {{C|A}} entry, since they don&#039;t use SMTP or XMPP.&lt;br /&gt;
&lt;br /&gt;
=== Configure LetsEncrypt ===&lt;br /&gt;
&lt;br /&gt;
Since we changed the DNS settings, we can now set up certbot:&lt;br /&gt;
&lt;br /&gt;
 certbot register -n --agree-tos -m technician@feministwiki.org&lt;br /&gt;
 letsencrypt-refresh&lt;br /&gt;
&lt;br /&gt;
=== Finishing up ===&lt;br /&gt;
&lt;br /&gt;
At this point, everything should be functional.  If not, it&#039;s time for some debugging!&lt;/div&gt;</summary>
		<author><name>Technician</name></author>
	</entry>
</feed>