<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.csclub.uwaterloo.ca/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=A268wang</id>
	<title>CSCWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.csclub.uwaterloo.ca/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=A268wang"/>
	<link rel="alternate" type="text/html" href="https://wiki.csclub.uwaterloo.ca/Special:Contributions/A268wang"/>
	<updated>2026-04-23T20:22:39Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://wiki.csclub.uwaterloo.ca/index.php?title=Mirror&amp;diff=4889</id>
		<title>Mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.csclub.uwaterloo.ca/index.php?title=Mirror&amp;diff=4889"/>
		<updated>2022-10-04T03:19:25Z</updated>

		<summary type="html">&lt;p&gt;A268wang: Update section for merlin&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [https://csclub.uwaterloo.ca Computer Science Club] runs a public mirror ([http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca]) on [[Machine_List#potassium-benzoate|potassium-benzoate]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We are listed on the ResNet &amp;amp;quot;don&#039;t count&amp;amp;quot; list, so downloading from our mirror will not count against one&#039;s ResNet quota.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Software Mirrored ==&lt;br /&gt;
&lt;br /&gt;
A list of current archives (and their respective disk usage) is listed on our mirror&#039;s homepage at [http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
=== Mirroring Requests ===&lt;br /&gt;
&lt;br /&gt;
Requests to mirror a particular distribution or archive should be made to [mailto:syscom@csclub.uwaterloo.ca syscom@csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
== Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Syncing ===&lt;br /&gt;
&lt;br /&gt;
==== Storage ====&lt;br /&gt;
&lt;br /&gt;
All of our projects are stored on an 8x18TB disk raidz2 array (cscmirror0). There is an additional drive acting as a hot-spare.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/mirror/root/.cscmirror0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each project is given a filesystem the pool. Symlinks are created &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt; to point to the correct pool and file system.&lt;br /&gt;
&lt;br /&gt;
==== Merlin ====&lt;br /&gt;
Project synchronization is done by &amp;quot;merlin&amp;quot; which is a Go rewrite of the Python script &amp;quot;merlin&amp;quot; originally written by a2brenna.&lt;br /&gt;
&lt;br /&gt;
The program is stored in &amp;lt;code&amp;gt;~mirror/merlin&amp;lt;/code&amp;gt; and is managed by the systemd unit &amp;lt;code&amp;gt;merlin-go.service&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The config file &amp;lt;code&amp;gt;merlin-config.ini&amp;lt;/code&amp;gt; contains the list of repositories along with their configurations.&lt;br /&gt;
&lt;br /&gt;
To view the sync status, execute &amp;lt;code&amp;gt;~mirror/merlin/cmd/arthur/arthur status&amp;lt;/code&amp;gt;. To force the sync of a project, execute &amp;lt;code&amp;gt;~mirror/merlin/cmd/arthur/arthur sync:PROJECT_NAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Remark&#039;&#039;&#039;: For syncing Debian repositories we were [https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1020998 requested] to use ftpsync which has configs in &amp;lt;code&amp;gt;~mirror/ftpsync&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Push Sync =====&lt;br /&gt;
&lt;br /&gt;
Some projects support push syncing via SSH.&lt;br /&gt;
&lt;br /&gt;
We are running a special SSHD instance on mirror.csclub.uwaterloo.ca:22. This instance has been locked down, with the following settings:&lt;br /&gt;
&lt;br /&gt;
* Only SSH key authentication&lt;br /&gt;
* Only users of the &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; group (except &amp;lt;code&amp;gt;mirror&amp;lt;/code&amp;gt;) are allowed to connect&lt;br /&gt;
* X11 Forwarding, TCP Forwarding, Agent Forwarding, User RC and TTY are disabled&lt;br /&gt;
* Users are chrooted to &amp;lt;code&amp;gt;/mirror/merlin&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most projects will connect using the &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; user. The SSH authorized keys file is located at &amp;lt;code&amp;gt;/home/push/.ssh/authorized_keys&amp;lt;/code&amp;gt;. An example entry is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
restrict,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command=&amp;quot;arthur sync:ubuntu &amp;gt;/dev/null 2&amp;gt;/dev/null &amp;lt;/dev/null &amp;amp;&amp;quot;,from=&amp;quot;XXX.XXX.XXX.XXX&amp;quot; ssh-rsa ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sync Scripts ====&lt;br /&gt;
&lt;br /&gt;
Our collection of synchronization scripts are located in &amp;lt;code&amp;gt;~mirror/bin&amp;lt;/code&amp;gt;. They currently include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-apache&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-debian&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-debian-cd&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-gentoo&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-ssh&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-standard&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of these scripts take the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;local_dir rsync_host rsync_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HTTP(s) ===&lt;br /&gt;
&lt;br /&gt;
We use [https://nginx.org nginx] as our webserver.&lt;br /&gt;
&lt;br /&gt;
==== Index ====&lt;br /&gt;
&lt;br /&gt;
An index of the archives we mirror is available at [http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
As of Winter 2010, it is now generated by a Python script in &amp;lt;code&amp;gt;~mirror/mirror-index&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;~mirror/mirror-index/make-index&amp;lt;/code&amp;gt; is scheduled in &amp;lt;code&amp;gt;/etc/cron.d/csc-mirror&amp;lt;/code&amp;gt; to be run hourly. The script can be run manually when needed (for example, when the archive list is updated) by running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sudo -u mirror /home/mirror/mirror-index/make-index.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script will iterate all folders in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;, identify the size of the project using `zfs get -H -o value used $dataset`, where $dataset is calculated from the symlink in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;. The size of all folders is added together to calculate the total folder size (the total size includes hidden projects).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;make-index.py&amp;lt;/code&amp;gt; is configured by means of a [https://yaml.org YAML] file, &amp;lt;code&amp;gt;config.yaml&amp;lt;/code&amp;gt;, in the same directory. Its format is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;yaml&amp;quot;&amp;gt;docroot: /mirror/root&lt;br /&gt;
output: /mirror/root/index.html&lt;br /&gt;
&lt;br /&gt;
exclude:&lt;br /&gt;
   - include&lt;br /&gt;
   - lost+found&lt;br /&gt;
   - pub&lt;br /&gt;
# (...)&lt;br /&gt;
&lt;br /&gt;
directories:&lt;br /&gt;
  apache:&lt;br /&gt;
    site: apache.org&lt;br /&gt;
    url: http://www.apache.org/&lt;br /&gt;
&lt;br /&gt;
  archlinux:&lt;br /&gt;
    site: archlinux.org&lt;br /&gt;
    url: http://www.archlinux.org/&lt;br /&gt;
&lt;br /&gt;
# (...)&amp;lt;/pre&amp;gt;&lt;br /&gt;
The docroot is the directory which is to be scanned; this will probably always be the mirror root from which Apache serves. This is here so that it&#039;s easy to find and alter. For instance, we could change &amp;lt;code&amp;gt;--human-readable&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;--si&amp;lt;/code&amp;gt; if we ever decided that, like hard disk manufacturers, we want sizes to appear larger than they are. &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; defines the file to which the generated index will be written.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;exclude&amp;lt;/code&amp;gt; specifies the list of directories which will not be included in the generated index page (since, by default, all folders are included in the generated index page).&lt;br /&gt;
&lt;br /&gt;
Finally, &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt; specifies the information of directories. All directories are listed by default, whether or not they appear in this list - only those under &amp;lt;code&amp;gt;exclude&amp;lt;/code&amp;gt; are ignored. The format is fairly straightforward: simply name the directory and provide a site (the display name in the &amp;amp;quot;Project Site&amp;amp;quot; column) and URL. One caveat here is that YAML does not allow tabs for whitespace. Indent with two spaces to remain consistent with the existing file format, please. Also note that the directory name is case-sensitive, as is always the case on Unix.&lt;br /&gt;
&lt;br /&gt;
Finally, the HTML index file is generated from &amp;lt;code&amp;gt;index.mako&amp;lt;/code&amp;gt;, a Mako template (which is mostly HTML anyhow). If you really can&#039;t figure out how it works, look up the Mako documentation.&lt;br /&gt;
&lt;br /&gt;
=== FTP ===&lt;br /&gt;
&lt;br /&gt;
We use [http://www.proftpd.org/ proftpd] (standalone daemon) as our FTP server.&lt;br /&gt;
&lt;br /&gt;
To increase performance, we disable DNS lookups in &amp;lt;code&amp;gt;proftpd.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;UseReverseDNS           off&lt;br /&gt;
IdentLookups            off&amp;lt;/pre&amp;gt;&lt;br /&gt;
We also limit the amount of CPU/memory resources used (e.g. to minimize [https://en.wikipedia.org/wiki/Globbing Globbing] resources):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;RLimitCPU               session 10&lt;br /&gt;
RLimitMemory            session 4096K&amp;lt;/pre&amp;gt;&lt;br /&gt;
We allow a maximum of 500 concurrent FTP sessions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;MaxInstances            500&lt;br /&gt;
MaxClients              500&amp;lt;/pre&amp;gt;&lt;br /&gt;
The contents of &amp;lt;code&amp;gt;/mirror/root/include/motd.msg&amp;lt;/code&amp;gt; are displayed when a user connects.&lt;br /&gt;
&lt;br /&gt;
=== rsync ===&lt;br /&gt;
&lt;br /&gt;
We use &amp;lt;code&amp;gt;rsyncd&amp;lt;/code&amp;gt; (standalone daemon).&lt;br /&gt;
&lt;br /&gt;
We disable compression and checksumming in &amp;lt;code&amp;gt;rsyncd.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dont compress = *&lt;br /&gt;
refuse options = c delete&amp;lt;/pre&amp;gt;&lt;br /&gt;
The contents of &amp;lt;code&amp;gt;/mirror/root/include/motd.msg&amp;lt;/code&amp;gt; are displayed when a user connects.&lt;br /&gt;
&lt;br /&gt;
== Mirror Administration ==&lt;br /&gt;
&lt;br /&gt;
=== Adding a new project ===&lt;br /&gt;
&lt;br /&gt;
# Find the instructions for mirroring the project. Ideally, try to sync directly from the project’s source repository.&lt;br /&gt;
#* Note that some projects provide sync scripts, however we generally won’t use them. We will instead use our custom ones.&lt;br /&gt;
# Create a zfs filesystem to store the project in:&lt;br /&gt;
#*&amp;lt;code&amp;gt;zfs create cscmirror0/$PROJECT_NAME&amp;lt;/code&amp;gt;&lt;br /&gt;
# Change the folder ownership&lt;br /&gt;
#*&amp;lt;code&amp;gt;chown mirror:mirror /mirror/root/.cscmirror0/$PROJECT_NAME&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create the symlink in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;&lt;br /&gt;
#*&amp;lt;code&amp;gt;ln -s .cscmirror0/$PROJECT_NAME $PROJECT_NAME&amp;lt;/code&amp;gt; (&#039;&#039;&#039;NOTE&#039;&#039;&#039;: The symlink must be relative to the &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt; directory. If it isn’t, the symlinks will not work when chrooted)&lt;br /&gt;
# Repeat the above steps on mirror-phys. &amp;lt;code&amp;gt;sudo ssh mirror-dc&amp;lt;/code&amp;gt; on potassium-benzoate [&#039;&#039;&#039;NOTE: This machine is currently unavailable]&#039;&#039;&#039;&lt;br /&gt;
# Configure the project in merlin (&amp;lt;code&amp;gt;~mirror/merlin/merlin.py&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Select the appropriate sync script (typically &amp;lt;code&amp;gt;csc-sync-standard&amp;lt;/code&amp;gt;) and supply the appropriate parameters&lt;br /&gt;
# Restart merlin: &amp;lt;code&amp;gt;systemctl restart merlin&amp;lt;/code&amp;gt;&lt;br /&gt;
#* This will kick off the initial sync&lt;br /&gt;
#* Check &amp;lt;code&amp;gt;~mirror/merlin/logs/$PROJECT_NAME&amp;lt;/code&amp;gt; for errors, &amp;lt;code&amp;gt;~mirror/merlin/logs/transfer.log&amp;lt;/code&amp;gt; for transfer progress&lt;br /&gt;
# Configure the project in zfssync.yml (&amp;lt;code&amp;gt;~mirror/merlin/zfssync.yml&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Update the mirror index configuration (&amp;lt;code&amp;gt;~mirror/mirror-index/config.yaml&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Add the project to rsync (&amp;lt;code&amp;gt;/etc/rsyncd.conf&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Restart rsync with &amp;lt;code&amp;gt;systemctl restart rsync&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If push mirroring is available/required, see [[#Push_Sync|Push Sync]].&lt;br /&gt;
&lt;br /&gt;
=== Secondary Mirror ===&lt;br /&gt;
&lt;br /&gt;
The School of Computer Science&#039;s CSCF has provided us with a secondary mirror machine located in DC. This will limit the downtime of mirror.csclub in the event of an outage affecting the MC machine room.&lt;br /&gt;
&lt;br /&gt;
==== Keepalived ====&lt;br /&gt;
&lt;br /&gt;
Mirror&#039;s IP addresses (129.97.134.71 and 2620:101:f000:4901:c5c::f:1055) have been configured has VRRP address on both machines. Keepalived does the monitoring and selecting of the active node.&lt;br /&gt;
&lt;br /&gt;
Potassium-benzoate has higher priority and will typically be the active node. A node&#039;s priority is reduced when nginx, proftpd or rsync are not running. Potassium-benzoate starts with a score of 100 and mirror-dc starts with a priority of 90 (higher score wins).&lt;br /&gt;
&lt;br /&gt;
When nginx is unavailable (checked w/ curl), the priority is reduced by 20. When proftpd is unavailable (checked with curl), the priority is reduced by 5. When rsync is unavailable (checking with rsync), the priority is reduced by 15.&lt;br /&gt;
&lt;br /&gt;
The Systems Committee should received an email when the nodes swap position.&lt;br /&gt;
&lt;br /&gt;
==== Project synchronization ====&lt;br /&gt;
&lt;br /&gt;
Only potassium-benzoate is configure with merlin. mirror-dc has the software components, but they are probably not update to date nor configured to run correctly.&lt;br /&gt;
&lt;br /&gt;
When a project sync is complete, merlin will kick off a custom script to sync the zfs dataset to the other node. These scripts live in /usr/local/bin and in ~mirror/merlin.&lt;/div&gt;</summary>
		<author><name>A268wang</name></author>
	</entry>
	<entry>
		<id>https://wiki.csclub.uwaterloo.ca/index.php?title=Mirror&amp;diff=4854</id>
		<title>Mirror</title>
		<link rel="alternate" type="text/html" href="https://wiki.csclub.uwaterloo.ca/index.php?title=Mirror&amp;diff=4854"/>
		<updated>2022-08-05T02:37:30Z</updated>

		<summary type="html">&lt;p&gt;A268wang: add temporary update message for merlin-go&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The [https://csclub.uwaterloo.ca Computer Science Club] runs a public mirror ([http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca]) on [[Machine_List#potassium-benzoate|potassium-benzoate]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We are listed on the ResNet &amp;amp;quot;don&#039;t count&amp;amp;quot; list, so downloading from our mirror will not count against one&#039;s ResNet quota.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Software Mirrored ==&lt;br /&gt;
&lt;br /&gt;
A list of current archives (and their respective disk usage) is listed on our mirror&#039;s homepage at [http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
=== Mirroring Requests ===&lt;br /&gt;
&lt;br /&gt;
Requests to mirror a particular distribution or archive should be made to [mailto:syscom@csclub.uwaterloo.ca syscom@csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
== Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Syncing ===&lt;br /&gt;
&lt;br /&gt;
==== Storage ====&lt;br /&gt;
&lt;br /&gt;
All of our projects are stored on one of three zfs zpools. There are 8 drives per array (7 run cscmirror3), configured as raidz2, and there is an additional drive that can be swapped in (in the event of a disk failure).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/mirror/root/.cscmirror1&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;/mirror/root/.cscmirror2&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;/mirror/root/.cscmirror3&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each project is given a filesystem under one of the two pools. Symlinks are created &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt; to point to the correct pool and file system.&lt;br /&gt;
&lt;br /&gt;
==== Merlin ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;**&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039;UPDATE&#039;&#039;&#039;**: merlin.py and the sync scripts are currently being merged together into merlin-go which can be found at &amp;lt;code&amp;gt;/home/mirror-go/merlin&amp;lt;/code&amp;gt;. The current status can be found using &amp;lt;code&amp;gt;systemctl status merlin-go.service&amp;lt;/code&amp;gt; or by going to &amp;lt;code&amp;gt;/home/mirror-go/merlin/cmd/arthur&amp;lt;/code&amp;gt; and running &amp;lt;code&amp;gt;./arthur status&amp;lt;/code&amp;gt;. To force sync a project execute &amp;lt;code&amp;gt;./arthur sync:PROJECT_NAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The synchronization process is run by a Python script called &amp;amp;quot;merlin&amp;amp;quot;, written by a2brenna. The script is stored in &amp;lt;code&amp;gt;~mirror/merlin&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The list of repositories and their configuration (synch frequency, location, etc.) is configured in &amp;lt;code&amp;gt;merlin.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To view the sync status, execute &amp;lt;code&amp;gt;~mirror/merlin/arthur.py status&amp;lt;/code&amp;gt;. To force the sync of a project, execute &amp;lt;code&amp;gt;~mirror/merlin/arthur.py sync:PROJECT_NAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Push Sync =====&lt;br /&gt;
&lt;br /&gt;
Some projects support push syncing via SSH.&lt;br /&gt;
&lt;br /&gt;
We are running a special SSHD instance on mirror.csclub.uwaterloo.ca:22. This instance has been locked down, with the following settings:&lt;br /&gt;
&lt;br /&gt;
* Only SSH key authentication&lt;br /&gt;
* Only users of the &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; group (except &amp;lt;code&amp;gt;mirror&amp;lt;/code&amp;gt;) are allowed to connect&lt;br /&gt;
* X11 Forwarding, TCP Forwarding, Agent Forwarding, User RC and TTY are disabled&lt;br /&gt;
* Users are chrooted to &amp;lt;code&amp;gt;/mirror/merlin&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most projects will connect using the &amp;lt;code&amp;gt;push&amp;lt;/code&amp;gt; user. The SSH authorized keys file is located at &amp;lt;code&amp;gt;/home/push/.ssh/authorized_keys&amp;lt;/code&amp;gt;. An example entry is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
restrict,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command=&amp;quot;arthur sync:ubuntu &amp;gt;/dev/null 2&amp;gt;/dev/null &amp;lt;/dev/null &amp;amp;&amp;quot;,from=&amp;quot;XXX.XXX.XXX.XXX&amp;quot; ssh-rsa ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sync Scripts ====&lt;br /&gt;
&lt;br /&gt;
Our collection of synchronization scripts are located in &amp;lt;code&amp;gt;~mirror/bin&amp;lt;/code&amp;gt;. They currently include:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-apache&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-debian&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-debian-cd&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-gentoo&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-ssh&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;csc-sync-standard&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Most of these scripts take the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;local_dir rsync_host rsync_dir&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== HTTP(s) ===&lt;br /&gt;
&lt;br /&gt;
We use [https://nginx.org nginx] as our webserver.&lt;br /&gt;
&lt;br /&gt;
==== Index ====&lt;br /&gt;
&lt;br /&gt;
An index of the archives we mirror is available at [http://mirror.csclub.uwaterloo.ca mirror.csclub.uwaterloo.ca].&lt;br /&gt;
&lt;br /&gt;
As of Winter 2010, it is now generated by a Python script in &amp;lt;code&amp;gt;~mirror/mirror-index&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;~mirror/mirror-index/make-index&amp;lt;/code&amp;gt; is scheduled in &amp;lt;code&amp;gt;/etc/cron.d/csc-mirror&amp;lt;/code&amp;gt; to be run hourly. The script can be run manually when needed (for example, when the archive list is updated) by running:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sudo -u mirror /home/mirror/mirror-index/make-index.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script will iterate all folders in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;, identify the size of the project using `zfs get -H -o value used $dataset`, where $dataset is calculated from the symlink in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;. The size of all folders is added together to calculate the total folder size (the total size includes hidden projects).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;make-index.py&amp;lt;/code&amp;gt; is configured by means of a [https://yaml.org YAML] file, &amp;lt;code&amp;gt;config.yaml&amp;lt;/code&amp;gt;, in the same directory. Its format is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;yaml&amp;quot;&amp;gt;docroot: /mirror/root&lt;br /&gt;
output: /mirror/root/index.html&lt;br /&gt;
&lt;br /&gt;
exclude:&lt;br /&gt;
   - include&lt;br /&gt;
   - lost+found&lt;br /&gt;
   - pub&lt;br /&gt;
# (...)&lt;br /&gt;
&lt;br /&gt;
directories:&lt;br /&gt;
  apache:&lt;br /&gt;
    site: apache.org&lt;br /&gt;
    url: http://www.apache.org/&lt;br /&gt;
&lt;br /&gt;
  archlinux:&lt;br /&gt;
    site: archlinux.org&lt;br /&gt;
    url: http://www.archlinux.org/&lt;br /&gt;
&lt;br /&gt;
# (...)&amp;lt;/pre&amp;gt;&lt;br /&gt;
The docroot is the directory which is to be scanned; this will probably always be the mirror root from which Apache serves. This is here so that it&#039;s easy to find and alter. For instance, we could change &amp;lt;code&amp;gt;--human-readable&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;--si&amp;lt;/code&amp;gt; if we ever decided that, like hard disk manufacturers, we want sizes to appear larger than they are. &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; defines the file to which the generated index will be written.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;exclude&amp;lt;/code&amp;gt; specifies the list of directories which will not be included in the generated index page (since, by default, all folders are included in the generated index page).&lt;br /&gt;
&lt;br /&gt;
Finally, &amp;lt;code&amp;gt;directories&amp;lt;/code&amp;gt; specifies the information of directories. All directories are listed by default, whether or not they appear in this list - only those under &amp;lt;code&amp;gt;exclude&amp;lt;/code&amp;gt; are ignored. The format is fairly straightforward: simply name the directory and provide a site (the display name in the &amp;amp;quot;Project Site&amp;amp;quot; column) and URL. One caveat here is that YAML does not allow tabs for whitespace. Indent with two spaces to remain consistent with the existing file format, please. Also note that the directory name is case-sensitive, as is always the case on Unix.&lt;br /&gt;
&lt;br /&gt;
Finally, the HTML index file is generated from &amp;lt;code&amp;gt;index.mako&amp;lt;/code&amp;gt;, a Mako template (which is mostly HTML anyhow). If you really can&#039;t figure out how it works, look up the Mako documentation.&lt;br /&gt;
&lt;br /&gt;
=== FTP ===&lt;br /&gt;
&lt;br /&gt;
We use [http://www.proftpd.org/ proftpd] (standalone daemon) as our FTP server.&lt;br /&gt;
&lt;br /&gt;
To increase performance, we disable DNS lookups in &amp;lt;code&amp;gt;proftpd.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;UseReverseDNS           off&lt;br /&gt;
IdentLookups            off&amp;lt;/pre&amp;gt;&lt;br /&gt;
We also limit the amount of CPU/memory resources used (e.g. to minimize [https://en.wikipedia.org/wiki/Globbing Globbing] resources):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;RLimitCPU               session 10&lt;br /&gt;
RLimitMemory            session 4096K&amp;lt;/pre&amp;gt;&lt;br /&gt;
We allow a maximum of 500 concurrent FTP sessions:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;MaxInstances            500&lt;br /&gt;
MaxClients              500&amp;lt;/pre&amp;gt;&lt;br /&gt;
The contents of &amp;lt;code&amp;gt;/mirror/root/include/motd.msg&amp;lt;/code&amp;gt; are displayed when a user connects.&lt;br /&gt;
&lt;br /&gt;
=== rsync ===&lt;br /&gt;
&lt;br /&gt;
We use &amp;lt;code&amp;gt;rsyncd&amp;lt;/code&amp;gt; (standalone daemon).&lt;br /&gt;
&lt;br /&gt;
We disable compression and checksumming in &amp;lt;code&amp;gt;rsyncd.conf&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;dont compress = *&lt;br /&gt;
refuse options = c delete&amp;lt;/pre&amp;gt;&lt;br /&gt;
The contents of &amp;lt;code&amp;gt;/mirror/root/include/motd.msg&amp;lt;/code&amp;gt; are displayed when a user connects.&lt;br /&gt;
&lt;br /&gt;
== Mirror Administration ==&lt;br /&gt;
&lt;br /&gt;
=== Adding a new project ===&lt;br /&gt;
&lt;br /&gt;
# Find the instructions for mirroring the project. Ideally, try to sync directly from the project’s source repository.&lt;br /&gt;
#* Note that some projects provide sync scripts, however we generally won’t use them. We will instead use our custom ones.&lt;br /&gt;
# Create a zfs filesystem to store the project in:&lt;br /&gt;
#* Find the pool with least current disk usage&lt;br /&gt;
#* &amp;lt;code&amp;gt;zfs create cscmirror{1,2,3}/$PROJECT_NAME&amp;lt;/code&amp;gt;&lt;br /&gt;
# Change the folder ownership&lt;br /&gt;
#* &amp;lt;code&amp;gt;chown mirror:mirror /mirror/root/.cscmirror{1,2,3}/$PROJECT_NAME&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create the symlink in &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt;&lt;br /&gt;
#* &amp;lt;code&amp;gt;ln -s .cscmirror{1,2,3}/$PROJECT_NAME $PROJECT_NAME&amp;lt;/code&amp;gt; (&#039;&#039;&#039;NOTE&#039;&#039;&#039;: The symlink must be relative to the &amp;lt;code&amp;gt;/mirror/root&amp;lt;/code&amp;gt; directory. If it isn’t, the symlinks will not work when chrooted)&lt;br /&gt;
# Repeat the above steps on mirror-dc. &amp;lt;code&amp;gt;sudo ssh mirror-dc&amp;lt;/code&amp;gt; on potassium-benzoate&lt;br /&gt;
# Configure the project in merlin (&amp;lt;code&amp;gt;~mirror/merlin/merlin.py&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Select the appropriate sync script (typically &amp;lt;code&amp;gt;csc-sync-standard&amp;lt;/code&amp;gt;) and supply the appropriate parameters&lt;br /&gt;
# Restart merlin: &amp;lt;code&amp;gt;systemctl restart merlin&amp;lt;/code&amp;gt;&lt;br /&gt;
# Configure the project in zfssync.yml (&amp;lt;code&amp;gt;~mirror/merlin/zfssync.yml&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* This will kick off the initial sync&lt;br /&gt;
#* Check &amp;lt;code&amp;gt;~mirror/merlin/logs/$PROJECT_NAME&amp;lt;/code&amp;gt; for errors, &amp;lt;code&amp;gt;~mirror/merlin/logs/transfer.log&amp;lt;/code&amp;gt; for transfer progress&lt;br /&gt;
# Update the mirror index configuration (&amp;lt;code&amp;gt;~mirror/mirror-index/config.yaml&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Add the project to rsync (&amp;lt;code&amp;gt;/etc/rsyncd.conf&amp;lt;/code&amp;gt;)&lt;br /&gt;
#* Restart rsync with &amp;lt;code&amp;gt;systemctl restart rsync&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If push mirroring is available/required, see [[#Push_Sync|Push Sync]].&lt;br /&gt;
&lt;br /&gt;
=== Secondary Mirror ===&lt;br /&gt;
&lt;br /&gt;
The School of Computer Science&#039;s CSCF has provided us with a secondary mirror machine located in DC. This will limit the downtime of mirror.csclub in the event of an outage affecting the MC machine room.&lt;br /&gt;
&lt;br /&gt;
==== Keepalived ====&lt;br /&gt;
&lt;br /&gt;
Mirror&#039;s IP addresses (129.97.134.71 and 2620:101:f000:4901:c5c::f:1055) have been configured has VRRP address on both machines. Keepalived does the monitoring and selecting of the active node.&lt;br /&gt;
&lt;br /&gt;
Potassium-benzoate has higher priority and will typically be the active node. A node&#039;s priority is reduced when nginx, proftpd or rsync are not running. Potassium-benzoate starts with a score of 100 and mirror-dc starts with a priority of 90 (higher score wins).&lt;br /&gt;
&lt;br /&gt;
When nginx is unavailable (checked w/ curl), the priority is reduced by 20. When proftpd is unavailable (checked with curl), the priority is reduced by 5. When rsync is unavailable (checking with rsync), the priority is reduced by 15.&lt;br /&gt;
&lt;br /&gt;
The Systems Committee should received an email when the nodes swap position.&lt;br /&gt;
&lt;br /&gt;
==== Project synchronization ====&lt;br /&gt;
&lt;br /&gt;
Only potassium-benzoate is configure with merlin. mirror-dc has the software components, but they are probably not update to date nor configured to run correctly.&lt;br /&gt;
&lt;br /&gt;
When a project sync is complete, merlin will kick off a custom script to sync the zfs dataset to the other node. These scripts live in /usr/local/bin and in ~mirror/merlin.&lt;/div&gt;</summary>
		<author><name>A268wang</name></author>
	</entry>
	<entry>
		<id>https://wiki.csclub.uwaterloo.ca/index.php?title=New_CSC_Machine&amp;diff=4826</id>
		<title>New CSC Machine</title>
		<link rel="alternate" type="text/html" href="https://wiki.csclub.uwaterloo.ca/index.php?title=New_CSC_Machine&amp;diff=4826"/>
		<updated>2022-06-25T02:13:20Z</updated>

		<summary type="html">&lt;p&gt;A268wang: fix ipv6 static address&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Firmware Updates =&lt;br /&gt;
&lt;br /&gt;
Vendors such as Dell provide firmware updates that should be applied before putting new machines into service. Even if the machine&#039;s warranty has expired, security updates are still made available.&lt;br /&gt;
&lt;br /&gt;
It is recommended to use the following sequence when updating firmware on the Dell PowerEdge servers ([https://downloads.dell.com/solutions/general-solution-resources/White%20Papers/Recommended%20Workflow%20for%20Performing%20Firmware%20Updates%20on%20PowerEdge%20Servers.pdf]):&lt;br /&gt;
&lt;br /&gt;
# iDRAC&lt;br /&gt;
# Lifecycle Controller&lt;br /&gt;
# BIOS&lt;br /&gt;
# Diagnostics&lt;br /&gt;
# OS Driver Pack&lt;br /&gt;
# RAID&lt;br /&gt;
# NIC&lt;br /&gt;
# PSU&lt;br /&gt;
# CPLD&lt;br /&gt;
# Other update&lt;br /&gt;
&lt;br /&gt;
= Booting =&lt;br /&gt;
&lt;br /&gt;
* Put the TFTP image in place (if dist-arch pair installed before, you may skip this).&lt;br /&gt;
e.g. extract http://mirror.csclub.uwaterloo.ca/ubuntu/dists/oneiric/main/installer-amd64/current/images/netboot/netboot.tar.gz to caffeine:/srv/tftp/oneiric-amd64&lt;br /&gt;
&lt;br /&gt;
* Force network boot in the BIOS. This may be called &amp;quot;Legacy LAN&amp;quot; or other such cryptic things. If this doesn&#039;t work, boot from CD or USB instead.&lt;br /&gt;
&lt;br /&gt;
It is preferred to use the &amp;quot;alternate&amp;quot; Ubuntu installer image, based on debian-installer, instead of the Ubiquity installer. This installer supports software RAID and LVM out of the box, and will generally make your life easier. If installing Debian, this is the usual installer, so don&#039;t sweat it.&lt;br /&gt;
&lt;br /&gt;
* Most of our newer servers (e.g. PowerEdge R815) need non-free firmware in order to boot. This means that if you are using a new netboot image, it is highly recommended to include the entire non-free firmware bundle in the boot image. See [https://wiki.debian.org/DebianInstaller/NetbootFirmware] for more information.&lt;br /&gt;
&lt;br /&gt;
= Installing =&lt;br /&gt;
&lt;br /&gt;
== debian-installer ==&lt;br /&gt;
&lt;br /&gt;
At least in expert mode, you can choose a custom mirror (top of the countries list) and give the path for mirror directly. This will make installation super-fast compared to installing from anywhere else.&lt;br /&gt;
&lt;br /&gt;
Please install to LVM volumes, as this is our standard configuration on all machines where possible. It allows more flexible partitioning across available volumes. Since GRUB 2, even /boot may be on LVM; this is the preferred configuration for simplicity, except when legacy partitioning setups make this inconvenient.&lt;br /&gt;
&lt;br /&gt;
You may enable unattended upgrades, but do not enable Canonical&#039;s remote management service or any such nonsense. This is mostly a straightforward Debian/Ubuntu install.&lt;br /&gt;
&lt;br /&gt;
== Ubiquity ==&lt;br /&gt;
&lt;br /&gt;
Ubiquity is the Ubuntu GUI installer. For it to have lvm support, run:&lt;br /&gt;
 apt install lvm2&lt;br /&gt;
&lt;br /&gt;
If you still can&#039;t see the partitions (even if lvscan sees them, but no devices exist), run &amp;lt;tt&amp;gt;vgscan&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;vgchange -ay&amp;lt;/tt&amp;gt; as root. Now the partitioner should be able to see them. We prefer to use LVM for partitions. Since GRUB 2, even /boot may be on LVM; this is the preferred configuration for simplicity, except when legacy partitioning setups make this inconvenient.&lt;br /&gt;
&lt;br /&gt;
After installing with Ubiquity, you must also add LVM support to the newly installed system, and in particular its initramfs.&lt;br /&gt;
&lt;br /&gt;
 mount /dev/vg0/root /mnt&lt;br /&gt;
 mount /dev/sda1 /mnt/boot&lt;br /&gt;
 chroot /mnt&lt;br /&gt;
 apt install lvm2&lt;br /&gt;
&lt;br /&gt;
You should see an update-initramfs update. Reboot.&lt;br /&gt;
&lt;br /&gt;
= After Installing =&lt;br /&gt;
&lt;br /&gt;
Add the machine&#039;s name to ~git/public/hosts.git, and run the ansible playbook (https://git.uwaterloo.ca/csc/playbooks/blob/master/update-hosts.yml) to distribute the updated hosts file to all machines.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== apt ==&lt;br /&gt;
&lt;br /&gt;
If you did not during installation, change all references in &amp;lt;tt&amp;gt;/etc/apt/sources.list&amp;lt;/tt&amp;gt; to use &amp;lt;tt&amp;gt;mirror&amp;lt;/tt&amp;gt; instead of the usual mirrors.&lt;br /&gt;
&lt;br /&gt;
Also add support for the CSC packages. Add the following to &amp;lt;tt&amp;gt;/etc/apt/sources.list.d/csclub.list&amp;lt;/tt&amp;gt; (or copy from another host):&lt;br /&gt;
&lt;br /&gt;
 deb http://debian.csclub.uwaterloo.ca/ &amp;lt;distribution&amp;gt; main contrib non-free&lt;br /&gt;
 deb-src http://debian.csclub.uwaterloo.ca/ &amp;lt;distribution&amp;gt; main contrib non-free&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also need the CSC archive signing key (if &amp;lt;tt&amp;gt;curl&amp;lt;/tt&amp;gt; is not installed, install it).&lt;br /&gt;
 curl -s http://debian.csclub.uwaterloo.ca/csclub.asc | apt-key add -&lt;br /&gt;
&lt;br /&gt;
You should now run &amp;lt;tt&amp;gt;apt-get update&amp;lt;/tt&amp;gt; to reflect these changes.&lt;br /&gt;
&lt;br /&gt;
For unattended upgrades in the future, install the &amp;lt;tt&amp;gt;unattended-upgrades&amp;lt;/tt&amp;gt; package and copy &amp;lt;tt&amp;gt;/etc/apt/apt.conf&amp;lt;/tt&amp;gt; from another host.&lt;br /&gt;
&lt;br /&gt;
== network ==&lt;br /&gt;
&lt;br /&gt;
Note that inapt current uninstalls NetworkManager, which is what Ubuntu uses by default to configure the network. Once this completes, open &amp;lt;tt&amp;gt;/etc/network/interfaces&amp;lt;/tt&amp;gt; and set up a static networking configuration (otherwise, networking will not come back up on reboot). It should look something like this (NOTE: csc-storage is only for servers in the machine room):&lt;br /&gt;
&lt;br /&gt;
 # This file describes the network interfaces available on your system&lt;br /&gt;
 # and how to activate them. For more information, see interfaces(5).&lt;br /&gt;
 &lt;br /&gt;
 # The loopback network interface&lt;br /&gt;
 auto lo&lt;br /&gt;
 iface lo inet loopback&lt;br /&gt;
 &lt;br /&gt;
 # The primary network interface&lt;br /&gt;
 auto eth0&lt;br /&gt;
 iface eth0 inet static&lt;br /&gt;
         address 129.97.134.xxx&lt;br /&gt;
         netmask 255.255.255.0&lt;br /&gt;
         gateway 129.97.134.1&lt;br /&gt;
 &lt;br /&gt;
 iface eth0 inet6 static&lt;br /&gt;
         address 2620:101:f000:4901:c5c::XXXX&lt;br /&gt;
         netmask 64&lt;br /&gt;
         gateway 2620:101:f000:4901::1&lt;br /&gt;
  &lt;br /&gt;
  # csc-storage&lt;br /&gt;
  auto eth0.530&lt;br /&gt;
  iface eth0.530 inet static&lt;br /&gt;
         address 172.19.168.xxx&lt;br /&gt;
         netmask 255.255.255.224&lt;br /&gt;
         vlan-raw-device eth0&lt;br /&gt;
  &lt;br /&gt;
  iface eth0.530 inet6 static&lt;br /&gt;
         address fd74:6b6a:8eca:4903:c5c::xx&lt;br /&gt;
         netmask 64&lt;br /&gt;
&lt;br /&gt;
== Keys ==&lt;br /&gt;
&lt;br /&gt;
If this is a reinstall of an existing host, copy back the SSH host keys and &amp;lt;tt&amp;gt;/etc/krb5.keytab&amp;lt;/tt&amp;gt; from its former incarnation. Otherwise, create a new Kerberos principal and copy the keytab over, as follows (run from the host in question):&lt;br /&gt;
 kadmin -p sysadmin/admin   # or any other admin principal; the password for this one is the usual root password&lt;br /&gt;
 addprinc -randkey host/[hostname].csclub.uwaterloo.ca&lt;br /&gt;
 ktadd host/[hostname].csclub.uwaterloo.ca&lt;br /&gt;
&lt;br /&gt;
This will generate a new principal (you can skip this step if one already exists) and add it to the local Kerberos keytab.&lt;br /&gt;
&lt;br /&gt;
Also copy &amp;lt;tt&amp;gt;/etc/ssl/certs/GlobalSign_Intermediate_Root_SHA256_G2.pem&amp;lt;/tt&amp;gt; from another host, as many of our services use a certificate issued by this CA.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
The following config files are needed to work in the CSC environment (examples given below for an office terminal; perhaps refer to another host if preferred).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/etc/nsswitch.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 # /etc/nsswitch.conf&lt;br /&gt;
 #&lt;br /&gt;
 # Example configuration of GNU Name Service Switch functionality.&lt;br /&gt;
 # If you have the `glibc-doc-reference&#039; and `info&#039; packages installed, try:&lt;br /&gt;
 # `info libc &amp;quot;Name Service Switch&amp;quot;&#039; for information about this file.&lt;br /&gt;
 &lt;br /&gt;
 passwd:         files ldap&lt;br /&gt;
 group:          files ldap&lt;br /&gt;
 shadow:         files ldap&lt;br /&gt;
 sudoers:        files ldap&lt;br /&gt;
 &lt;br /&gt;
 hosts:          files dns&lt;br /&gt;
 networks:       files&lt;br /&gt;
 &lt;br /&gt;
 protocols:      db files&lt;br /&gt;
 services:       db files&lt;br /&gt;
 ethers:         db files&lt;br /&gt;
 rpc:            db files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/etc/ldap/ldap.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 # $OpenLDAP: pkg/ldap/libraries/libldap/ldap.conf,v 1.9 2000/09/04 19:57:01 kurt Exp $&lt;br /&gt;
 #&lt;br /&gt;
 # LDAP Defaults&lt;br /&gt;
 #&lt;br /&gt;
 &lt;br /&gt;
 # See ldap.conf(5) for details&lt;br /&gt;
 # This file should be world readable but not world writable.&lt;br /&gt;
 &lt;br /&gt;
 BASE   dc=csclub, dc=uwaterloo, dc=ca&lt;br /&gt;
 URI     ldap://ldap1.csclub.uwaterloo.ca ldap://ldap2.csclub.uwaterloo.ca&lt;br /&gt;
 &lt;br /&gt;
 SIZELIMIT      0&lt;br /&gt;
 &lt;br /&gt;
 TLS_CACERT      /etc/ssl/certs/GlobalSign_Intermediate_Root_SHA256_G2.pem&lt;br /&gt;
 TLS_CACERTFILE /etc/ssl/certs/GlobalSign_Intermediate_Root_SHA256_G2.pem&lt;br /&gt;
 &lt;br /&gt;
 SUDOERS_BASE    ou=SUDOers,dc=csclub,dc=uwaterloo,dc=ca&lt;br /&gt;
&lt;br /&gt;
Also make &amp;lt;tt&amp;gt;/etc/sudo-ldap.conf&amp;lt;/tt&amp;gt; a symlink to the above. On debian, install &amp;lt;tt&amp;gt;sudo-ldap&amp;lt;/tt&amp;gt; package too.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/etc/nslcd.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 # /etc/nslcd.conf&lt;br /&gt;
 # nslcd configuration file. See nslcd.conf(5)&lt;br /&gt;
 # for details.&lt;br /&gt;
 &lt;br /&gt;
 # The user and group nslcd should run as.&lt;br /&gt;
 uid nslcd&lt;br /&gt;
 gid nslcd&lt;br /&gt;
 &lt;br /&gt;
 # The location at which the LDAP server(s) should be reachable.&lt;br /&gt;
 uri ldap://ldap1.csclub.uwaterloo.ca&lt;br /&gt;
 uri ldap://ldap2.csclub.uwaterloo.ca&lt;br /&gt;
 &lt;br /&gt;
 # The search base that will be used for all queries.&lt;br /&gt;
 base dc=csclub,dc=uwaterloo,dc=ca&lt;br /&gt;
 &lt;br /&gt;
 # use the uniqueMember attribute for group membership&lt;br /&gt;
 # (not applicable on Debian squeeze)&lt;br /&gt;
 map group member uniqueMember&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/etc/krb5.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
 [libdefaults]&lt;br /&gt;
         default_realm = CSCLUB.UWATERLOO.CA&lt;br /&gt;
         forwardable = true&lt;br /&gt;
         proxiable = true&lt;br /&gt;
         dns_lookup_kdc = false&lt;br /&gt;
         dns_lookup_realm = false&lt;br /&gt;
 &lt;br /&gt;
 [realms]&lt;br /&gt;
         CSCLUB.UWATERLOO.CA = {&lt;br /&gt;
                 kdc = kdc1.csclub.uwaterloo.ca&lt;br /&gt;
                 kdc = kdc2.csclub.uwaterloo.ca&lt;br /&gt;
                 admin_server = kadmin.csclub.uwaterloo.ca&lt;br /&gt;
         }&lt;br /&gt;
 (rest omitted for brevity)&lt;br /&gt;
&lt;br /&gt;
Update: &amp;lt;tt&amp;gt;allow_weak_crypto&amp;lt;/tt&amp;gt; is basically a no-op in recent Kerberos versions - but this is not a problem as any linux kernel with version &amp;gt;= 2.6.38.2 can use any cipher available to the kernel to grab tickets from the KDC for the purpose of NFS sec=krb5. Notably, this means you can use ciphersuites less craptastic than des-cbc-crc (the only one that used to work prior to this kernel revision) for NFS sec=krb5 mounts. Therefore, &amp;lt;tt&amp;gt;allow_weak_crypto&amp;lt;/tt&amp;gt; has been removed from /etc/krb5.conf on all our machines.&lt;br /&gt;
&lt;br /&gt;
Furthermore, the lines &amp;lt;tt&amp;gt;dns_lookup_kdc&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;dns_lookup_realm&amp;lt;/tt&amp;gt; have been added - they are needed to stop the KDC from throwing its arms in the air and giving up if IST&#039;s DNS servers ever explode - an event that has happened in the recent past far more often than I&#039;d like it to.&lt;br /&gt;
&lt;br /&gt;
Notably, &amp;lt;tt&amp;gt;allow_weak_crypto&amp;lt;/tt&amp;gt; is currently needed to mount &amp;lt;tt&amp;gt;/users&amp;lt;/tt&amp;gt; (/music and &amp;lt;tt&amp;gt;/scratch&amp;lt;/tt&amp;gt; is sec=sys and thus will always mount, even when krb5 is down and/or broken). Otherwise, you will get a mysterious &amp;quot;permission denied&amp;quot; error (even though the server claims to have authenticated the mount successfully).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/etc/pam.d/common-account&amp;lt;/tt&amp;gt;&lt;br /&gt;
 #&lt;br /&gt;
 # /etc/pam.d/common-account - authorization settings common to all services&lt;br /&gt;
 #&lt;br /&gt;
 &lt;br /&gt;
 # here are the per-package modules (the &amp;quot;Primary&amp;quot; block)&lt;br /&gt;
 account        [success=1 new_authtok_reqd=done default=ignore]        pam_unix.so &lt;br /&gt;
 # here&#039;s the fallback if no module succeeds&lt;br /&gt;
 account        requisite                       pam_deny.so&lt;br /&gt;
 # prime the stack with a positive return value if there isn&#039;t one already;&lt;br /&gt;
 # this avoids us returning an error just because nothing sets a success code&lt;br /&gt;
 # since the modules above will each just jump around&lt;br /&gt;
 account        required                        pam_permit.so&lt;br /&gt;
 # and here are more per-package modules (the &amp;quot;Additional&amp;quot; block)&lt;br /&gt;
 account        required                        pam_krb5.so minimum_uid=10000&lt;br /&gt;
 # end of pam-auth-update config&lt;br /&gt;
 &lt;br /&gt;
 # Make sure the user is up to date. System accounts and syscom are exempt.&lt;br /&gt;
 account [success=2 default=ignore]     pam_succeed_if.so quiet uid &amp;lt; 10000&lt;br /&gt;
 account [success=1 default=ignore]     pam_succeed_if.so quiet user ingroup syscom&lt;br /&gt;
 account required        pam_csc.so&lt;br /&gt;
&lt;br /&gt;
This file is notably different on syscom-only hosts. Look at an existing syscom-only host to see the difference.&lt;br /&gt;
&lt;br /&gt;
Alter &amp;lt;tt&amp;gt;/etc/default/nfs-common&amp;lt;/tt&amp;gt; to enable &amp;lt;tt&amp;gt;statd&amp;lt;/tt&amp;gt;, and more importantly &amp;lt;tt&amp;gt;gssd&amp;lt;/tt&amp;gt; (needed for Kerberos NFS mounts). Start both daemons manually for now.&lt;br /&gt;
&lt;br /&gt;
Add &amp;lt;tt&amp;gt;/users&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;/music&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/scratch&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;/etc/fstab&amp;lt;/tt&amp;gt; (as appropriate for the machine&#039;s role), make their mount points and mount them. Note that &amp;lt;tt&amp;gt;/music&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/scratch&amp;lt;/tt&amp;gt; are sec=sys whereas /users is sec=krb5 (with exceptions granted on a case-by-case basis for servers only, office terminals are always sec=krb5 for security reasons).&lt;br /&gt;
&lt;br /&gt;
To allow single sign-on as &amp;lt;tt&amp;gt;root&amp;lt;/tt&amp;gt; (primarily useful for pushing files to all machines simultaneously), put the following in &amp;lt;tt&amp;gt;/root/.k5login&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 sysadmin/admin@CSCLUB.UWATERLOO.CA&lt;br /&gt;
&lt;br /&gt;
Also copy the following files from another CSC host:&lt;br /&gt;
* &amp;lt;tt&amp;gt;/etc/ssh/ssh_config&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;/etc/ssh/sshd_config&amp;lt;/tt&amp;gt; (for single sign-on)&lt;br /&gt;
* &amp;lt;tt&amp;gt;/etc/ssh/ssh_known_hosts&amp;lt;/tt&amp;gt; (to remove hostkey warnings within our network)&lt;br /&gt;
* &amp;lt;tt&amp;gt;/etc/hosts&amp;lt;/tt&amp;gt; (for host tab completion and emergency name resolution)&lt;br /&gt;
* &amp;lt;tt&amp;gt;/etc/resolv.conf&amp;lt;/tt&amp;gt; (to use IST&#039;s nameservers and search csclub/uwaterloo domains. Only required if you are not using &amp;lt;tt&amp;gt;/etc/network/interfaces&amp;lt;/tt&amp;gt; to configure DNS)&lt;br /&gt;
&lt;br /&gt;
=== Display Manager ===&lt;br /&gt;
&lt;br /&gt;
LightDM (with unity-greeter) is the current display manager of choice for CSC office terminals. Copy &amp;lt;tt&amp;gt;/etc/lightdm/lightdm.conf&amp;lt;/tt&amp;gt; from another CSC machine to configure it properly. If kdm or another display manager gets installed, please ensure that you continue to choose LightDM as the default display manager.&lt;br /&gt;
&lt;br /&gt;
Please leave AccountsService enabled, as LightDM and certain parts of the GNOME packages work better when it is available.&lt;br /&gt;
&lt;br /&gt;
The Unity greeter configuration is now in gsettings. We currently have a novelty wallpaper configured. To configure this, copy &amp;lt;tt&amp;gt;/usr/local/share/backgrounds/tarkin.png&amp;lt;/tt&amp;gt; from another machine and run:&lt;br /&gt;
&lt;br /&gt;
 sudo -u lightdm dbus-launch gsettings set com.canonical.unity-greeter background /usr/local/share/backgrounds/tarkin.png&lt;br /&gt;
&lt;br /&gt;
=== User-Defined Session ===&lt;br /&gt;
&lt;br /&gt;
For some reason, ubuntu does not install a session file for a session that just launches whatever&#039;s in the user&#039;s ~/.xsession. To fix this, put the following into &amp;lt;tt&amp;gt;/usr/share/xsessions/xsession.desktop&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 [Desktop Entry]&lt;br /&gt;
 Name=User-defined session&lt;br /&gt;
 Exec=/etc/X11/Xsession&lt;br /&gt;
&lt;br /&gt;
=== Audio ===&lt;br /&gt;
&lt;br /&gt;
On an office terminal, copy &amp;lt;tt&amp;gt;/etc/pulse/default.pa&amp;lt;/tt&amp;gt; from another office terminal.&lt;br /&gt;
&lt;br /&gt;
If this is to be the machine that actually plays audio (currently &amp;lt;tt&amp;gt;nullsleep&amp;lt;/tt&amp;gt;), the setup is slightly more complicated. You&#039;ll need to set up MPD and PulseAudio to receive connections, and store the PulseAudio cookie in &amp;lt;tt&amp;gt;~audio&amp;lt;/tt&amp;gt;, with appropriate permissions so that only the &amp;lt;tt&amp;gt;audio&amp;lt;/tt&amp;gt; group can access it. If this is a new audio machine, you&#039;ll also need to change &amp;lt;tt&amp;gt;default.pa&amp;lt;/tt&amp;gt; on all office terminals to point to it.&lt;br /&gt;
&lt;br /&gt;
=== Tweaks ===&lt;br /&gt;
&lt;br /&gt;
On Ubuntu precise, even when &amp;lt;tt&amp;gt;gnome-keyring&amp;lt;/tt&amp;gt; is uninstalled, it leaves a config file behind that causes error messages. Remove &amp;lt;tt&amp;gt;/etc/pkcs11/modules/gnome-keyring-module&amp;lt;/tt&amp;gt; to fix this.&lt;br /&gt;
&lt;br /&gt;
On Ubuntu saucy or newer, edit &amp;lt;tt&amp;gt;/etc/sysctl.d/10-magic-sysrq&amp;lt;/tt&amp;gt; at change the value 244.&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
&lt;br /&gt;
You probably already created the host in the University IPAM system beforehand. If not, please do so.&lt;br /&gt;
&lt;br /&gt;
Please also add the host to the [[Machine List]] here on the Wiki, and to &amp;lt;tt&amp;gt;/users/syscom/csc-machines&amp;lt;/tt&amp;gt; (and &amp;lt;tt&amp;gt;csc-office-machines&amp;lt;/tt&amp;gt;, if applicable).&lt;br /&gt;
&lt;br /&gt;
== Munin (System Monitoring) ==&lt;br /&gt;
&lt;br /&gt;
If the new machine is not a container, you probably want to have it participate in the Munin cluster. Run &amp;lt;tt&amp;gt;apt-get install munin-node&amp;lt;/tt&amp;gt; to install the monitoring client, then&lt;br /&gt;
edit the file /etc/munin/munin-node.conf. Look for a line that says &amp;lt;tt&amp;gt;allow ^127\.0\.0\.1$&amp;lt;/tt&amp;gt; and add the following on a new line immediately below it:&lt;br /&gt;
&amp;lt;tt&amp;gt;allow ^129\.97\.134\.51$&amp;lt;/tt&amp;gt; (this is the IP address for munin.csclub). Save the file, then &amp;lt;tt&amp;gt;/etc/init.d/munin-node restart&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;update-rc.d munin-node defaults&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Then, ssh into munin.csclub and edit the file /etc/munin/munin.conf and add the following lines to the end:&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[NEW-MACHINE-NAME.csclub] &amp;lt;br/&amp;gt;&lt;br /&gt;
addr 129.97.134.### &amp;lt;br /&amp;gt;&lt;br /&gt;
use_node_name yes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= New Distribution =&lt;br /&gt;
&lt;br /&gt;
If you&#039;re adding a new distribution, there a couple of steps you&#039;ll need to take in updating the CSClub Debian repository on [[Machine_List#sodium_benzoate|sodium-benzoate/mirror]]. &lt;br /&gt;
&lt;br /&gt;
The steps to add a new Debian release (in the examples, jessie) is as follows, modify as necessary:&lt;br /&gt;
&lt;br /&gt;
=== Step 0: Create a GPG key ===&lt;br /&gt;
&lt;br /&gt;
Use &amp;quot;gpg --gen-key&amp;quot; or something like that. Skip this if you already have one.&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Add to Uploaders ===&lt;br /&gt;
&lt;br /&gt;
The /srv/debian/conf/uploaders file on mirror contains the list of people who can upload. Add your GPG key id to this file.  Use &amp;quot;gpg --list-secret-keys&amp;quot; to find out the key ID. You also need to import your key into the mirror&#039;s gpg homedir as follows:&lt;br /&gt;
&lt;br /&gt;
 gpg --export $KEYID | sudo env GNUPGHOME=/srv/debian/gpg gpg --import&lt;br /&gt;
&lt;br /&gt;
You only need to do this step once.&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Add Distro ===&lt;br /&gt;
&lt;br /&gt;
Add a new section to /srv/debian/conf/distributions:&lt;br /&gt;
&lt;br /&gt;
 Origin: CSC&lt;br /&gt;
 Label: Debian&lt;br /&gt;
 Codename: &#039;&#039;&#039;jessie&#039;&#039;&#039;&lt;br /&gt;
 Architectures: alpha amd64 i386 mips mipsel sparc powerpc armel source&lt;br /&gt;
 Components: main contrib non-free&lt;br /&gt;
 Uploaders: uploaders&lt;br /&gt;
 Update: dell chrome&lt;br /&gt;
 SignWith: yes&lt;br /&gt;
 Log: &#039;&#039;&#039;jessie&#039;&#039;&#039;.log&lt;br /&gt;
  --changes notifier&lt;br /&gt;
&lt;br /&gt;
And update the &#039;&#039;&#039;Allow&#039;&#039;&#039; line in /srv/debian/conf/incoming:&lt;br /&gt;
&lt;br /&gt;
 Allow: &#039;&#039;&#039;jessie&amp;gt;jessie&#039;&#039;&#039; oldstable&amp;gt;squeeze stable&amp;gt;wheezy lucid&amp;gt;lucid maverick&amp;gt;maverick oneiric&amp;gt;oneiric precise&amp;gt;precise quantal&amp;gt;quantal&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Update from Sources ===&lt;br /&gt;
&lt;br /&gt;
Run:&lt;br /&gt;
&lt;br /&gt;
 sudo env GNUPGHOME=/srv/debian/gpg /srv/debian/bin/rrr-update&lt;br /&gt;
&lt;br /&gt;
If all went well you should see the new distribution listed at http://debian.csclub.uwaterloo.ca/dists/&lt;br /&gt;
&lt;br /&gt;
=== Step 4: CSC Packages ===&lt;br /&gt;
&lt;br /&gt;
Now that we&#039;ve got our new distribution set up we need to generate our packages and have them uploaded. Namely, ceo and libpam-csc. For libpam-csc:&lt;br /&gt;
&lt;br /&gt;
Get the package:&lt;br /&gt;
&lt;br /&gt;
 git clone https://git.csclub.uwaterloo.ca/public/libpam-csc.git&lt;br /&gt;
 cd libpam-csc&lt;br /&gt;
&lt;br /&gt;
Update change log:&lt;br /&gt;
&lt;br /&gt;
 EMAIL=[you]@csclub.uwaterloo.ca NAME=&amp;quot;Your Name&amp;quot; dch -i&lt;br /&gt;
&lt;br /&gt;
Update as necessary, i.e:&lt;br /&gt;
&lt;br /&gt;
 libpam-csc (1.10&#039;&#039;&#039;jessie0&#039;&#039;&#039;) &#039;&#039;&#039;jessie&#039;&#039;&#039;; urgency=low&lt;br /&gt;
 &lt;br /&gt;
   * Packaging for jessie.&lt;br /&gt;
 &lt;br /&gt;
  -- Your Name &amp;lt;[you]@csclub.uwaterloo.ca&amp;gt;  Thu, 10 Oct 2013 22:08:48 -0400&lt;br /&gt;
&lt;br /&gt;
Build! (You may need to install various dependencies, which it will yell at you if you don&#039;t have.)&lt;br /&gt;
&lt;br /&gt;
 debuild -k&#039;&#039;&#039;YOURKEYID&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Yay, it built now let&#039;s upload it to the repo. The build process which create a PACKAGE.changes file in the parent directory (replace PACKAGE with the actual package name).&lt;br /&gt;
&lt;br /&gt;
Copy the dupload file from corn-syrup and dupload:&lt;br /&gt;
&lt;br /&gt;
 mv /etc/dupload /etc/dupload.bak&lt;br /&gt;
 scp corn-syrup:/etc/dupload /etc/dupload&lt;br /&gt;
 dupload libpam-csc_1.10jessie0_amd64.changes&lt;br /&gt;
&lt;br /&gt;
Finally, log into mirror and type &amp;quot;sudo /srv/debian/bin/rrr-incoming&amp;quot;. This is supposed to happen once every few minutes however it is always faster to run it manually.&lt;br /&gt;
&lt;br /&gt;
And you&#039;re done. For CEO, see https://git.csclub.uwaterloo.ca/public/pyceo/src/branch/master/PACKAGING.md&lt;/div&gt;</summary>
		<author><name>A268wang</name></author>
	</entry>
	<entry>
		<id>https://wiki.csclub.uwaterloo.ca/index.php?title=MEF_Guide&amp;diff=4581</id>
		<title>MEF Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.csclub.uwaterloo.ca/index.php?title=MEF_Guide&amp;diff=4581"/>
		<updated>2021-11-15T03:40:25Z</updated>

		<summary type="html">&lt;p&gt;A268wang: fix url&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Website: http://mef.uwaterloo.ca/&lt;br /&gt;
&lt;br /&gt;
==Beginning of the term==&lt;br /&gt;
&lt;br /&gt;
It&#039;s wise to start thinking about proposals at the start of term (or even before the term starts). The due date for proposals is typically 2.5 months into the term.&lt;br /&gt;
&lt;br /&gt;
==Writing up the proposal==&lt;br /&gt;
&lt;br /&gt;
* MEF seems to like us getting high-quality components from respectable vendors (e.g. HP).&lt;br /&gt;
* MEF wants us to do our research. This means that we should be able to clearly justify why we need exactly what we&#039;ve asked for. In the past they have indicated that we didn&#039;t give enough explanation as to why we needed something.&lt;br /&gt;
* Make sure to justify how the project/request falls under MEF&#039;s mandate. Specifically, it should somehow benefit undergraduate education.&lt;br /&gt;
* Talk to MathSoc in advance about the proposal. The intersection of MathSoc and MEF is generally large, and they tend to hold sway on the MEF council.&lt;br /&gt;
&lt;br /&gt;
==What MEF likes to fund==&lt;br /&gt;
* Textbooks; note that MEF doesn&#039;t like funding programming language manuals/guides (unless they are obscure/special).&lt;br /&gt;
* Talks; we need to have specific speakers lined up; we can&#039;t just ask for &amp;quot;$X for random speakers&amp;quot;.&lt;br /&gt;
* Hardware; as long as we can justify the usefulness of the purchase, they generally seem open to fund it; here&#039;s some good reasons:&lt;br /&gt;
** Existing hardware is failing (e.g. mirror, caffeine)&lt;br /&gt;
** Existing hardware is inadequate (e.g. gigabit switch)&lt;br /&gt;
&lt;br /&gt;
==Presenting at the funding council meeting==&lt;br /&gt;
&lt;br /&gt;
* MEF wants professional presentations.&lt;br /&gt;
* Most people prepare slide shows and we should too, if possible.&lt;br /&gt;
* Holden should never present to MEF - he&#039;s far too sketchy.&lt;br /&gt;
&lt;br /&gt;
[[Category:MEF]]&lt;br /&gt;
[[Category:Guides]]&lt;/div&gt;</summary>
		<author><name>A268wang</name></author>
	</entry>
</feed>